aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1997-03-15 07:14:27 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1997-03-15 07:14:27 -0500
commit29ae50126345055d032f8725be11c02441892542 (patch)
treeca6ed6949fe93823c3a0e5ed64cad8239e50e239 /gcc
parentabd268e28d3cfd7e581b5116ec9f50234c4d5cf9 (diff)
downloadgcc-29ae50126345055d032f8725be11c02441892542.zip
gcc-29ae50126345055d032f8725be11c02441892542.tar.gz
gcc-29ae50126345055d032f8725be11c02441892542.tar.bz2
(eliminate_regs): Add STORING arg.
(eliminate_regs, case SET): Pass that we are storing to recursive call. (eliminate_regs, case SUBREG): If storing and same number of words, use larger mode. From-SVN: r13704
Diffstat (limited to 'gcc')
-rw-r--r--gcc/reload1.c88
1 files changed, 50 insertions, 38 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 30f97c4..ad0f8f8 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -946,7 +946,7 @@ reload (first, global, dumpfile)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i])
{
- rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX);
+ rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX, 0);
if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),
XEXP (x, 0)))
@@ -2759,10 +2759,11 @@ static struct rtvec_def *old_asm_operands_vec, *new_asm_operands_vec;
the proper thing. */
rtx
-eliminate_regs (x, mem_mode, insn)
+eliminate_regs (x, mem_mode, insn, storing)
rtx x;
enum machine_mode mem_mode;
rtx insn;
+ int storing;
{
enum rtx_code code = GET_CODE (x);
struct elim_table *ep;
@@ -2819,7 +2820,7 @@ eliminate_regs (x, mem_mode, insn)
reference to the pseudo. Ensure we make a copy of the
address in case it is shared. */
new = eliminate_regs (reg_equiv_memory_loc[regno],
- mem_mode, insn);
+ mem_mode, insn, 0);
if (new != reg_equiv_memory_loc[regno])
{
cannot_omit_stores[regno] = 1;
@@ -2881,8 +2882,8 @@ eliminate_regs (x, mem_mode, insn)
reload. This is the desired action. */
{
- rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn);
- rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn);
+ rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
+ rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0);
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
{
@@ -2953,9 +2954,9 @@ eliminate_regs (x, mem_mode, insn)
case GE: case GT: case GEU: case GTU:
case LE: case LT: case LEU: case LTU:
{
- rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
rtx new1
- = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn) : 0;
+ = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn, 0) : 0;
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
return gen_rtx (code, GET_MODE (x), new0, new1);
@@ -2966,7 +2967,7 @@ eliminate_regs (x, mem_mode, insn)
/* If we have something in XEXP (x, 0), the usual case, eliminate it. */
if (XEXP (x, 0))
{
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
x = gen_rtx (EXPR_LIST, REG_NOTE_KIND (x), new, XEXP (x, 1));
}
@@ -2979,7 +2980,7 @@ eliminate_regs (x, mem_mode, insn)
strictly needed, but it simplifies the code. */
if (XEXP (x, 1))
{
- new = eliminate_regs (XEXP (x, 1), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0);
if (new != XEXP (x, 1))
return gen_rtx (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new);
}
@@ -3015,7 +3016,7 @@ eliminate_regs (x, mem_mode, insn)
case ABS:
case SQRT:
case FFS:
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
return gen_rtx (code, GET_MODE (x), new);
return x;
@@ -3034,7 +3035,7 @@ eliminate_regs (x, mem_mode, insn)
&& reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
{
new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))],
- mem_mode, insn);
+ mem_mode, insn, 0);
/* If we didn't change anything, we must retain the pseudo. */
if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))])
@@ -3054,27 +3055,37 @@ eliminate_regs (x, mem_mode, insn)
}
}
else
- new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
+ new = eliminate_regs (SUBREG_REG (x), mem_mode, insn, 0);
if (new != XEXP (x, 0))
{
- if (GET_CODE (new) == MEM
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (new)))
+ int x_size = GET_MODE_SIZE (GET_MODE (x));
+ int new_size = GET_MODE_SIZE (GET_MODE (new));
+
+ /* When asked to spill a partial word subreg, we need to go
+ ahead and spill the whole thing against the possibility
+ that we reload the whole reg and find garbage at the top. */
+ if (storing
+ && GET_CODE (new) == MEM
+ && x_size < new_size
+ && ((x_size + UNITS_PER_WORD-1) / UNITS_PER_WORD
+ == (new_size + UNITS_PER_WORD-1) / UNITS_PER_WORD))
+ return new;
+ else if (GET_CODE (new) == MEM
+ && x_size <= new_size
#ifdef LOAD_EXTEND_OP
- /* On these machines we will be reloading what is
- inside the SUBREG if it originally was a pseudo and
- the inner and outer modes are both a word or
- smaller. So leave the SUBREG then. */
- && ! (GET_CODE (SUBREG_REG (x)) == REG
- && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
- && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (new)))
- && INTEGRAL_MODE_P (GET_MODE (new))
- && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
+ /* On these machines we will be reloading what is
+ inside the SUBREG if it originally was a pseudo and
+ the inner and outer modes are both a word or
+ smaller. So leave the SUBREG then. */
+ && ! (GET_CODE (SUBREG_REG (x)) == REG
+ && x_size <= UNITS_PER_WORD
+ && new_size <= UNITS_PER_WORD
+ && x_size > new_size
+ && INTEGRAL_MODE_P (GET_MODE (new))
+ && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
#endif
- )
+ )
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
enum machine_mode mode = GET_MODE (x);
@@ -3102,7 +3113,7 @@ eliminate_regs (x, mem_mode, insn)
if (ep->from_rtx == XEXP (x, 0))
ep->can_eliminate = 0;
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
return gen_rtx (code, GET_MODE (x), new);
return x;
@@ -3115,7 +3126,7 @@ eliminate_regs (x, mem_mode, insn)
if (ep->to_rtx == XEXP (x, 0))
ep->can_eliminate = 0;
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
return gen_rtx (code, GET_MODE (x), new);
return x;
@@ -3133,7 +3144,7 @@ eliminate_regs (x, mem_mode, insn)
temp_vec = (rtx *) alloca (XVECLEN (x, 3) * sizeof (rtx));
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
temp_vec[i] = eliminate_regs (ASM_OPERANDS_INPUT (x, i),
- mem_mode, insn);
+ mem_mode, insn, 0);
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
if (temp_vec[i] != ASM_OPERANDS_INPUT (x, i))
@@ -3204,8 +3215,8 @@ eliminate_regs (x, mem_mode, insn)
/* Now avoid the loop below in this common case. */
{
- rtx new0 = eliminate_regs (SET_DEST (x), 0, insn);
- rtx new1 = eliminate_regs (SET_SRC (x), 0, insn);
+ rtx new0 = eliminate_regs (SET_DEST (x), 0, insn, 1);
+ rtx new1 = eliminate_regs (SET_SRC (x), 0, insn, 0);
/* If SET_DEST changed from a REG to a MEM and INSN is an insn,
write a CLOBBER insn. */
@@ -3224,7 +3235,7 @@ eliminate_regs (x, mem_mode, insn)
/* Our only special processing is to pass the mode of the MEM to our
recursive call and copy the flags. While we are here, handle this
case more efficiently. */
- new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn);
+ new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn, 0);
if (new != XEXP (x, 0))
{
new = gen_rtx (MEM, GET_MODE (x), new);
@@ -3244,7 +3255,7 @@ eliminate_regs (x, mem_mode, insn)
{
if (*fmt == 'e')
{
- new = eliminate_regs (XEXP (x, i), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, i), mem_mode, insn, 0);
if (new != XEXP (x, i) && ! copied)
{
rtx new_x = rtx_alloc (code);
@@ -3261,7 +3272,7 @@ eliminate_regs (x, mem_mode, insn)
int copied_vec = 0;
for (j = 0; j < XVECLEN (x, i); j++)
{
- new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn);
+ new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn, 0);
if (new != XVECEXP (x, i, j) && ! copied_vec)
{
rtvec new_v = gen_rtvec_vv (XVECLEN (x, i),
@@ -3439,7 +3450,7 @@ eliminate_regs_in_insn (insn, replace)
but now can do this as a load-address. This saves an insn in this
common case. */
- new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX);
+ new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX, 0);
if (new_body != old_body)
{
/* If we aren't replacing things permanently and we changed something,
@@ -3528,7 +3539,7 @@ eliminate_regs_in_insn (insn, replace)
of spill registers to be needed in the final reload pass than in
the pre-passes. */
if (val && REG_NOTES (insn) != 0)
- REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn));
+ REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn), 0);
if (! replace)
pop_obstacks ();
@@ -4006,7 +4017,8 @@ reload_as_needed (first, live_known)
&& GET_CODE (XEXP (PATTERN (insn), 0)) == MEM)
XEXP (XEXP (PATTERN (insn), 0), 0)
= eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0),
- GET_MODE (XEXP (PATTERN (insn), 0)), NULL_RTX);
+ GET_MODE (XEXP (PATTERN (insn), 0)),
+ NULL_RTX, 0);
/* If we need to do register elimination processing, do so.
This might delete the insn, in which case we are done. */