The following fixes the bootstrap-debug miscompare caused by STV where we ended up with chain-to-scalar copies just because of debug uses. Instead we have to avoid that, eventually substituting into debug uses or resetting debug stmts when there are reaching defs from both inside and outside of the chain (since we rename all in-chain defs).
Bootstrapped on i686-linux-gnu (with a setup previously reproducing the miscompare). Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. OK for trunk? Thanks, Richard. 2019-08-29 Richard Biener <rguent...@suse.de> PR bootstrap/91580 * config/i386/i386-features.c (general_scalar_chain::convert_insn): Do not emit scalar copies for debug-insns, instead replace their uses with the reg copy used in the chain or reset them if there is a reaching definition outside of the chain as well. Index: gcc/config/i386/i386-features.c =================================================================== --- gcc/config/i386/i386-features.c (revision 274991) +++ gcc/config/i386/i386-features.c (working copy) @@ -880,18 +880,52 @@ general_scalar_chain::convert_op (rtx *o void general_scalar_chain::convert_insn (rtx_insn *insn) { - /* Generate copies for out-of-chain uses of defs. */ + /* Generate copies for out-of-chain uses of defs and adjust debug uses. */ for (df_ref ref = DF_INSN_DEFS (insn); ref; ref = DF_REF_NEXT_LOC (ref)) if (bitmap_bit_p (defs_conv, DF_REF_REGNO (ref))) { df_link *use; for (use = DF_REF_CHAIN (ref); use; use = use->next) - if (DF_REF_REG_MEM_P (use->ref) - || !bitmap_bit_p (insns, DF_REF_INSN_UID (use->ref))) + if (NONDEBUG_INSN_P (DF_REF_INSN (use->ref)) + && (DF_REF_REG_MEM_P (use->ref) + || !bitmap_bit_p (insns, DF_REF_INSN_UID (use->ref)))) break; if (use) convert_reg (insn, DF_REF_REG (ref), *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)])); + else + { + /* If we generated a scalar copy we can leave debug-insns + as-is, if not, we have to adjust them. */ + auto_vec<rtx_insn *, 5> to_reset_debug_insns; + for (use = DF_REF_CHAIN (ref); use; use = use->next) + if (DEBUG_INSN_P (DF_REF_INSN (use->ref))) + { + rtx_insn *debug_insn = DF_REF_INSN (use->ref); + /* If there's a reaching definition outside of the + chain we have to reset. */ + df_link *def; + for (def = DF_REF_CHAIN (use->ref); def; def = def->next) + if (!bitmap_bit_p (insns, DF_REF_INSN_UID (def->ref))) + break; + if (def) + to_reset_debug_insns.safe_push (debug_insn); + else + { + *DF_REF_REAL_LOC (use->ref) + = *defs_map.get (regno_reg_rtx [DF_REF_REGNO (ref)]); + df_insn_rescan (debug_insn); + } + } + /* Have to do the reset outside of the DF_CHAIN walk to not + disrupt it. */ + while (!to_reset_debug_insns.is_empty ()) + { + rtx_insn *debug_insn = to_reset_debug_insns.pop (); + INSN_VAR_LOCATION_LOC (debug_insn) = gen_rtx_UNKNOWN_VAR_LOC (); + df_insn_rescan_debug_internal (debug_insn); + } + } } /* Replace uses in this insn with the defs we use in the chain. */