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

--- Comment #14 from Uroš Bizjak <ubizjak at gmail dot com> ---
Untested patch:

--cut here--
diff --git a/gcc/combine.cc b/gcc/combine.cc
index 3beeb514b81..99cd64ada1f 100644
--- a/gcc/combine.cc
+++ b/gcc/combine.cc
@@ -14559,7 +14559,8 @@ distribute_notes (rtx notes, rtx_insn *from_insn,
rtx_insn *i3, rtx_insn *i2,
                 referenced in i3) that it's unused, just as it was
                 unused before, and we place the note in i2.  */
              if (from_insn != i3 && i2 && INSN_P (i2)
-                 && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
+                 && reg_referenced_p (XEXP (note, 0), PATTERN (i2))
+                 && !reg_referenced_p (XEXP (note, 0), PATTERN (i3)))
                {
                  if (!reg_set_p (XEXP (note, 0), PATTERN (i2)))
                    PUT_REG_NOTE_KIND (note, REG_DEAD);
--cut here--

The combine is trying to combine:

Trying 16, 22, 21 -> 23:
   16: r104:QI=flags:CCNO>0
   22: {r120:QI=r104:QI^0x1;clobber flags:CC;}
      REG_UNUSED flags:CC
   21: r119:QI=flags:CCNO<=0
      REG_DEAD flags:CCNO
   23: {r110:QI=r119:QI|r120:QI;clobber flags:CC;}
      REG_DEAD r120:QI
      REG_DEAD r119:QI
      REG_UNUSED flags:CC

and creates:

modifying insn i2    22: r104:QI=flags:CCNO>0
      REG_DEAD flags:CC
deferring rescan insn with uid = 22.
modifying insn i3    23: r110:QI=flags:CCNO<=0
      REG_DEAD flags:CC
deferring rescan insn with uid = 23.

In try_combine() megafunction, we have this part:

--cut here--
    /* Distribute all the LOG_LINKS and REG_NOTES from I1, I2, and I3.  */
    if (i3notes)
      distribute_notes (i3notes, i3, i3, newi2pat ? i2 : NULL,
                        elim_i2, elim_i1, elim_i0);
    if (i2notes)
      distribute_notes (i2notes, i2, i3, newi2pat ? i2 : NULL,
                        elim_i2, elim_i1, elim_i0);
    if (i1notes)
      distribute_notes (i1notes, i1, i3, newi2pat ? i2 : NULL,
                        elim_i2, local_elim_i1, local_elim_i0);
    if (i0notes)
      distribute_notes (i0notes, i0, i3, newi2pat ? i2 : NULL,
                        elim_i2, elim_i1, local_elim_i0);
    if (midnotes)
      distribute_notes (midnotes, NULL, i3, newi2pat ? i2 : NULL,
                        elim_i2, elim_i1, elim_i0);
--cut here--

where the compiler distributes REG_UNUSED note from i2:

   22: {r120:QI=r104:QI^0x1;clobber flags:CC;}
      REG_UNUSED flags:CC

via distribute_notes() with:

--cut here--
              /* Otherwise, if this register is now referenced in i2
                 then the register used to be modified in one of the
                 original insns.  If it was i3 (say, in an unused
                 parallel), it's now completely gone, so the note can
                 be discarded.  But if it was modified in i2, i1 or i0
                 and we still reference it in i2, then we're
                 referencing the previous value, and since the
                 register was modified and REG_UNUSED, we know that
                 the previous value is now dead.  So, if we only
                 reference the register in i2, we change the note to
                 REG_DEAD, to reflect the previous value.  However, if
                 we're also setting or clobbering the register as
                 scratch, we know (because the register was not
                 referenced in i3) that it's unused, just as it was
                 unused before, and we place the note in i2.  */
              if (from_insn != i3 && i2 && INSN_P (i2)
                  && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
                {
                  if (!reg_set_p (XEXP (note, 0), PATTERN (i2)))
                    PUT_REG_NOTE_KIND (note, REG_DEAD);
                  if (! (REG_P (XEXP (note, 0))
                         ? find_regno_note (i2, REG_NOTE_KIND (note),
                                            REGNO (XEXP (note, 0)))
                         : find_reg_note (i2, REG_NOTE_KIND (note),
                                          XEXP (note, 0))))
                    place = i2;
                }
--cut here--

However (and as shown in Comment #11) the flags register is far from UNUSED
(let alone DEAD), because it is used in i3. So, the proposed solution is to
simply remove REG_UNUSED or REG_DEAD notes when the register is also mentioned
in i3.

Reply via email to