summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/reload.c50
-rw-r--r--gcc/reload.h3
-rw-r--r--gcc/reload1.c59
4 files changed, 83 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5cc14f3d28b..532a9c6bfd5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2000-11-10 Bernd Schmidt <bernds@redhat.co.uk>
+
+ * reload.c (find_reloads_address_1, case POST_MODIFY): Use RELOAD_OTHER
+ for address reloads. Push replacements for REG_INC notes.
+ (regno_clobbered_p): New arg SETS. Examine SETs if it's nonzero. All
+ callers changed.
+ * reload1.c (choose_reload_regs): Registers set in the insn can't be
+ used for RELOAD_OTHER reloads.
+
2000-11-10 Mark Mitchell <mark@codesourcery.com>
* c-dump.h: New file.
diff --git a/gcc/reload.c b/gcc/reload.c
index 65a5e731b41..86d80c1af23 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -4536,7 +4536,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
else if (regno < FIRST_PSEUDO_REGISTER
&& REGNO_MODE_OK_FOR_BASE_P (regno, mode)
- && ! regno_clobbered_p (regno, this_insn, mode))
+ && ! regno_clobbered_p (regno, this_insn, mode, 0))
return 0;
/* If we do not have one of the cases above, we must do the reload. */
@@ -5155,7 +5155,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
if (REG_P (XEXP (op1, 0)))
{
- register int regno = REGNO (XEXP (op1, 0));
+ rtx link;
+ int regno = REGNO (XEXP (op1, 0));
+ int reloadnum;
/* A register that is incremented cannot be constant! */
if (regno >= FIRST_PSEUDO_REGISTER
@@ -5178,15 +5180,17 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
write back the value after reading it, hence we actually
need two registers. */
find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, type,
+ &XEXP (tem, 0), opnum,
+ RELOAD_OTHER,
ind_levels, insn);
/* Then reload the memory location into a base
register. */
- push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0),
- BASE_REG_CLASS, GET_MODE (x), GET_MODE (x),
- 0, 0, opnum, RELOAD_OTHER);
- break;
+ reloadnum = push_reload (tem, tem, &XEXP (x, 0),
+ &XEXP (op1, 0), BASE_REG_CLASS,
+ GET_MODE (x), GET_MODE (x), 0,
+ 0, opnum, RELOAD_OTHER);
+ goto reg_inc;
}
}
@@ -5196,12 +5200,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
/* We require a base register here... */
if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x)))
{
- push_reload (XEXP (op1, 0), XEXP (x, 0),
- &XEXP (op1, 0), &XEXP (x, 0),
- BASE_REG_CLASS,
- GET_MODE (x), GET_MODE (x), 0, 0,
- opnum, RELOAD_OTHER);
+ reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
+ &XEXP (op1, 0), &XEXP (x, 0),
+ BASE_REG_CLASS,
+ GET_MODE (x), GET_MODE (x), 0, 0,
+ opnum, RELOAD_OTHER);
}
+
+ /* Update the REG_INC notes. */
+ reg_inc:
+ for (link = REG_NOTES (this_insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_INC
+ && REGNO (XEXP (link, 0)) == regno)
+ push_replacement (&XEXP (link, 0), reloadnum, VOIDmode);
}
else
abort ();
@@ -5441,7 +5452,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
in this insn, reload it into some other register to be safe.
The CLOBBER is supposed to make the register unavailable
from before this insn to after it. */
- if (regno_clobbered_p (regno, this_insn, GET_MODE (x)))
+ if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
{
push_reload (x, NULL_RTX, loc, NULL_PTR,
(context ? INDEX_REG_CLASS : BASE_REG_CLASS),
@@ -6552,18 +6563,21 @@ find_inc_amount (x, inced)
return 0;
}
-/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */
+/* Return 1 if register REGNO is the subject of a clobber in insn INSN.
+ If SETS is nonzero, also consider SETs. */
int
-regno_clobbered_p (regno, insn, mode)
+regno_clobbered_p (regno, insn, mode, sets)
unsigned int regno;
rtx insn;
enum machine_mode mode;
+ int sets;
{
int nregs = HARD_REGNO_NREGS (regno, mode);
int endregno = regno + nregs;
- if (GET_CODE (PATTERN (insn)) == CLOBBER
+ if ((GET_CODE (PATTERN (insn)) == CLOBBER
+ || (sets && GET_CODE (PATTERN (insn)) == SET))
&& GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
{
int test = REGNO (XEXP (PATTERN (insn), 0));
@@ -6578,7 +6592,9 @@ regno_clobbered_p (regno, insn, mode)
for (; i >= 0; i--)
{
rtx elt = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG)
+ if ((GET_CODE (elt) == CLOBBER
+ || (sets && GET_CODE (PATTERN (insn)) == SET))
+ && GET_CODE (XEXP (elt, 0)) == REG)
{
int test = REGNO (XEXP (elt, 0));
diff --git a/gcc/reload.h b/gcc/reload.h
index a2df3b1caa5..7841c7ad7d1 100644
--- a/gcc/reload.h
+++ b/gcc/reload.h
@@ -335,7 +335,8 @@ extern rtx find_equiv_reg PARAMS ((rtx, rtx, enum reg_class, int, short *,
int, enum machine_mode));
/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */
-extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode));
+extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode,
+ int));
/* Return 1 if X is an operand of an insn that is being earlyclobbered. */
int earlyclobber_operand_p PARAMS ((rtx));
diff --git a/gcc/reload1.c b/gcc/reload1.c
index dbe13fa6f51..fe749293dbf 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -5544,25 +5544,44 @@ choose_reload_regs (chain)
In particular, we then can't use EQUIV for a
RELOAD_FOR_OUTPUT_ADDRESS reload. */
- if (equiv != 0 && regno_clobbered_p (regno, insn, rld[r].mode))
- {
- switch (rld[r].when_needed)
- {
- case RELOAD_FOR_OTHER_ADDRESS:
- case RELOAD_FOR_INPADDR_ADDRESS:
- case RELOAD_FOR_INPUT_ADDRESS:
- case RELOAD_FOR_OPADDR_ADDR:
- break;
- case RELOAD_OTHER:
- case RELOAD_FOR_INPUT:
- case RELOAD_FOR_OPERAND_ADDRESS:
- if (! rld[r].optional)
- reload_override_in[r] = equiv;
- /* Fall through. */
- default:
- equiv = 0;
- break;
- }
+ if (equiv != 0)
+ {
+ if (regno_clobbered_p (regno, insn, rld[r].mode, 0))
+ switch (rld[r].when_needed)
+ {
+ case RELOAD_FOR_OTHER_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_OPADDR_ADDR:
+ break;
+ case RELOAD_OTHER:
+ case RELOAD_FOR_INPUT:
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ if (! rld[r].optional)
+ reload_override_in[r] = equiv;
+ /* Fall through. */
+ default:
+ equiv = 0;
+ break;
+ }
+ else if (regno_clobbered_p (regno, insn, rld[r].mode, 1))
+ switch (rld[r].when_needed)
+ {
+ case RELOAD_FOR_OTHER_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_OPADDR_ADDR:
+ case RELOAD_FOR_OPERAND_ADDRESS:
+ case RELOAD_FOR_INPUT:
+ break;
+ case RELOAD_OTHER:
+ if (! rld[r].optional)
+ reload_override_in[r] = equiv;
+ /* Fall through. */
+ default:
+ equiv = 0;
+ break;
+ }
}
/* If we found an equivalent reg, say no code need be generated
@@ -6567,7 +6586,7 @@ emit_output_reload_insns (chain, rl, j)
|| !(set = single_set (insn))
|| rtx_equal_p (old, SET_DEST (set))
|| !reg_mentioned_p (old, SET_SRC (set))
- || !regno_clobbered_p (REGNO (old), insn, rl->mode))
+ || !regno_clobbered_p (REGNO (old), insn, rl->mode, 0))
gen_reload (old, reloadreg, rl->opnum,
rl->when_needed);
}