https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89679

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ebotcazou at gcc dot gnu.org,
                   |                            |law at gcc dot gnu.org

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
If I change inside of the debugger that 0xffff in REG_EQUAL note to
constm1_rtx, then the testcase is not miscompiled.
The REG_EQUAL note is initially added by expand_mult_const:
      if (SCALAR_INT_MODE_P (mode))
        {
          /* Write a REG_EQUAL note on the last insn so that we can cse
             multiplication sequences.  Note that if ACCUM is a SUBREG,
             we've set the inner register and must properly indicate that.  */
          tem = op0, nmode = mode;
          accum_inner = accum;
          if (GET_CODE (accum) == SUBREG)
            {
              accum_inner = SUBREG_REG (accum);
              nmode = GET_MODE (accum_inner);
              tem = gen_lowpart (nmode, op0);
            }

          insn = get_last_insn ();
          wide_int wval_so_far
            = wi::uhwi (val_so_far,
                        GET_MODE_PRECISION (as_a <scalar_mode> (nmode)));
          rtx c = immed_wide_int_const (wval_so_far, nmode);
          set_dst_reg_note (insn, REG_EQUAL, gen_rtx_MULT (nmode, tem, c),
                            accum_inner);
        }
As accum is a (subreg:HI (reg:SI 140) 0), it emits a REG_EQUAL note with
paradoxical subreg in it:
(insn 17 16 18 2 (set (reg:SI 140)
        (plus:SI (subreg:SI (reg:HI 138) 0)
            (subreg:SI (reg:HI 136) 0))) "pr89679.c":16:3 -1
     (expr_list:REG_EQUAL (mult:SI (subreg:SI (reg:HI 136) 0)
            (const_int 257 [0x101]))
        (nil)))
the note is already quite questionable, because the SImode register is not
necessarily equal to that, the high 16 bits can be anything.
If it is not valid, then we either must make sure not to emit a REG_EQUAL note
in that case or emit it on some insn that sets a HImode reg rather than SImode.
Note we emit that that way for quite a long time, I think since
https://gcc.gnu.org/ml/gcc-patches/2000-12/msg00837.html

This is related to the https://gcc.gnu.org/ml/gcc-patches/2016-04/msg00418.html
change, though in this case we already have such a REG_EQUAL note that before
the change can be at least determined to have a paradoxical subreg in it and so
REG_EQUAL note consumers could take that into account.
But if we simplify it into a CONST_INT or whatever else that doesn't have the
paradoxical subreg in there anymore, this info is lost.

We could e.g. do:
--- gcc/fwprop.c.jj     2019-01-01 12:37:21.190908780 +0100
+++ gcc/fwprop.c        2019-03-12 17:24:14.623863160 +0100
@@ -1327,7 +1327,12 @@ forward_propagate_and_simplify (df_ref u
     {
       rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
       if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
-       loc = &XEXP (note, 0);
+       {
+         loc = &XEXP (note, 0);
+         /* Don't simplify a paradoxical SUBREG in a REG_EQUAL note.  */
+         if (paradoxical_subreg_p (DF_REF_REG (use)))
+           return false;
+       }
       else
        loc = &SET_SRC (use_set);

and thus not really simplify paradoxical subregs in REG_EQUAL notes, the notes
will be then removed if we DCE the setters of corresponding pseudos.

Thoughts on this?

Reply via email to