really reload just the inside expression in its own mode.
If we have (SUBREG:M1 (REG:M2 ...) ...) with M1 wider than M2 and the
register is a pseudo, this will become the same as the above case.
- Do the same for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
+ Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
either M1 is not valid for R or M2 is wider than a word but we only
need one word to store an M2-sized quantity in R.
+ (However, if OUT is nonzero, we need to reload the reg *and*
+ the subreg, so do nothing here, and let following statement handle it.)
+
Note that the case of (SUBREG (CONST_INT...)...) is handled elsewhere;
we can't handle it here because CONST_INT does not indicate a mode.
&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (inmode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))))
- || (GET_CODE (SUBREG_REG (in)) == REG
- && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ || (REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ /* The case where out is nonzero
+ is handled differently in the following statement. */
+ && (out == 0 || SUBREG_WORD (in) == 0)
&& (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)), inmode)
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
inmode = GET_MODE (in);
}
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
+ either M1 is not valid for R or M2 is wider than a word but we only
+ need one word to store an M2-sized quantity in R.
+
+ However, we must reload the inner reg *as well as* the subreg in
+ that case. */
+
+ if (in != 0 && GET_CODE (in) == SUBREG
+ && GET_CODE (SUBREG_REG (in)) == REG
+ && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)), inmode)
+ || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
+ > UNITS_PER_WORD)
+ && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
+ / UNITS_PER_WORD)
+ != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
+ GET_MODE (SUBREG_REG (in)))))))
+ {
+ push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
+ GENERAL_REGS, VOIDmode, VOIDmode, 0, 0, opnum, type);
+ }
+
+
/* Similarly for paradoxical and problematical SUBREGs on the output.
Note that there is no reason we need worry about the previous value
of SUBREG_REG (out); even if wider than out,
for (j = 0; j < n_reloads; j++)
if (i != j && reload_in[j] != 0 && reload_out[j] == 0
&& reload_when_needed[j] == reload_when_needed[i]
- && MATCHES (reload_in[i], reload_in[j]))
+ && MATCHES (reload_in[i], reload_in[j])
+ && reload_reg_class[i] == reload_reg_class[j]
+ && !reload_nocombine[i] && !reload_nocombine[j])
{
reload_opnum[i] = MIN (reload_opnum[i], reload_opnum[j]);
transfer_replacements (i, j);
return x;
}
+/* Return a mem ref for the memory equivalent of reg REGNO.
+ This mem ref is not shared with anything. */
+
static rtx
make_memloc (ad, regno)
rtx ad;
{
register int i;
rtx tem = reg_equiv_address[regno];
+
+#if 0 /* We cannot safely reuse a memloc made here;
+ if the pseudo appears twice, and its mem needs a reload,
+ it gets two separate reloads assigned, but it only
+ gets substituted with the second of them;
+ then it can get used before that reload reg gets loaded up. */
for (i = 0; i < n_memlocs; i++)
if (rtx_equal_p (tem, XEXP (memlocs[i], 0)))
return memlocs[i];
+#endif
/* If TEM might contain a pseudo, we must copy it to avoid
modifying it when we do the substitution for the reload. */
}
/* We can avoid a reload if the register's equivalent memory expression
- is valid as an indirect memory address. */
+ is valid as an indirect memory address.
+ But not all addresses are valid in a mem used as an indirect address:
+ only reg or reg+constant. */
else if (reg_equiv_mem[regno] != 0 && ind_levels > 0
- && strict_memory_address_p (mode, reg_equiv_mem[regno]))
+ && strict_memory_address_p (mode, reg_equiv_mem[regno])
+ && (GET_CODE (XEXP (reg_equiv_mem[regno], 0)) == REG
+ || (GET_CODE (XEXP (reg_equiv_mem[regno], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (reg_equiv_mem[regno], 0), 0)) == REG
+ && CONSTANT_P (XEXP (XEXP (reg_equiv_mem[regno], 0), 0)))))
return 0;
/* The only remaining case where we can avoid a reload is if this is a