On Wed, 26 Feb 2025, Uros Bizjak wrote:

> The combine pass 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 the following two insn sequence:
> 
> 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.
> 
> where the REG_DEAD note in i2 is not correct, because the flags
> register is still referenced in i3.  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() using the following:
> 
> --cut here--
>       /* Otherwise, if this register is used by I3, then this register
>          now dies here, so we must put a REG_DEAD note here unless there
>          is one already.  */
>       else if (reg_referenced_p (XEXP (note, 0), PATTERN (i3))
>            && ! (REG_P (XEXP (note, 0))
>              ? find_regno_note (i3, REG_DEAD,
>                         REGNO (XEXP (note, 0)))
>              : find_reg_note (i3, REG_DEAD, XEXP (note, 0))))
>         {
>           PUT_REG_NOTE_KIND (note, REG_DEAD);
>           place = i3;
>         }
> --cut here--
> 
> Flags register is used in I3, but there already is a REG_DEAD note in I3.
> The above condition doesn't trigger and continues in the "else" part where
> REG_DEAD note is put to I2.  The proposed solution corrects the above
> logic to trigger every time the register is referenced in I3, avoiding the
> "else" part.
>
>     PR rtl-optimization/118739
> 
> gcc/ChangeLog:
> 
>     * combine.cc (distribute_notes) <case REG_UNUSED>: Correct the
>       logic when the register is used by I3.
> 
> gcc/testsuite/ChangeLog:
> 
>     * gcc.target/i386/pr118739.c: New test.
> 
> Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
> 
> OK for master and eventual backports?

OK if there's no other comments on this until Monday.

Thanks,
Richard.

Reply via email to