aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-02-25 07:19:23 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1994-02-25 07:19:23 -0500
commita2d353e50cec8279fba0f9905efc38839e6cfce9 (patch)
treef281395f57292f9790841137ffcde384404c1f27 /gcc/reload.c
parent8bffcaf6a039d6ab262ac2b90d8fa7174d764320 (diff)
downloadgcc-a2d353e50cec8279fba0f9905efc38839e6cfce9.zip
gcc-a2d353e50cec8279fba0f9905efc38839e6cfce9.tar.gz
gcc-a2d353e50cec8279fba0f9905efc38839e6cfce9.tar.bz2
(find_reloads): Don't restrict class of multiword operand to preferred class.
(find_reloads_address_1): Rework to use `switch'. Reload a SUBREG of a hard reg as a unit. From-SVN: r6622
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c330
1 files changed, 184 insertions, 146 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index b3a21c8..37d3dd8 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -2971,18 +2971,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
Don't bother with this if this alternative will accept this
operand.
- Don't do this for a multiword operand, if
- we have to worry about small classes, because making reg groups
- harder to allocate is asking for trouble.
+ Don't do this for a multiword operand, since it is only a
+ small win and has the risk of requiring more spill registers,
+ which could cause a large loss.
Don't do this if the preferred class has only one register
because we might otherwise exhaust the class. */
if (! win && this_alternative[i] != (int) NO_REGS
-#ifdef SMALL_REGISTER_CLASSES
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
-#endif
&& reg_class_size[(int) preferred_class[i]] > 1)
{
if (! reg_class_subset_p (this_alternative[i],
@@ -4408,92 +4406,107 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
{
register RTX_CODE code = GET_CODE (x);
- if (code == PLUS)
+ switch (code)
{
- register rtx orig_op0 = XEXP (x, 0);
- register rtx orig_op1 = XEXP (x, 1);
- register RTX_CODE code0 = GET_CODE (orig_op0);
- register RTX_CODE code1 = GET_CODE (orig_op1);
- register rtx op0 = orig_op0;
- register rtx op1 = orig_op1;
-
- if (GET_CODE (op0) == SUBREG)
- {
- op0 = SUBREG_REG (op0);
- code0 = GET_CODE (op0);
- }
- if (GET_CODE (op1) == SUBREG)
- {
- op1 = SUBREG_REG (op1);
- code1 = GET_CODE (op1);
- }
+ case PLUS:
+ {
+ register rtx orig_op0 = XEXP (x, 0);
+ register rtx orig_op1 = XEXP (x, 1);
+ register RTX_CODE code0 = GET_CODE (orig_op0);
+ register RTX_CODE code1 = GET_CODE (orig_op1);
+ register rtx op0 = orig_op0;
+ register rtx op1 = orig_op1;
+
+ if (GET_CODE (op0) == SUBREG)
+ {
+ op0 = SUBREG_REG (op0);
+ code0 = GET_CODE (op0);
+ }
- if (code0 == MULT || code0 == SIGN_EXTEND || code1 == MEM)
- {
- find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
- ind_levels);
- find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
- ind_levels);
- }
- else if (code1 == MULT || code1 == SIGN_EXTEND || code0 == MEM)
- {
- find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
- ind_levels);
- find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
- ind_levels);
- }
- else if (code0 == CONST_INT || code0 == CONST
- || code0 == SYMBOL_REF || code0 == LABEL_REF)
- find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type, ind_levels);
- else if (code1 == CONST_INT || code1 == CONST
- || code1 == SYMBOL_REF || code1 == LABEL_REF)
- find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type, ind_levels);
- else if (code0 == REG && code1 == REG)
- {
- if (REG_OK_FOR_INDEX_P (op0)
- && REG_OK_FOR_BASE_P (op1))
- return 0;
- else if (REG_OK_FOR_INDEX_P (op1)
- && REG_OK_FOR_BASE_P (op0))
- return 0;
- else if (REG_OK_FOR_BASE_P (op1))
- find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
+ if (GET_CODE (op1) == SUBREG)
+ {
+ op1 = SUBREG_REG (op1);
+ code1 = GET_CODE (op1);
+ }
+
+ if (code0 == MULT || code0 == SIGN_EXTEND || code1 == MEM)
+ {
+ find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
ind_levels);
- else if (REG_OK_FOR_BASE_P (op0))
- find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
+ find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
ind_levels);
- else if (REG_OK_FOR_INDEX_P (op1))
+ }
+
+ else if (code1 == MULT || code1 == SIGN_EXTEND || code0 == MEM)
+ {
find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
ind_levels);
- else if (REG_OK_FOR_INDEX_P (op0))
- find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
+ find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
ind_levels);
- else
- {
- find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
- ind_levels);
- find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
- ind_levels);
- }
- }
- else if (code0 == REG)
- {
- find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
- ind_levels);
+ }
+
+ else if (code0 == CONST_INT || code0 == CONST
+ || code0 == SYMBOL_REF || code0 == LABEL_REF)
find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
ind_levels);
- }
- else if (code1 == REG)
- {
- find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
- ind_levels);
+
+ else if (code1 == CONST_INT || code1 == CONST
+ || code1 == SYMBOL_REF || code1 == LABEL_REF)
find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
ind_levels);
- }
- }
- else if (code == POST_INC || code == POST_DEC
- || code == PRE_INC || code == PRE_DEC)
- {
+
+ else if (code0 == REG && code1 == REG)
+ {
+ if (REG_OK_FOR_INDEX_P (op0)
+ && REG_OK_FOR_BASE_P (op1))
+ return 0;
+ else if (REG_OK_FOR_INDEX_P (op1)
+ && REG_OK_FOR_BASE_P (op0))
+ return 0;
+ else if (REG_OK_FOR_BASE_P (op1))
+ find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
+ ind_levels);
+ else if (REG_OK_FOR_BASE_P (op0))
+ find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
+ ind_levels);
+ else if (REG_OK_FOR_INDEX_P (op1))
+ find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
+ ind_levels);
+ else if (REG_OK_FOR_INDEX_P (op0))
+ find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
+ ind_levels);
+ else
+ {
+ find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
+ ind_levels);
+ find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
+ ind_levels);
+ }
+ }
+
+ else if (code0 == REG)
+ {
+ find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
+ ind_levels);
+ find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
+ ind_levels);
+ }
+
+ else if (code1 == REG)
+ {
+ find_reloads_address_1 (orig_op1, 1, &XEXP (x, 1), opnum, type,
+ ind_levels);
+ find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
+ ind_levels);
+ }
+ }
+
+ return 0;
+
+ case POST_INC:
+ case POST_DEC:
+ case PRE_INC:
+ case PRE_DEC:
if (GET_CODE (XEXP (x, 0)) == REG)
{
register int regno = REGNO (XEXP (x, 0));
@@ -4559,6 +4572,7 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
}
return value;
}
+
else if (GET_CODE (XEXP (x, 0)) == MEM)
{
/* This is probably the result of a substitution, by eliminate_regs,
@@ -4591,16 +4605,16 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
return 1;
}
- }
- else if (code == MEM)
- {
- /* This is probably the result of a substitution, by eliminate_regs,
- of an equivalent address for a pseudo that was not allocated to a
- hard register. Verify that the specified address is valid and reload
- it into a register.
+ return 0;
+
+ case MEM:
+ /* This is probably the result of a substitution, by eliminate_regs, of
+ an equivalent address for a pseudo that was not allocated to a hard
+ register. Verify that the specified address is valid and reload it
+ into a register.
- Since we know we are going to reload this item, don't decrement
- for the indirection level.
+ Since we know we are going to reload this item, don't decrement for
+ the indirection level.
Note that this is actually conservative: it would be slightly more
efficient to use the value of SPILL_INDIRECT_LEVELS from
@@ -4608,78 +4622,102 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, type, ind_levels);
-
push_reload (*loc, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
- }
- else if (code == REG)
- {
- register int regno = REGNO (x);
- if (reg_equiv_constant[regno] != 0)
- {
- find_reloads_address_part (reg_equiv_constant[regno], loc,
- (context ? INDEX_REG_CLASS
- : BASE_REG_CLASS),
- GET_MODE (x), opnum, type, ind_levels);
- return 1;
- }
+ case REG:
+ {
+ register int regno = REGNO (x);
+
+ if (reg_equiv_constant[regno] != 0)
+ {
+ find_reloads_address_part (reg_equiv_constant[regno], loc,
+ (context ? INDEX_REG_CLASS
+ : BASE_REG_CLASS),
+ GET_MODE (x), opnum, type, ind_levels);
+ return 1;
+ }
#if 0 /* This might screw code in reload1.c to delete prior output-reload
that feeds this insn. */
- if (reg_equiv_mem[regno] != 0)
- {
- push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
- context ? INDEX_REG_CLASS : BASE_REG_CLASS,
- GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- return 1;
- }
+ if (reg_equiv_mem[regno] != 0)
+ {
+ push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
+ context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+ }
#endif
- if (reg_equiv_address[regno] != 0)
- {
- x = make_memloc (x, regno);
- find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
- opnum, type, ind_levels);
- }
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
- if ((regno >= FIRST_PSEUDO_REGISTER
- || !(context ? REGNO_OK_FOR_INDEX_P (regno)
- : REGNO_OK_FOR_BASE_P (regno))))
- {
- push_reload (x, NULL_RTX, loc, NULL_PTR,
- context ? INDEX_REG_CLASS : BASE_REG_CLASS,
- GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- return 1;
- }
+ if (reg_equiv_address[regno] != 0)
+ {
+ x = make_memloc (x, regno);
+ find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
+ opnum, type, ind_levels);
+ }
- /* If a register appearing in an address is the subject of a CLOBBER
- in this insn, reload it into some other register to be safe.
- The CLOBBER is supposed to make the register unavailable
- from before this insn to after it. */
- if (regno_clobbered_p (regno, this_insn))
- {
- push_reload (x, NULL_RTX, loc, NULL_PTR,
- context ? INDEX_REG_CLASS : BASE_REG_CLASS,
- GET_MODE (x), VOIDmode, 0, 0, opnum, type);
- return 1;
- }
- }
- else
- {
- register char *fmt = GET_RTX_FORMAT (code);
- register int i;
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
+ if ((regno >= FIRST_PSEUDO_REGISTER
+ || !(context ? REGNO_OK_FOR_INDEX_P (regno)
+ : REGNO_OK_FOR_BASE_P (regno))))
+ {
+ push_reload (x, NULL_RTX, loc, NULL_PTR,
+ context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+ }
+
+ /* If a register appearing in an address is the subject of a CLOBBER
+ in this insn, reload it into some other register to be safe.
+ The CLOBBER is supposed to make the register unavailable
+ from before this insn to after it. */
+ if (regno_clobbered_p (regno, this_insn))
+ {
+ push_reload (x, NULL_RTX, loc, NULL_PTR,
+ context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+ }
+ }
+ return 0;
+
+ case SUBREG:
+ /* If this is a SUBREG of a hard register and the resulting register is
+ of the wrong class, reload the whole SUBREG. This avoids needless
+ copies if SUBREG_REG is multi-word. */
+ if (GET_CODE (SUBREG_REG (x)) == REG
+ && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
{
- if (fmt[i] == 'e')
- find_reloads_address_1 (XEXP (x, i), context, &XEXP (x, i),
- opnum, type, ind_levels);
+ int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+
+ if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
+ : REGNO_OK_FOR_BASE_P (regno)))
+ {
+ push_reload (x, NULL_RTX, loc, NULL_PTR,
+ context ? INDEX_REG_CLASS : BASE_REG_CLASS,
+ GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ return 1;
+ }
}
+ break;
}
+ {
+ register char *fmt = GET_RTX_FORMAT (code);
+ register int i;
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ find_reloads_address_1 (XEXP (x, i), context, &XEXP (x, i),
+ opnum, type, ind_levels);
+ }
+ }
+
return 0;
}