reload.c (find_reloads_address_1): Handle PLUS expressions resulting from register elimination as PRE_MODIFY /...
* reload.c (find_reloads_address_1): Handle PLUS expressions resulting from register elimination as PRE_MODIFY / POST_MODIFY increments. Do not attempt to handle MEM inside auto-inc expressions. * reload1.c (eliminate_regs_1): Do not attempt to handle elimination of a register modified by an auto-inc expression. However, do handle elimination of a register used as PRE_MODIFY / POST_MODIFY increment. (elimination_effects): Prohibit elimination of a register modified by an auto-inc expression. Disable register elimination rules whose target register is modified by an auto-inc expression with variable increment. From-SVN: r122318
This commit is contained in:
parent
ae19c0415c
commit
b098aaf2ae
3 changed files with 63 additions and 47 deletions
|
@ -1,3 +1,16 @@
|
|||
2007-02-25 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* reload.c (find_reloads_address_1): Handle PLUS expressions resulting
|
||||
from register elimination as PRE_MODIFY / POST_MODIFY increments.
|
||||
Do not attempt to handle MEM inside auto-inc expressions.
|
||||
* reload1.c (eliminate_regs_1): Do not attempt to handle elimination
|
||||
of a register modified by an auto-inc expression. However, do handle
|
||||
elimination of a register used as PRE_MODIFY / POST_MODIFY increment.
|
||||
(elimination_effects): Prohibit elimination of a register modified
|
||||
by an auto-inc expression. Disable register elimination rules whose
|
||||
target register is modified by an auto-inc expression with variable
|
||||
increment.
|
||||
|
||||
2007-02-25 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* tree-ssa-loop-niter.c (compute_estimated_nb_iterations): Fix
|
||||
|
|
51
gcc/reload.c
51
gcc/reload.c
|
@ -5543,16 +5543,20 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
|
|||
auto-modify by a constant then we could try replacing a pseudo
|
||||
register with its equivalent constant where applicable.
|
||||
|
||||
We also handle the case where the register was eliminated
|
||||
resulting in a PLUS subexpression.
|
||||
|
||||
If we later decide to reload the whole PRE_MODIFY or
|
||||
POST_MODIFY, inc_for_reload might clobber the reload register
|
||||
before reading the index. The index register might therefore
|
||||
need to live longer than a TYPE reload normally would, so be
|
||||
conservative and class it as RELOAD_OTHER. */
|
||||
if (REG_P (XEXP (op1, 1)))
|
||||
if (!REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
|
||||
find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
|
||||
&XEXP (op1, 1), opnum, RELOAD_OTHER,
|
||||
ind_levels, insn);
|
||||
if ((REG_P (XEXP (op1, 1))
|
||||
&& !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
|
||||
|| GET_CODE (XEXP (op1, 1)) == PLUS)
|
||||
find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
|
||||
&XEXP (op1, 1), opnum, RELOAD_OTHER,
|
||||
ind_levels, insn);
|
||||
|
||||
gcc_assert (REG_P (XEXP (op1, 0)));
|
||||
|
||||
|
@ -5733,43 +5737,6 @@ find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
|
|||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
else if (MEM_P (XEXP (x, 0)))
|
||||
{
|
||||
/* 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. */
|
||||
/* Variable `tem' might or might not be used in FIND_REG_INC_NOTE. */
|
||||
rtx tem ATTRIBUTE_UNUSED = XEXP (x, 0);
|
||||
rtx link;
|
||||
int reloadnum;
|
||||
|
||||
/* 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
|
||||
reload1.c here. */
|
||||
/* We can't use ADDR_TYPE (type) here, because we need to
|
||||
write back the value after reading it, hence we actually
|
||||
need two registers. */
|
||||
find_reloads_address (GET_MODE (x), &XEXP (x, 0),
|
||||
XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
|
||||
opnum, type, ind_levels, insn);
|
||||
|
||||
reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
|
||||
context_reg_class,
|
||||
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
|
||||
rld[reloadnum].inc
|
||||
= find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
|
||||
|
||||
link = FIND_REG_INC_NOTE (this_insn, tem);
|
||||
if (link != 0)
|
||||
push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case TRUNCATE:
|
||||
|
|
|
@ -2548,6 +2548,30 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
|
|||
case POST_INC:
|
||||
case PRE_DEC:
|
||||
case POST_DEC:
|
||||
/* We do not support elimination of a register that is modified.
|
||||
elimination_effects has already make sure that this does not
|
||||
happen. */
|
||||
return x;
|
||||
|
||||
case PRE_MODIFY:
|
||||
case POST_MODIFY:
|
||||
/* We do not support elimination of a register that is modified.
|
||||
elimination_effects has already make sure that this does not
|
||||
happen. The only remaining case we need to consider here is
|
||||
that the increment value may be an eliminable register. */
|
||||
if (GET_CODE (XEXP (x, 1)) == PLUS
|
||||
&& XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
|
||||
{
|
||||
rtx new = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
|
||||
insn, true);
|
||||
|
||||
if (new != XEXP (XEXP (x, 1), 1))
|
||||
return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
|
||||
gen_rtx_PLUS (GET_MODE (x),
|
||||
XEXP (x, 0), new));
|
||||
}
|
||||
return x;
|
||||
|
||||
case STRICT_LOW_PART:
|
||||
case NEG: case NOT:
|
||||
case SIGN_EXTEND: case ZERO_EXTEND:
|
||||
|
@ -2743,6 +2767,14 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
|
|||
case POST_DEC:
|
||||
case POST_MODIFY:
|
||||
case PRE_MODIFY:
|
||||
/* If we modify the source of an elimination rule, disable it. */
|
||||
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
||||
if (ep->from_rtx == XEXP (x, 0))
|
||||
ep->can_eliminate = 0;
|
||||
|
||||
/* If we modify the target of an elimination rule by adding a constant,
|
||||
update its offset. If we modify the target in any other way, we'll
|
||||
have to disable the rule as well. */
|
||||
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
||||
if (ep->to_rtx == XEXP (x, 0))
|
||||
{
|
||||
|
@ -2757,11 +2789,15 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
|
|||
ep->offset += size;
|
||||
else if (code == PRE_INC || code == POST_INC)
|
||||
ep->offset -= size;
|
||||
else if ((code == PRE_MODIFY || code == POST_MODIFY)
|
||||
&& GET_CODE (XEXP (x, 1)) == PLUS
|
||||
&& XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
|
||||
&& CONSTANT_P (XEXP (XEXP (x, 1), 1)))
|
||||
ep->offset -= INTVAL (XEXP (XEXP (x, 1), 1));
|
||||
else if (code == PRE_MODIFY || code == POST_MODIFY)
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) == PLUS
|
||||
&& XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
|
||||
&& CONST_INT_P (XEXP (XEXP (x, 1), 1)))
|
||||
ep->offset -= INTVAL (XEXP (XEXP (x, 1), 1));
|
||||
else
|
||||
ep->can_eliminate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* These two aren't unary operators. */
|
||||
|
|
Loading…
Add table
Reference in a new issue