diff options
Diffstat (limited to 'gcc/combine.c')
-rw-r--r-- | gcc/combine.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index 786a840..7f10c67 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -14219,6 +14219,46 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2, PUT_REG_NOTE_KIND (note, REG_DEAD); place = i3; } + + /* A SET or CLOBBER of the REG_UNUSED reg has been removed, + but we can't tell which at this point. We must reset any + expectations we had about the value that was previously + stored in the reg. ??? Ideally, we'd adjust REG_N_SETS + and, if appropriate, restore its previous value, but we + don't have enough information for that at this point. */ + else + { + record_value_for_reg (XEXP (note, 0), NULL, NULL_RTX); + + /* 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; + } + } + break; case REG_EQUAL: |