+2007-01-21 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR rtl-optimization/29329
+ * combine.c (replaced_rhs_insn): Rename to i2mod.
+ (replaced_rhs_value): Rename to i2mod_new_rhs.
+ (i2mod_old_rhs): New global variable.
+ (combine_instructions): Adjust for above change. Save a copy of
+ the old RHS into i2mod_old_rhs when the contents of a REG_EQUAL
+ note are substituted in the second instruction.
+ (distribute_notes) <REG_DEAD>: Adjust for above change. Do not
+ ditch the note if it pertains to the second eliminated register
+ and this register is mentioned in i2mod_old_rhs.
+
+ Revert:
+ 2006-09-12 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ * combine.c (distribute_notes) <REG_DEAD>: Do not consider SETs past
+ the insn to which the note was originally attached.
+
2007-01-21 Jan Hubicka <jh@suse.cz>
* ipa-inline.c (inlining_mode): Comment, move up.
static int total_attempts, total_merges, total_extras, total_successes;
-/* Sometimes combine tries to replace the right hand side of an insn
- with the value of a REG_EQUAL note. This is the insn that has been
- so modified, or null if none. */
+/* combine_instructions may try to replace the right hand side of the
+ second instruction with the value of an associated REG_EQUAL note
+ before throwing it at try_combine. That is problematic when there
+ is a REG_DEAD note for a register used in the old right hand side
+ and can cause distribute_notes to do wrong things. This is the
+ second instruction if it has been so modified, null otherwise. */
-static rtx replaced_rhs_insn;
+static rtx i2mod;
-/* When REPLACED_RHS_INSN is nonnull, this is a copy of the new right
- hand side. */
+/* When I2MOD is nonnull, this is a copy of the old right hand side. */
-static rtx replaced_rhs_value;
+static rtx i2mod_old_rhs;
+
+/* When I2MOD is nonnull, this is a copy of the new right hand side. */
+
+static rtx i2mod_new_rhs;
\f
/* Vector mapping INSN_UIDs to cuids.
The cuids are like uids but increase monotonically always.
be deleted or recognized by try_combine. */
rtx orig = SET_SRC (set);
SET_SRC (set) = note;
- replaced_rhs_insn = temp;
- replaced_rhs_value = copy_rtx (note);
- next = try_combine (insn, temp, NULL_RTX,
+ i2mod = temp;
+ i2mod_old_rhs = copy_rtx (orig);
+ i2mod_new_rhs = copy_rtx (note);
+ next = try_combine (insn, i2mod, NULL_RTX,
&new_direct_jump_p);
- replaced_rhs_insn = NULL;
+ i2mod = NULL_RTX;
if (next)
goto retry;
SET_SRC (set) = orig;
use of A and put the death note there. */
if (from_insn
- && from_insn == replaced_rhs_insn
- && !reg_overlap_mentioned_p (XEXP (note, 0), replaced_rhs_value))
+ && from_insn == i2mod
+ && !reg_overlap_mentioned_p (XEXP (note, 0), i2mod_new_rhs))
tem = from_insn;
else
{
else if (i2 != 0 && next_nonnote_insn (i2) == i3
&& reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
place = i2;
- else if (rtx_equal_p (XEXP (note, 0), elim_i2)
+ else if ((rtx_equal_p (XEXP (note, 0), elim_i2)
+ && !(i2mod
+ && reg_overlap_mentioned_p (XEXP (note, 0),
+ i2mod_old_rhs)))
|| rtx_equal_p (XEXP (note, 0), elim_i1))
break;
tem = i3;
continue;
}
- /* If TEM is a (reaching) definition of the use to which the
- note was attached, see if that is all TEM is doing. If so,
- delete TEM. Otherwise, make this into a REG_UNUSED note
- instead. Don't delete sets to global register vars. */
- if ((!from_insn
- || INSN_CUID (tem) < INSN_CUID (from_insn))
- && (REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER
- || !global_regs[REGNO (XEXP (note, 0))])
+ /* If the register is being set at TEM, see if that is all
+ TEM is doing. If so, delete TEM. Otherwise, make this
+ into a REG_UNUSED note instead. Don't delete sets to
+ global register vars. */
+ if ((REGNO (XEXP (note, 0)) >= FIRST_PSEUDO_REGISTER
+ || !global_regs[REGNO (XEXP (note, 0))])
&& reg_set_p (XEXP (note, 0), PATTERN (tem)))
{
rtx set = single_set (tem);