diff options
author | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-02-06 05:58:11 +0000 |
---|---|---|
committer | kazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-02-06 05:58:11 +0000 |
commit | 9feec5c7c3cc304b6c9b6d97a6a6d53d4e86e862 (patch) | |
tree | 069e6abdb4fa637c3c8989691451d99fc06b5044 /gcc/reload1.c | |
parent | 39cc9599f82417be8a7b53a76aeaa649a08b1814 (diff) | |
download | gcc-9feec5c7c3cc304b6c9b6d97a6a6d53d4e86e862.tar.gz |
* reload1.c (eliminate_regs_in_insn): If a set has a REG_EQUAL
note containing (plus (reg) (const_int)), where reg is an
eliminable reg, then perform the register elimination without
depending on eliminate_regs().
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@77378 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r-- | gcc/reload1.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c index c24f4ac7be0..171283c4b55 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -2879,6 +2879,7 @@ eliminate_regs_in_insn (rtx insn, int replace) rtx substed_operand[MAX_RECOG_OPERANDS]; rtx orig_operand[MAX_RECOG_OPERANDS]; struct elim_table *ep; + rtx plus_src; if (! insn_is_asm && icode < 0) { @@ -2982,17 +2983,40 @@ eliminate_regs_in_insn (rtx insn, int replace) } /* We allow one special case which happens to work on all machines we - currently support: a single set with the source being a PLUS of an - eliminable register and a constant. */ - if (old_set - && GET_CODE (SET_DEST (old_set)) == REG - && GET_CODE (SET_SRC (old_set)) == PLUS - && GET_CODE (XEXP (SET_SRC (old_set), 0)) == REG - && GET_CODE (XEXP (SET_SRC (old_set), 1)) == CONST_INT - && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER) + currently support: a single set with the source or a REG_EQUAL + note being a PLUS of an eliminable register and a constant. */ + plus_src = 0; + if (old_set && GET_CODE (SET_DEST (old_set)) == REG) { - rtx reg = XEXP (SET_SRC (old_set), 0); - HOST_WIDE_INT offset = INTVAL (XEXP (SET_SRC (old_set), 1)); + /* First see if the source is of the form (plus (reg) CST). */ + if (GET_CODE (SET_SRC (old_set)) == PLUS + && GET_CODE (XEXP (SET_SRC (old_set), 0)) == REG + && GET_CODE (XEXP (SET_SRC (old_set), 1)) == CONST_INT + && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER) + plus_src = SET_SRC (old_set); + else if (GET_CODE (SET_SRC (old_set)) == REG) + { + /* Otherwise, see if we have a REG_EQUAL note of the form + (plus (reg) CST). */ + rtx links; + for (links = REG_NOTES (insn); links; links = XEXP (links, 1)) + { + if (REG_NOTE_KIND (links) == REG_EQUAL + && GET_CODE (XEXP (links, 0)) == PLUS + && GET_CODE (XEXP (XEXP (links, 0), 0)) == REG + && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT + && REGNO (XEXP (XEXP (links, 0), 0)) < FIRST_PSEUDO_REGISTER) + { + plus_src = XEXP (links, 0); + break; + } + } + } + } + if (plus_src) + { + rtx reg = XEXP (plus_src, 0); + HOST_WIDE_INT offset = INTVAL (XEXP (plus_src, 1)); for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) if (ep->from_rtx == reg && ep->can_eliminate) @@ -3022,7 +3046,12 @@ eliminate_regs_in_insn (rtx insn, int replace) if (INSN_CODE (insn) < 0) abort (); } - else + /* If we have a nonzero offset, and the source is already + a simple REG, the following transformation would + increase the cost of the insn by replacing a simple REG + with (plus (reg sp) CST). So try only when plus_src + comes from old_set proper, not REG_NOTES. */ + else if (SET_SRC (old_set) == plus_src) { new_body = old_body; if (! replace) @@ -3037,6 +3066,9 @@ eliminate_regs_in_insn (rtx insn, int replace) XEXP (SET_SRC (old_set), 0) = ep->to_rtx; XEXP (SET_SRC (old_set), 1) = GEN_INT (offset); } + else + break; + val = 1; /* This can't have an effect on elimination offsets, so skip right to the end. */ |