aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@cygnus.co.uk>2000-03-09 16:01:10 +0000
committerBernd Schmidt <crux@gcc.gnu.org>2000-03-09 16:01:10 +0000
commitaa5524a98e895542d7ce243bca3f3f0646f1ccb6 (patch)
tree2920d7b1f8f838a3962928b1195fa0fa7e34ca41
parentfb863f625e01b70f4e8335b81c66d5f41c2dc54a (diff)
downloadgcc-aa5524a98e895542d7ce243bca3f3f0646f1ccb6.zip
gcc-aa5524a98e895542d7ce243bca3f3f0646f1ccb6.tar.gz
gcc-aa5524a98e895542d7ce243bca3f3f0646f1ccb6.tar.bz2
Fix suboptimal code generation by register elimination
From-SVN: r32446
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/reload1.c80
2 files changed, 53 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0470a0b..c721bf5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2000-03-09 Bernd Schmidt <bernds@cygnus.co.uk>
+
+ * reload1.c (eliminate_regs_in_insn): Handle additions of eliminable
+ register and a constant specially.
+
2000-03-08 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* libgcc2.h: New file.
diff --git a/gcc/reload1.c b/gcc/reload1.c
index e91cf6f..a716b13 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -2903,41 +2903,57 @@ eliminate_regs_in_insn (insn, replace)
val = 1;
goto done;
}
+ }
- /* Check for (set (reg) (plus (reg from) (offset))) where the offset
- in the insn is the negative of the offset in FROM. Substitute
- (set (reg) (reg to)) for the insn and change its code.
+ /* 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_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)
+ {
+ rtx reg = XEXP (SET_SRC (old_set), 0);
+ int offset = INTVAL (XEXP (SET_SRC (old_set), 1));
- We have to do this here, rather than in eliminate_regs, so that we can
- change the insn code. */
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (ep->from_rtx == reg && ep->can_eliminate)
+ {
+ offset += ep->offset;
- 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)
- for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
- ep++)
- if (ep->from_rtx == XEXP (SET_SRC (old_set), 0)
- && ep->can_eliminate)
- {
- /* We must stop at the first elimination that will be used.
- If this one would replace the PLUS with a REG, do it
- now. Otherwise, quit the loop and let eliminate_regs
- do its normal replacement. */
- if (ep->offset == - INTVAL (XEXP (SET_SRC (old_set), 1)))
- {
- /* We assume here that we don't need a PARALLEL of
- any CLOBBERs for this assignment. There's not
- much we can do if we do need it. */
- PATTERN (insn) = gen_rtx_SET (VOIDmode,
- SET_DEST (old_set),
- ep->to_rtx);
- INSN_CODE (insn) = -1;
- val = 1;
- goto done;
- }
+ if (offset == 0)
+ {
+ /* We assume here that we don't need a PARALLEL of
+ any CLOBBERs for this assignment. There's not
+ much we can do if we do need it. */
+ PATTERN (insn) = gen_rtx_SET (VOIDmode,
+ SET_DEST (old_set),
+ ep->to_rtx);
+ INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
+ if (INSN_CODE (insn) < 0)
+ abort ();
+ }
+ else
+ {
+ new_body = old_body;
+ if (! replace)
+ {
+ new_body = copy_insn (old_body);
+ if (REG_NOTES (insn))
+ REG_NOTES (insn) = copy_insn_1 (REG_NOTES (insn));
+ }
+ PATTERN (insn) = new_body;
+ old_set = single_set (insn);
- break;
- }
+ XEXP (SET_SRC (old_set), 0) = ep->to_rtx;
+ XEXP (SET_SRC (old_set), 1) = GEN_INT (offset);
+ }
+ val = 1;
+ /* This can't have an effect on elimination offsets, so skip right
+ to the end. */
+ goto done;
+ }
}
/* Determine the effects of this insn on elimination offsets. */
@@ -2990,7 +3006,7 @@ eliminate_regs_in_insn (insn, replace)
for (i = 0; i < recog_data.n_dups; i++)
*recog_data.dup_loc[i]
- = *recog_data.operand_loc[(int)recog_data.dup_num[i]];
+ = *recog_data.operand_loc[(int)recog_data.dup_num[i]];
/* If any eliminable remain, they aren't eliminable anymore. */
check_eliminable_occurrences (old_body);