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:
Ulrich Weigand 2007-02-25 20:56:46 +00:00 committed by Ulrich Weigand
parent ae19c0415c
commit b098aaf2ae
3 changed files with 63 additions and 47 deletions

View file

@ -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

View file

@ -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:

View file

@ -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 < &reg_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 < &reg_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. */