(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
This commit is contained in:
parent
8bffcaf6a0
commit
a2d353e50c
332
gcc/reload.c
332
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;
|
||||
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 (GET_CODE (op1) == SUBREG)
|
||||
{
|
||||
op1 = SUBREG_REG (op1);
|
||||
code1 = GET_CODE (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,
|
||||
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);
|
||||
}
|
||||
|
||||
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 == 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;
|
||||
|
||||
Since we know we are going to reload this item, don't decrement
|
||||
for the indirection level.
|
||||
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.
|
||||
|
||||
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))
|
||||
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)
|
||||
{
|
||||
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 (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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user