On Mon, Feb 24, 2025 at 10:46 AM Richard Biener <richard.guent...@gmail.com> wrote: > > On Wed, Feb 12, 2025 at 1:16 PM Uros Bizjak <ubiz...@gmail.com> 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 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, the flags register is not UNUSED (or DEAD), because it is > > used in i3. The proposed solution is to remove the REG_UNUSED note > > from i2 when the register is also mentioned in i3. > > But there is > > /* 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; > } > > which of course isn't taken as there is a NOTE in i3 already. Still the > note is supposed to be moved there (just not emitted, it's already there. > So a better fix is to refactor the above to > > /* 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)) > { > if (! (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; > } > } > > ? At least the else { case seems to assume the reg isn't refernced in i3. > The comment wording might also need an update of course.
Yes, this revision works as well. I'll prepare a v2 patch. Thanks, Uros.