On Tue, Nov 29, 2016 at 8:41 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > The x86_64 stv pass uses PUT_MODE to change REGs and MEMs in place to affect > all setters and users, but that is undesirable in debug insns which are > intentionally ignored during the analysis and we should keep using correct > modes (TImode) instead of the new one (V1TImode). > > The current fix_debug_reg_uses implementation just assumes such a pseudo > can appear only directly in the VAR_LOCATION's second operand, but it can of > course appear anywhere in the expression, the whole expression doesn't have > to be TImode either (e.g. on the testcase it is a QImode comparison of > originally TImode pseudo with CONST_INT, which stv incorrectly changes into > comparison of V1TImode with CONST_INT). > > The following patch fixes that and also fixes an issue if the pseudo appears > multiple times in the debug info that the rescan could break traversal of > further uses. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2016-11-29 Jakub Jelinek <ja...@redhat.com> > > PR rtl-optimization/78575 > * config/i386/i386.c (timode_scalar_chain::fix_debug_reg_uses): Use > DF infrastructure to wrap all V1TImode reg uses into TImode subreg > if not already wrapped in a subreg. Make sure df_insn_rescan does not > affect further iterations. > > * gcc.dg/pr78575.c: New test.
OK. Thanks, Uros. > --- gcc/config/i386/i386.c.jj 2016-11-28 10:59:08.000000000 +0100 > +++ gcc/config/i386/i386.c 2016-11-29 08:31:58.061278522 +0100 > @@ -3831,30 +3831,32 @@ timode_scalar_chain::fix_debug_reg_uses > if (!flag_var_tracking) > return; > > - df_ref ref; > - for (ref = DF_REG_USE_CHAIN (REGNO (reg)); > - ref; > - ref = DF_REF_NEXT_REG (ref)) > + df_ref ref, next; > + for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref; ref = next) > { > rtx_insn *insn = DF_REF_INSN (ref); > + /* Make sure the next ref is for a different instruction, > + so that we're not affected by the rescan. */ > + next = DF_REF_NEXT_REG (ref); > + while (next && DF_REF_INSN (next) == insn) > + next = DF_REF_NEXT_REG (next); > + > if (DEBUG_INSN_P (insn)) > { > /* It may be a debug insn with a TImode variable in > register. */ > - rtx val = PATTERN (insn); > - if (GET_MODE (val) != TImode) > - continue; > - gcc_assert (GET_CODE (val) == VAR_LOCATION); > - rtx loc = PAT_VAR_LOCATION_LOC (val); > - /* It may have been converted to TImode already. */ > - if (GET_MODE (loc) == TImode) > - continue; > - gcc_assert (REG_P (loc) > - && GET_MODE (loc) == V1TImode); > - /* Convert V1TImode register, which has been updated by a SET > - insn before, to SUBREG TImode. */ > - PAT_VAR_LOCATION_LOC (val) = gen_rtx_SUBREG (TImode, loc, 0); > - df_insn_rescan (insn); > + bool changed = false; > + for (; ref != next; ref = DF_REF_NEXT_REG (ref)) > + { > + rtx *loc = DF_REF_LOC (ref); > + if (REG_P (*loc) && GET_MODE (*loc) == V1TImode) > + { > + *loc = gen_rtx_SUBREG (TImode, *loc, 0); > + changed = true; > + } > + } > + if (changed) > + df_insn_rescan (insn); > } > } > } > --- gcc/testsuite/gcc.dg/pr78575.c.jj 2016-11-29 08:36:25.821932436 +0100 > +++ gcc/testsuite/gcc.dg/pr78575.c 2016-11-29 08:35:35.000000000 +0100 > @@ -0,0 +1,16 @@ > +/* PR rtl-optimization/78575 */ > +/* { dg-do compile { target int128 } } */ > +/* { dg-options "-O2 -g -Wno-psabi" } */ > + > +typedef unsigned __int128 V __attribute__((vector_size(64))); > + > +V g; > + > +void > +foo (V v) > +{ > + unsigned __int128 x = 1; > + int c = v[1] <= ~x; > + v &= v[1]; > + g = v; > +} > > Jakub