static void record_value_for_reg PROTO((rtx, rtx, rtx));
static void record_dead_and_set_regs_1 PROTO((rtx, rtx));
static void record_dead_and_set_regs PROTO((rtx));
-static int get_last_value_validate PROTO((rtx *, int, int));
+static int get_last_value_validate PROTO((rtx *, rtx, int, int));
static rtx get_last_value PROTO((rtx));
static int use_crosses_set_p PROTO((rtx, int));
static void reg_dead_at_p_1 PROTO((rtx, rtx));
case SIGN_EXTEND:
inner = XEXP (SET_SRC (x), 0);
+
+ /* We can't optimize if either mode is a partial integer
+ mode as we don't know how many bits are significant
+ in those modes. */
+ if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_PARTIAL_INT
+ || GET_MODE_CLASS (GET_MODE (SET_SRC (x))) == MODE_PARTIAL_INT)
+ break;
+
pos = 0;
len = GET_MODE_BITSIZE (GET_MODE (inner));
unsignedp = 0;
if (CONSTANT_P (SUBREG_REG (x)) && op0_mode != VOIDmode
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
- && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD
+ && GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
&& GET_MODE_CLASS (mode) == MODE_INT)
{
temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x),
/* If we want a subreg of a constant, at offset 0,
take the low bits. On a little-endian machine, that's
always valid. On a big-endian machine, it's valid
- only if the constant's mode fits in one word. */
- if (CONSTANT_P (SUBREG_REG (x)) && subreg_lowpart_p (x)
+ only if the constant's mode fits in one word. Note that we
+ cannot use subreg_lowpart_p since SUBREG_REG may be VOIDmode. */
+ if (CONSTANT_P (SUBREG_REG (x))
+ && ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD
+ || ! WORDS_BIG_ENDIAN)
+ ? SUBREG_WORD (x) == 0
+ : (SUBREG_WORD (x)
+ == ((GET_MODE_SIZE (op0_mode)
+ - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
+ / UNITS_PER_WORD)))
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode)
&& (! WORDS_BIG_ENDIAN
|| GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD))
break;
case TRUNCATE:
+ /* We can't handle truncation to a partial integer mode here
+ because we don't know the real bitsize of the partial
+ integer mode. */
+ if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
+ break;
+
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
SUBST (XEXP (x, 0),
force_to_mode (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
if ((cond0 != 0 || cond1 != 0)
&& ! (cond0 != 0 && cond1 != 0 && ! rtx_equal_p (cond0, cond1)))
{
+ /* If if_then_else_cond returned zero, then true/false are the
+ same rtl. We must copy one of them to prevent invalid rtl
+ sharing. */
+ if (cond0 == 0)
+ true0 = copy_rtx (true0);
+ else if (cond1 == 0)
+ true1 = copy_rtx (true1);
+
*ptrue = gen_binary (code, mode, true0, true1);
*pfalse = gen_binary (code, mode, false0, false1);
return cond0 ? cond0 : cond1;
/* The value being assigned might refer to X (like in "x++;"). In that
case, we must replace it with (clobber (const_int 0)) to prevent
infinite loops. */
- if (value && ! get_last_value_validate (&value,
+ if (value && ! get_last_value_validate (&value, insn,
reg_last_set_label[regno], 0))
{
value = copy_rtx (value);
- if (! get_last_value_validate (&value, reg_last_set_label[regno], 1))
+ if (! get_last_value_validate (&value, insn,
+ reg_last_set_label[regno], 1))
value = 0;
}
we don't know exactly what registers it was produced from. */
static int
-get_last_value_validate (loc, tick, replace)
+get_last_value_validate (loc, insn, tick, replace)
rtx *loc;
+ rtx insn;
int tick;
int replace;
{
return 1;
}
+ /* If this is a memory reference, make sure that there were
+ no stores after it that might have clobbered the value. We don't
+ have alias info, so we assume any store invalidates it. */
+ else if (GET_CODE (x) == MEM && ! RTX_UNCHANGING_P (x)
+ && INSN_CUID (insn) <= mem_last_set)
+ {
+ if (replace)
+ *loc = gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
+ return replace;
+ }
for (i = 0; i < len; i++)
if ((fmt[i] == 'e'
- && get_last_value_validate (&XEXP (x, i), tick, replace) == 0)
+ && get_last_value_validate (&XEXP (x, i), insn, tick, replace) == 0)
/* Don't bother with these. They shouldn't occur anyway. */
|| fmt[i] == 'E')
return 0;
}
/* If the value has all its registers valid, return it. */
- if (get_last_value_validate (&value, reg_last_set_label[regno], 0))
+ if (get_last_value_validate (&value, reg_last_set[regno],
+ reg_last_set_label[regno], 0))
return value;
/* Otherwise, make a copy and replace any invalid register with
(clobber (const_int 0)). If that fails for some reason, return 0. */
value = copy_rtx (value);
- if (get_last_value_validate (&value, reg_last_set_label[regno], 1))
+ if (get_last_value_validate (&value, reg_last_set[regno],
+ reg_last_set_label[regno], 1))
return value;
return 0;
if (note != 0 && regno < FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
- != GET_MODE_SIZE (GET_MODE (x))))
+ > GET_MODE_SIZE (GET_MODE (x))))
{
int deadregno = REGNO (XEXP (note, 0));
int deadend
gen_rtx (REG, reg_raw_mode[i], i),
REG_NOTES (where_dead));
}
- /* If we didn't find any note, and we have a multi-reg hard
+ /* If we didn't find any note, or if we found a REG_DEAD note that
+ covers only part of the given reg, and we have a multi-reg hard
register, then to be safe we must check for REG_DEAD notes
for each register other than the first. They could have
their own REG_DEAD notes lying around. */
- else if (note == 0 && regno < FIRST_PSEUDO_REGISTER
+ else if ((note == 0
+ || (note != 0
+ && (GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
+ < GET_MODE_SIZE (GET_MODE (x)))))
+ && regno < FIRST_PSEUDO_REGISTER
&& HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1)
{
int ourend = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
- int i;
+ int i, offset;
rtx oldnotes = 0;
- for (i = regno + 1; i < ourend; i++)
+ if (note)
+ offset = HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0)));
+ else
+ offset = 1;
+
+ for (i = regno + offset; i < ourend; i++)
move_deaths (gen_rtx (REG, reg_raw_mode[i], i),
maybe_kill_insn, from_cuid, to_insn, &oldnotes);
}
next_note = XEXP (note, 1);
switch (REG_NOTE_KIND (note))
{
+ case REG_BR_PROB:
+ case REG_EXEC_COUNT:
+ /* Doesn't matter much where we put this, as long as it's somewhere.
+ It is preferable to keep these notes on branches, which is most
+ likely to be i3. */
+ place = i3;
+ break;
+
case REG_UNUSED:
/* Any clobbers for i3 may still exist, and so we must process
REG_UNUSED notes from that insn.