Commit a2d353e5 by Richard Kenner

(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
parent 8bffcaf6
...@@ -2971,18 +2971,16 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) ...@@ -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 Don't bother with this if this alternative will accept this
operand. operand.
Don't do this for a multiword operand, if Don't do this for a multiword operand, since it is only a
we have to worry about small classes, because making reg groups small win and has the risk of requiring more spill registers,
harder to allocate is asking for trouble. which could cause a large loss.
Don't do this if the preferred class has only one register Don't do this if the preferred class has only one register
because we might otherwise exhaust the class. */ because we might otherwise exhaust the class. */
if (! win && this_alternative[i] != (int) NO_REGS if (! win && this_alternative[i] != (int) NO_REGS
#ifdef SMALL_REGISTER_CLASSES
&& GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
#endif
&& reg_class_size[(int) preferred_class[i]] > 1) && reg_class_size[(int) preferred_class[i]] > 1)
{ {
if (! reg_class_subset_p (this_alternative[i], if (! reg_class_subset_p (this_alternative[i],
...@@ -4408,92 +4406,107 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels) ...@@ -4408,92 +4406,107 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
{ {
register RTX_CODE code = GET_CODE (x); register RTX_CODE code = GET_CODE (x);
if (code == PLUS) switch (code)
{ {
register rtx orig_op0 = XEXP (x, 0); case PLUS:
register rtx orig_op1 = XEXP (x, 1); {
register RTX_CODE code0 = GET_CODE (orig_op0); register rtx orig_op0 = XEXP (x, 0);
register RTX_CODE code1 = GET_CODE (orig_op1); register rtx orig_op1 = XEXP (x, 1);
register rtx op0 = orig_op0; register RTX_CODE code0 = GET_CODE (orig_op0);
register rtx op1 = orig_op1; register RTX_CODE code1 = GET_CODE (orig_op1);
register rtx op0 = orig_op0;
if (GET_CODE (op0) == SUBREG) register rtx op1 = orig_op1;
{
op0 = SUBREG_REG (op0); if (GET_CODE (op0) == SUBREG)
code0 = GET_CODE (op0); {
} op0 = SUBREG_REG (op0);
if (GET_CODE (op1) == SUBREG) code0 = GET_CODE (op0);
{ }
op1 = SUBREG_REG (op1);
code1 = GET_CODE (op1);
}
if (code0 == MULT || code0 == SIGN_EXTEND || code1 == MEM) if (GET_CODE (op1) == SUBREG)
{ {
find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type, op1 = SUBREG_REG (op1);
ind_levels); code1 = GET_CODE (op1);
find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type, }
ind_levels);
} if (code0 == MULT || code0 == SIGN_EXTEND || code1 == MEM)
else if (code1 == MULT || code1 == SIGN_EXTEND || code0 == MEM) {
{ find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type,
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,
ind_levels); ind_levels);
else if (REG_OK_FOR_BASE_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); 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, find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
ind_levels); ind_levels);
else if (REG_OK_FOR_INDEX_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); ind_levels);
else }
{
find_reloads_address_1 (orig_op0, 1, &XEXP (x, 0), opnum, type, else if (code0 == CONST_INT || code0 == CONST
ind_levels); || code0 == SYMBOL_REF || code0 == LABEL_REF)
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, find_reloads_address_1 (orig_op1, 0, &XEXP (x, 1), opnum, type,
ind_levels); ind_levels);
}
else if (code1 == REG) else if (code1 == CONST_INT || code1 == CONST
{ || code1 == SYMBOL_REF || code1 == LABEL_REF)
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, find_reloads_address_1 (orig_op0, 0, &XEXP (x, 0), opnum, type,
ind_levels); ind_levels);
}
} else if (code0 == REG && code1 == REG)
else if (code == POST_INC || code == POST_DEC {
|| code == PRE_INC || code == PRE_DEC) 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) if (GET_CODE (XEXP (x, 0)) == REG)
{ {
register int regno = REGNO (XEXP (x, 0)); register int regno = REGNO (XEXP (x, 0));
...@@ -4559,6 +4572,7 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels) ...@@ -4559,6 +4572,7 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
} }
return value; return value;
} }
else if (GET_CODE (XEXP (x, 0)) == MEM) else if (GET_CODE (XEXP (x, 0)) == MEM)
{ {
/* This is probably the result of a substitution, by eliminate_regs, /* 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) ...@@ -4591,16 +4605,16 @@ find_reloads_address_1 (x, context, loc, opnum, type, ind_levels)
return 1; return 1;
} }
} return 0;
else if (code == MEM)
{ case MEM:
/* This is probably the result of a substitution, by eliminate_regs, /* This is probably the result of a substitution, by eliminate_regs, of
of an equivalent address for a pseudo that was not allocated to a an equivalent address for a pseudo that was not allocated to a hard
hard register. Verify that the specified address is valid and reload register. Verify that the specified address is valid and reload it
it into a register. into a register.
Since we know we are going to reload this item, don't decrement Since we know we are going to reload this item, don't decrement for
for the indirection level. the indirection level.
Note that this is actually conservative: it would be slightly more Note that this is actually conservative: it would be slightly more
efficient to use the value of SPILL_INDIRECT_LEVELS from 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) ...@@ -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), find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, type, ind_levels); opnum, type, ind_levels);
push_reload (*loc, NULL_RTX, loc, NULL_PTR, push_reload (*loc, NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS, context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, opnum, type); GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1; return 1;
}
else if (code == REG)
{
register int regno = REGNO (x);
if (reg_equiv_constant[regno] != 0) case REG:
{ {
find_reloads_address_part (reg_equiv_constant[regno], loc, register int regno = REGNO (x);
(context ? INDEX_REG_CLASS
: BASE_REG_CLASS), if (reg_equiv_constant[regno] != 0)
GET_MODE (x), opnum, type, ind_levels); {
return 1; 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 #if 0 /* This might screw code in reload1.c to delete prior output-reload
that feeds this insn. */ that feeds this insn. */
if (reg_equiv_mem[regno] != 0) if (reg_equiv_mem[regno] != 0)
{ {
push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR, push_reload (reg_equiv_mem[regno], NULL_RTX, loc, NULL_PTR,
context ? INDEX_REG_CLASS : BASE_REG_CLASS, context ? INDEX_REG_CLASS : BASE_REG_CLASS,
GET_MODE (x), VOIDmode, 0, 0, opnum, type); GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1; return 1;
} }
#endif #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) if (reg_equiv_address[regno] != 0)
regno = reg_renumber[regno]; {
if ((regno >= FIRST_PSEUDO_REGISTER x = make_memloc (x, regno);
|| !(context ? REGNO_OK_FOR_INDEX_P (regno) find_reloads_address (GET_MODE (x), 0, XEXP (x, 0), &XEXP (x, 0),
: REGNO_OK_FOR_BASE_P (regno)))) opnum, type, ind_levels);
{ }
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 if (reg_renumber[regno] >= 0)
in this insn, reload it into some other register to be safe. regno = reg_renumber[regno];
The CLOBBER is supposed to make the register unavailable
from before this insn to after it. */ if ((regno >= FIRST_PSEUDO_REGISTER
if (regno_clobbered_p (regno, this_insn)) || !(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, push_reload (x, NULL_RTX, loc, NULL_PTR,
GET_MODE (x), VOIDmode, 0, 0, opnum, type); context ? INDEX_REG_CLASS : BASE_REG_CLASS,
return 1; GET_MODE (x), VOIDmode, 0, 0, opnum, type);
} return 1;
} }
else
{ /* If a register appearing in an address is the subject of a CLOBBER
register char *fmt = GET_RTX_FORMAT (code); in this insn, reload it into some other register to be safe.
register int i; The CLOBBER is supposed to make the register unavailable
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) 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') int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
find_reloads_address_1 (XEXP (x, i), context, &XEXP (x, i),
opnum, type, ind_levels); 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; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment