summaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>2004-02-06 05:58:11 +0000
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>2004-02-06 05:58:11 +0000
commit9feec5c7c3cc304b6c9b6d97a6a6d53d4e86e862 (patch)
tree069e6abdb4fa637c3c8989691451d99fc06b5044 /gcc/reload1.c
parent39cc9599f82417be8a7b53a76aeaa649a08b1814 (diff)
downloadgcc-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.c54
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 < &reg_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. */