From cc6757ec825d05ba36419234bdcfea6bf03079d1 Mon Sep 17 00:00:00 2001 From: uweigand Date: Sun, 25 Feb 2007 20:56:46 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122318 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 13 +++++++++++++ gcc/reload.c | 51 +++++++++------------------------------------------ gcc/reload1.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 63 insertions(+), 47 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e835441970b..2ed49124480 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2007-02-25 Ulrich Weigand + + * 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 * tree-ssa-loop-niter.c (compute_estimated_nb_iterations): Fix diff --git a/gcc/reload.c b/gcc/reload.c index 21c5ed20026..c297494f119 100644 --- a/gcc/reload.c +++ b/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: diff --git a/gcc/reload1.c b/gcc/reload1.c index c86b2bd429f..c469fb07618 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -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. */ -- 2.11.0