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;
new_mask >>= info->regno - regno;
else
new_mask <<= regno - info->regno;
- info->mask &= new_mask;
+ info->mask &= ~new_mask;
}
/* Return nonzero iff part of the return value is live during INSN, and
info.nregs = nregs;
info.mask = mask;
for (p = PREV_INSN (use); info.mask && p != insn; p = PREV_INSN (p))
- note_stores (PATTERN (insn), likely_spilled_retval_1, &info);
+ if (INSN_P (p))
+ note_stores (PATTERN (p), likely_spilled_retval_1, &info);
mask = info.mask;
/* Check if any of the (probably) live return value registers is
rtx i3dest_killed = 0;
/* SET_DEST and SET_SRC of I2 and I1. */
rtx i2dest, i2src, i1dest = 0, i1src = 0;
- /* PATTERN (I2), or a copy of it in certain cases. */
- rtx i2pat;
+ /* PATTERN (I1) and PATTERN (I2), or a copy of it in certain cases. */
+ rtx i1pat = 0, i2pat = 0;
/* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC. */
int i2dest_in_i2src = 0, i1dest_in_i1src = 0, i2dest_in_i1src = 0;
int i2dest_killed = 0, i1dest_killed = 0;
offset = -1;
}
- if (offset >= 0)
+ if (offset >= 0
+ && (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp)))
+ <= HOST_BITS_PER_WIDE_INT * 2))
{
HOST_WIDE_INT mhi, ohi, ihi;
HOST_WIDE_INT mlo, olo, ilo;
rtx. If I2 is a PARALLEL, we just need the piece that assigns I2SRC to
I2DEST. */
- i2pat = (GET_CODE (PATTERN (i2)) == PARALLEL
- ? gen_rtx_SET (VOIDmode, i2dest, i2src)
- : PATTERN (i2));
-
if (added_sets_2)
- i2pat = copy_rtx (i2pat);
+ {
+ if (GET_CODE (PATTERN (i2)) == PARALLEL)
+ i2pat = gen_rtx_SET (VOIDmode, i2dest, copy_rtx (i2src));
+ else
+ i2pat = copy_rtx (PATTERN (i2));
+ }
+
+ if (added_sets_1)
+ {
+ if (GET_CODE (PATTERN (i1)) == PARALLEL)
+ i1pat = gen_rtx_SET (VOIDmode, i1dest, copy_rtx (i1src));
+ else
+ i1pat = copy_rtx (PATTERN (i1));
+ }
combine_merges++;
}
if (added_sets_1)
- XVECEXP (newpat, 0, --total_sets)
- = (GET_CODE (PATTERN (i1)) == PARALLEL
- ? gen_rtx_SET (VOIDmode, i1dest, i1src) : PATTERN (i1));
+ XVECEXP (newpat, 0, --total_sets) = i1pat;
if (added_sets_2)
{
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;