This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: RFC: remove find_replacement. (pr24912 / pr25335)
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: Ulrich Weigand <uweigand at de dot ibm dot com>
- Cc: David Edelsohn <dje at watson dot ibm dot com>, Bernd Schmidt <bernds_cb1 at t-online dot de>, kenner at nyu dot edu, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 07 Feb 2006 23:40:33 +0000
- Subject: Re: RFC: remove find_replacement. (pr24912 / pr25335)
- References: <200602030121.k131LRZx026479@d12av02.megacenter.de.ibm.com>
Ulrich Weigand wrote:
The culprit appears to be not reload inheritance proper, but this last-
minute attempt in emit_input_reload_insns:
/* If reloading from memory, see if there is a register
that already holds the same value. If so, reload from there.
We can pass 0 as the reload_reg_p argument because
any other reload has either already been emitted,
in which case find_equiv_reg will see the reload-insn,
or has yet to be emitted, in which case it doesn't matter
because we will use this equiv reg right away. */
Does the attached patch work for you?
2006-02-07 J"orn Rennecke <joern.rennecke@st.com>
* reload1.c (reload_as_needed): Call subst_reloads before
emit_reload_insns.
(gen_reload): Don't call find_replacement.
* reload.c (find_replacement): Remove.
* reload.h (find_replacement): Don't declare.
* expr.c (emit_move_multi_word): Don't use find_replacement.
* alpha.c (get_aligned_mem, get_unaligned_address): Likewise.
* s390.c (s390_expand_plus_operand): Likewise.
* s390.md (reload_outti, reload_outdi, reload_outdf): Likewise.
* m68k.c (emit_move_sequence): Likewise.
* arm.c (arm_reload_in_hi, arm_reload_out_hi): Likewise.
* pa.c (emit_move_sequence): Likewise.
* reload1.c (reconsider_reload_override) New function, broken out of:
(emit_input_reload_insns).
(reload_by_redirect): Likewise.
(reconsider_reload_regs): New function.
(reload_as_needed): Call it.
Index: reload.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L reload.c (revision 110699) -L reload.c (working copy) .svn/text-base/reload.c.svn-base reload.c
--- reload.c (revision 110699)
+++ reload.c (working copy)
@@ -6122,69 +6122,6 @@ move_replacements (rtx *x, rtx *y)
}
}
-/* If LOC was scheduled to be replaced by something, return the replacement.
- Otherwise, return *LOC. */
-
-rtx
-find_replacement (rtx *loc)
-{
- struct replacement *r;
-
- for (r = &replacements[0]; r < &replacements[n_replacements]; r++)
- {
- rtx reloadreg = rld[r->what].reg_rtx;
-
- if (reloadreg && r->where == loc)
- {
- if (r->mode != VOIDmode && GET_MODE (reloadreg) != r->mode)
- reloadreg = gen_rtx_REG (r->mode, REGNO (reloadreg));
-
- return reloadreg;
- }
- else if (reloadreg && r->subreg_loc == loc)
- {
- /* RELOADREG must be either a REG or a SUBREG.
-
- ??? Is it actually still ever a SUBREG? If so, why? */
-
- if (REG_P (reloadreg))
- return gen_rtx_REG (GET_MODE (*loc),
- (REGNO (reloadreg) +
- subreg_regno_offset (REGNO (SUBREG_REG (*loc)),
- GET_MODE (SUBREG_REG (*loc)),
- SUBREG_BYTE (*loc),
- GET_MODE (*loc))));
- else if (GET_MODE (reloadreg) == GET_MODE (*loc))
- return reloadreg;
- else
- {
- int final_offset = SUBREG_BYTE (reloadreg) + SUBREG_BYTE (*loc);
-
- /* When working with SUBREGs the rule is that the byte
- offset must be a multiple of the SUBREG's mode. */
- final_offset = (final_offset / GET_MODE_SIZE (GET_MODE (*loc)));
- final_offset = (final_offset * GET_MODE_SIZE (GET_MODE (*loc)));
- return gen_rtx_SUBREG (GET_MODE (*loc), SUBREG_REG (reloadreg),
- final_offset);
- }
- }
- }
-
- /* If *LOC is a PLUS, MINUS, or MULT, see if a replacement is scheduled for
- what's inside and make a new rtl if so. */
- if (GET_CODE (*loc) == PLUS || GET_CODE (*loc) == MINUS
- || GET_CODE (*loc) == MULT)
- {
- rtx x = find_replacement (&XEXP (*loc, 0));
- rtx y = find_replacement (&XEXP (*loc, 1));
-
- if (x != XEXP (*loc, 0) || y != XEXP (*loc, 1))
- return gen_rtx_fmt_ee (GET_CODE (*loc), GET_MODE (*loc), x, y);
- }
-
- return *loc;
-}
-
/* Return nonzero if register in range [REGNO, ENDREGNO)
appears either explicitly or implicitly in X
other than being stored into (except for earlyclobber operands).
Index: reload.h
===================================================================
/usr/bin/diff -p -d -F^( -u -L reload.h (revision 110699) -L reload.h (working copy) .svn/text-base/reload.h.svn-base reload.h
--- reload.h (revision 110699)
+++ reload.h (working copy)
@@ -300,10 +300,6 @@ extern void copy_replacements (rtx, rtx)
/* Change any replacements being done to *X to be done to *Y */
extern void move_replacements (rtx *x, rtx *y);
-/* If LOC was scheduled to be replaced by something, return the replacement.
- Otherwise, return *LOC. */
-extern rtx find_replacement (rtx *);
-
/* Nonzero if modifying X will affect IN. */
extern int reg_overlap_mentioned_for_reload_p (rtx, rtx);
Index: expr.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L expr.c (revision 110699) -L expr.c (working copy) .svn/text-base/expr.c.svn-base expr.c
--- expr.c (revision 110699)
+++ expr.c (working copy)
@@ -3046,7 +3046,7 @@ static rtx
emit_move_multi_word (enum machine_mode mode, rtx x, rtx y)
{
rtx last_insn = 0;
- rtx seq, inner;
+ rtx seq;
bool need_clobber;
int i;
@@ -3057,15 +3057,6 @@ emit_move_multi_word (enum machine_mode
if (push_operand (x, mode))
x = emit_move_resolve_push (mode, x);
- /* If we are in reload, see if either operand is a MEM whose address
- is scheduled for replacement. */
- if (reload_in_progress && MEM_P (x)
- && (inner = find_replacement (&XEXP (x, 0))) != XEXP (x, 0))
- x = replace_equiv_address_nv (x, inner);
- if (reload_in_progress && MEM_P (y)
- && (inner = find_replacement (&XEXP (y, 0))) != XEXP (y, 0))
- y = replace_equiv_address_nv (y, inner);
-
start_sequence ();
need_clobber = false;
Index: config/alpha/alpha.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/alpha/alpha.c (revision 110699) -L config/alpha/alpha.c (working copy) config/alpha/.svn/text-base/alpha.c.svn-base config/alpha/alpha.c
--- config/alpha/alpha.c (revision 110699)
+++ config/alpha/alpha.c (working copy)
@@ -1509,7 +1509,7 @@ get_aligned_mem (rtx ref, rtx *paligned_
if (reload_in_progress
&& ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
{
- base = find_replacement (&XEXP (ref, 0));
+ base = XEXP (ref, 0);
gcc_assert (memory_address_p (GET_MODE (ref), base));
}
else
@@ -1554,7 +1554,7 @@ get_unaligned_address (rtx ref, int extr
if (reload_in_progress
&& ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
{
- base = find_replacement (&XEXP (ref, 0));
+ base = XEXP (ref, 0);
gcc_assert (memory_address_p (GET_MODE (ref), base));
}
Index: config/s390/s390.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/s390/s390.c (revision 110699) -L config/s390/s390.c (working copy) config/s390/.svn/text-base/s390.c.svn-base config/s390/s390.c
--- config/s390/s390.c (revision 110699)
+++ config/s390/s390.c (working copy)
@@ -2667,8 +2667,8 @@ s390_expand_plus_operand (rtx target, rt
/* Check if any of the two operands is already scheduled
for replacement by reload. This can happen e.g. when
float registers occur in an address. */
- sum1 = find_replacement (&XEXP (src, 0));
- sum2 = find_replacement (&XEXP (src, 1));
+ sum1 = XEXP (src, 0);
+ sum2 = XEXP (src, 1);
src = gen_rtx_PLUS (Pmode, sum1, sum2);
/* If the address is already strictly valid, there's nothing to do. */
@@ -2691,8 +2691,7 @@ s390_expand_plus_operand (rtx target, rt
/* According to the way these invalid addresses are generated
in reload.c, it should never happen (at least on s390) that
- *neither* of the PLUS components, after find_replacements
- was applied, is an address register. */
+ *neither* of the PLUS components is an address register. */
if (sum1 == scratch && sum2 == scratch)
{
debug_rtx (src);
Index: config/s390/s390.md
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/s390/s390.md (revision 110699) -L config/s390/s390.md (working copy) config/s390/.svn/text-base/s390.md.svn-base config/s390/s390.md
--- config/s390/s390.md (revision 110699)
+++ config/s390/s390.md (working copy)
@@ -883,7 +883,7 @@ (define_expand "reload_outti"
"TARGET_64BIT"
{
gcc_assert (MEM_P (operands[0]));
- s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
+ s390_load_address (operands[2], XEXP (operands[0], 0));
operands[0] = replace_equiv_address (operands[0], operands[2]);
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -1078,7 +1078,7 @@ (define_expand "reload_outdi"
"!TARGET_64BIT"
{
gcc_assert (MEM_P (operands[0]));
- s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
+ s390_load_address (operands[2], XEXP (operands[0], 0));
operands[0] = replace_equiv_address (operands[0], operands[2]);
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -1686,7 +1686,7 @@ (define_expand "reload_outdf"
"!TARGET_64BIT"
{
gcc_assert (MEM_P (operands[0]));
- s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
+ s390_load_address (operands[2], XEXP (operands[0], 0));
operands[0] = replace_equiv_address (operands[0], operands[2]);
emit_move_insn (operands[0], operands[1]);
DONE;
Index: config/m68k/m68k.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/m68k/m68k.c (revision 110699) -L config/m68k/m68k.c (working copy) config/m68k/.svn/text-base/m68k.c.svn-base config/m68k/m68k.c
--- config/m68k/m68k.c (revision 110699)
+++ config/m68k/m68k.c (working copy)
@@ -2387,11 +2387,11 @@ emit_move_sequence (rtx *operands, enum
}
if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
- && ((tem = find_replacement (&XEXP (operand0, 0)))
+ && ((tem = XEXP (operand0, 0))
!= XEXP (operand0, 0)))
operand0 = gen_rtx_MEM (GET_MODE (operand0), tem);
if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
- && ((tem = find_replacement (&XEXP (operand1, 0)))
+ && ((tem = XEXP (operand1, 0))
!= XEXP (operand1, 0)))
operand1 = gen_rtx_MEM (GET_MODE (operand1), tem);
Index: config/arm/arm.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/arm/arm.c (revision 110699) -L config/arm/arm.c (working copy) config/arm/.svn/text-base/arm.c.svn-base config/arm/arm.c
--- config/arm/arm.c (revision 110699)
+++ config/arm/arm.c (working copy)
@@ -6827,14 +6827,14 @@ arm_reload_in_hi (rtx *operands)
if (reg_equiv_mem[REGNO (ref)])
{
ref = reg_equiv_mem[REGNO (ref)];
- base = find_replacement (&XEXP (ref, 0));
+ base = XEXP (ref, 0);
}
else
/* The slot is out of range, or was dressed up in a SUBREG. */
base = reg_equiv_address[REGNO (ref)];
}
else
- base = find_replacement (&XEXP (ref, 0));
+ base = XEXP (ref, 0);
/* Handle the case where the address is too complex to be offset by 1. */
if (GET_CODE (base) == MINUS
@@ -6944,14 +6944,14 @@ arm_reload_out_hi (rtx *operands)
if (reg_equiv_mem[REGNO (ref)])
{
ref = reg_equiv_mem[REGNO (ref)];
- base = find_replacement (&XEXP (ref, 0));
+ base = XEXP (ref, 0);
}
else
/* The slot is out of range, or was dressed up in a SUBREG. */
base = reg_equiv_address[REGNO (ref)];
}
else
- base = find_replacement (&XEXP (ref, 0));
+ base = XEXP (ref, 0);
scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
Index: config/pa/pa.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L config/pa/pa.c (revision 110699) -L config/pa/pa.c (working copy) config/pa/.svn/text-base/pa.c.svn-base config/pa/pa.c
--- config/pa/pa.c (revision 110699)
+++ config/pa/pa.c (working copy)
@@ -1389,12 +1389,12 @@ emit_move_sequence (rtx *operands, enum
}
if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM
- && ((tem = find_replacement (&XEXP (operand0, 0)))
+ && ((tem = XEXP (operand0, 0))
!= XEXP (operand0, 0)))
operand0 = replace_equiv_address (operand0, tem);
if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM
- && ((tem = find_replacement (&XEXP (operand1, 0)))
+ && ((tem = XEXP (operand1, 0))
!= XEXP (operand1, 0)))
operand1 = replace_equiv_address (operand1, tem);
Index: reload1.c
===================================================================
/usr/bin/diff -p -d -F^( -u -L reload1.c (revision 110699) -L reload1.c (working copy) .svn/text-base/reload1.c.svn-base reload1.c
--- reload1.c (revision 110699)
+++ reload1.c (working copy)
@@ -420,6 +420,9 @@ static int set_reload_reg (int, int);
static void choose_reload_regs_init (struct insn_chain *, rtx *);
static void choose_reload_regs (struct insn_chain *);
static void merge_assigned_reloads (rtx);
+static void reconsider_reload_regs (rtx insn);
+static void reconsider_reload_override (rtx, struct reload *, rtx, int);
+static bool reload_by_redirect (rtx, struct reload *, rtx, int, bool);
static void emit_input_reload_insns (struct insn_chain *, struct reload *,
rtx, int);
static void emit_output_reload_insns (struct insn_chain *, struct reload *,
@@ -3965,16 +3968,24 @@ reload_as_needed (int live_known)
if (SMALL_REGISTER_CLASSES)
merge_assigned_reloads (insn);
- /* Generate the insns to reload operands into or out of
- their reload regs. */
- emit_reload_insns (chain);
+ reconsider_reload_regs (insn);
/* Substitute the chosen reload regs from reload_reg_rtx
- into the insn's body (or perhaps into the bodies of other
- load and store insn that we just made for reloading
- and that we moved the structure into). */
+ into the insn's body, or perhaps into information about
+ the reloads that we are about to emit.
+ It's for the sake of the latter that we do this before
+ emitting the actual reload insns; this allows us to
+ check reload insns for validity in gen_reload. */
subst_reloads (insn);
+ /* ??? We should try to call reload_by_redirect from here.
+ Since the substitutions have already been done, multiple
+ reloaded occurences should pose no problem. */
+
+ /* Generate the insns to reload operands into or out of
+ their reload regs. */
+ emit_reload_insns (chain);
+
/* Adjust the exception region notes for loads and stores. */
if (flag_non_call_exceptions && !CALL_P (insn))
fixup_eh_region_note (insn, prev, next);
@@ -5715,6 +5726,7 @@ choose_reload_regs (struct insn_chain *c
there. */
gcc_assert (GET_CODE (equiv) == SUBREG);
regno = subreg_regno (equiv);
+ /* ??? We should take SUBREG_BYTE into account! */
equiv = gen_rtx_REG (rld[r].mode, regno);
/* If we choose EQUIV as the reload register, but the
loop below decides to cancel the inheritance, we'll
@@ -6276,54 +6288,38 @@ reload_adjust_reg_for_icode (rtx *reload
new_class, new_mode);
}
-/* Generate insns to perform reload RL, which is for the insn in CHAIN and
- has the number J. OLD contains the value to be used as input. */
-
+/* Try some more reload inheritance for INSN after merging assigned reloads. */
static void
-emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
- rtx old, int j)
+reconsider_reload_regs (rtx insn)
{
- rtx insn = chain->insn;
- rtx reloadreg = rl->reg_rtx;
- rtx oldequiv_reg = 0;
- rtx oldequiv = 0;
- int special = 0;
- enum machine_mode mode;
- rtx *where;
-
- /* Determine the mode to reload in.
- This is very tricky because we have three to choose from.
- There is the mode the insn operand wants (rl->inmode).
- There is the mode of the reload register RELOADREG.
- There is the intrinsic mode of the operand, which we could find
- by stripping some SUBREGs.
- It turns out that RELOADREG's mode is irrelevant:
- we can change that arbitrarily.
-
- Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
- then the reload reg may not support QImode moves, so use SImode.
- If foo is in memory due to spilling a pseudo reg, this is safe,
- because the QImode value is in the least significant part of a
- slot big enough for a SImode. If foo is some other sort of
- memory reference, then it is impossible to reload this case,
- so previous passes had better make sure this never happens.
-
- Then consider a one-word union which has SImode and one of its
- members is a float, being fetched as (SUBREG:SF union:SI).
- We must fetch that as SFmode because we could be loading into
- a float-only register. In this case OLD's mode is correct.
+ int j;
- Consider an immediate integer: it has VOIDmode. Here we need
- to get a mode from something else.
+ if (!optimize)
+ return;
+ for (j = 0; j < n_reloads; j++)
+ {
+ struct reload *rl = &rld[j];
+ rtx old = rl->in_reg && MEM_P (rl->in_reg) ? rl->in_reg : rl->in_reg;
- In some cases, there is a fourth mode, the operand's
- containing mode. If the insn specifies a containing mode for
- this operand, it overrides all others.
+ if (!old
+ || reload_inherited[j]
+ || ! rtx_equal_p (rl->reg_rtx, old)
+ || ! rl->reg_rtx != 0)
+ continue;
+ if (reload_by_redirect (insn, rl, old, j, false))
+ continue;
+ reconsider_reload_override (insn, rl, old, j);
+ }
+}
- I am not sure whether the algorithm here is always right,
- but it does the right things in those cases. */
+/* RL is a reload of INSN which reloads the input OLD, and has number J.
+ Try to find an equivalence to set reload_override_in. */
+static void
+reconsider_reload_override (rtx insn, struct reload *rl, rtx old, int j)
+{
+ enum machine_mode mode = GET_MODE (old);
+ rtx oldequiv = 0;
- mode = GET_MODE (old);
if (mode == VOIDmode)
mode = rl->inmode;
@@ -6333,8 +6329,7 @@ emit_input_reload_insns (struct insn_cha
register. */
if (rl->secondary_in_reload >= 0
- && rl->secondary_in_icode == CODE_FOR_nothing
- && optimize)
+ && rl->secondary_in_icode == CODE_FOR_nothing)
oldequiv
= find_equiv_reg (old, insn,
rld[rl->secondary_in_reload].class,
@@ -6348,7 +6343,7 @@ emit_input_reload_insns (struct insn_cha
or has yet to be emitted, in which case it doesn't matter
because we will use this equiv reg right away. */
- if (oldequiv == 0 && optimize
+ if (oldequiv == 0
&& (MEM_P (old)
|| (REG_P (old)
&& REGNO (old) >= FIRST_PSEUDO_REGISTER
@@ -6385,24 +6380,159 @@ emit_input_reload_insns (struct insn_cha
))
oldequiv = 0;
}
+ if (oldequiv)
+ {
+ if (GET_CODE (oldequiv) == SUBREG)
+ oldequiv
+ = simplify_subreg (mode, SUBREG_REG (oldequiv),
+ GET_MODE (SUBREG_REG (oldequiv)),
+ SUBREG_BYTE (oldequiv));
+ gcc_assert (REG_P (oldequiv));
+ rl->in = reload_override_in[j] = oldequiv;
+ }
+}
+
+/* RL is a reload of INSN which reloads the input OLD, and has number J.
+ Try to get the right value into the reload reg by changing a preceding
+ insn. If SUBSTED is true, reload registers have already been substituted
+ into INSN. Return true for success. */
+static bool
+reload_by_redirect (rtx insn, struct reload *rl, rtx old, int j, bool substed)
+{
+ rtx reloadreg = rl->reg_rtx;
+
+ /* If we are reloading a pseudo-register that was set by the previous
+ insn, see if we can get rid of that pseudo-register entirely
+ by redirecting the previous insn into our reload register. */
+
+ old = reload_override_in[j] ? rl->in_reg : old;
+ if (REG_P (old)
+ && REGNO (old) >= FIRST_PSEUDO_REGISTER
+ && dead_or_set_p (insn, old)
+ /* This is unsafe if some other reload
+ uses the same reg first. */
+ && ! conflicts_with_override (reloadreg)
+ && free_for_value_p (REGNO (reloadreg), rl->mode, rl->opnum,
+ rl->when_needed, old, rl->out, j, 0))
+ {
+ rtx temp = PREV_INSN (insn);
+ while (temp && NOTE_P (temp))
+ temp = PREV_INSN (temp);
+ if (temp
+ && NONJUMP_INSN_P (temp)
+ && GET_CODE (PATTERN (temp)) == SET
+ && SET_DEST (PATTERN (temp)) == old
+ /* Make sure we can access insn_operand_constraint. */
+ && asm_noperands (PATTERN (temp)) < 0
+ /* This is unsafe if operand occurs more than once in current
+ insn. Perhaps some occurrences aren't reloaded.
+ If we are running after subst_reloads, all reloaded
+ occurences will have been replaced. */
+ && count_occurrences (PATTERN (insn), old, 0) == substed ? 0 : 1)
+ {
+ rtx old = SET_DEST (PATTERN (temp));
+ /* Store into the reload register instead of the pseudo. */
+ SET_DEST (PATTERN (temp)) = reloadreg;
+
+ /* Verify that resulting insn is valid. */
+ extract_insn (temp);
+ if (constrain_operands (1))
+ {
+ /* If the previous insn is an output reload, the source is
+ a reload register, and its spill_reg_store entry will
+ contain the previous destination. This is now
+ invalid. */
+ if (REG_P (SET_SRC (PATTERN (temp)))
+ && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
+ {
+ spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+ spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+ }
+
+ /* If these are the only uses of the pseudo reg,
+ pretend for GDB it lives in the reload reg we used. */
+ if (REG_N_DEATHS (REGNO (old)) == 1
+ && REG_N_SETS (REGNO (old)) == 1)
+ {
+ reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
+ alter_reg (REGNO (old), -1);
+ }
+ reload_inherited[j] = 1;
+ reload_inheritance_insn[j] = temp;
+ return true;
+ }
+ else
+ {
+ SET_DEST (PATTERN (temp)) = old;
+ }
+ }
+ }
+ return false;
+}
+
+/* Generate insns to perform reload RL, which is for the insn in CHAIN and
+ has the number J. OLD contains the value to be used as input. */
+
+static void
+emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
+ rtx old, int j)
+{
+ rtx insn = chain->insn;
+ rtx reloadreg = rl->reg_rtx;
+ rtx oldequiv_reg = 0;
+ rtx oldequiv = 0;
+ int special = 0;
+ enum machine_mode mode;
+ rtx *where;
+
+ /* Determine the mode to reload in.
+ This is very tricky because we have three to choose from.
+ There is the mode the insn operand wants (rl->inmode).
+ There is the mode of the reload register RELOADREG.
+ There is the intrinsic mode of the operand, which we could find
+ by stripping some SUBREGs.
+ It turns out that RELOADREG's mode is irrelevant:
+ we can change that arbitrarily.
+
+ Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
+ then the reload reg may not support QImode moves, so use SImode.
+ If foo is in memory due to spilling a pseudo reg, this is safe,
+ because the QImode value is in the least significant part of a
+ slot big enough for a SImode. If foo is some other sort of
+ memory reference, then it is impossible to reload this case,
+ so previous passes had better make sure this never happens.
+
+ Then consider a one-word union which has SImode and one of its
+ members is a float, being fetched as (SUBREG:SF union:SI).
+ We must fetch that as SFmode because we could be loading into
+ a float-only register. In this case OLD's mode is correct.
+
+ Consider an immediate integer: it has VOIDmode. Here we need
+ to get a mode from something else.
+
+ In some cases, there is a fourth mode, the operand's
+ containing mode. If the insn specifies a containing mode for
+ this operand, it overrides all others.
+
+ I am not sure whether the algorithm here is always right,
+ but it does the right things in those cases. */
+
+ mode = GET_MODE (old);
+ if (mode == VOIDmode)
+ mode = rl->inmode;
/* delete_output_reload is only invoked properly if old contains
the original pseudo register. Since this is replaced with a
hard reg when RELOAD_OVERRIDE_IN is set, see if we can
find the pseudo in RELOAD_IN_REG. */
- if (oldequiv == 0
- && reload_override_in[j]
+ if (reload_override_in[j]
&& REG_P (rl->in_reg))
{
oldequiv = old;
old = rl->in_reg;
}
- if (oldequiv == 0)
+ else
oldequiv = old;
- else if (REG_P (oldequiv))
- oldequiv_reg = oldequiv;
- else if (GET_CODE (oldequiv) == SUBREG)
- oldequiv_reg = SUBREG_REG (oldequiv);
/* If we are reloading from a register that was recently stored in
with an output-reload, see if we can prove there was
@@ -6498,69 +6628,7 @@ emit_input_reload_insns (struct insn_cha
rl->inc);
}
- /* If we are reloading a pseudo-register that was set by the previous
- insn, see if we can get rid of that pseudo-register entirely
- by redirecting the previous insn into our reload register. */
-
- else if (optimize && REG_P (old)
- && REGNO (old) >= FIRST_PSEUDO_REGISTER
- && dead_or_set_p (insn, old)
- /* This is unsafe if some other reload
- uses the same reg first. */
- && ! conflicts_with_override (reloadreg)
- && free_for_value_p (REGNO (reloadreg), rl->mode, rl->opnum,
- rl->when_needed, old, rl->out, j, 0))
- {
- rtx temp = PREV_INSN (insn);
- while (temp && NOTE_P (temp))
- temp = PREV_INSN (temp);
- if (temp
- && NONJUMP_INSN_P (temp)
- && GET_CODE (PATTERN (temp)) == SET
- && SET_DEST (PATTERN (temp)) == old
- /* Make sure we can access insn_operand_constraint. */
- && asm_noperands (PATTERN (temp)) < 0
- /* This is unsafe if operand occurs more than once in current
- insn. Perhaps some occurrences aren't reloaded. */
- && count_occurrences (PATTERN (insn), old, 0) == 1)
- {
- rtx old = SET_DEST (PATTERN (temp));
- /* Store into the reload register instead of the pseudo. */
- SET_DEST (PATTERN (temp)) = reloadreg;
-
- /* Verify that resulting insn is valid. */
- extract_insn (temp);
- if (constrain_operands (1))
- {
- /* If the previous insn is an output reload, the source is
- a reload register, and its spill_reg_store entry will
- contain the previous destination. This is now
- invalid. */
- if (REG_P (SET_SRC (PATTERN (temp)))
- && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
- {
- spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
- spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
- }
-
- /* If these are the only uses of the pseudo reg,
- pretend for GDB it lives in the reload reg we used. */
- if (REG_N_DEATHS (REGNO (old)) == 1
- && REG_N_SETS (REGNO (old)) == 1)
- {
- reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
- alter_reg (REGNO (old), -1);
- }
- special = 1;
- }
- else
- {
- SET_DEST (PATTERN (temp)) = old;
- }
- }
- }
-
- /* We can't do that, so output an insn to load RELOADREG. */
+ /* Otherwise, output an insn to load RELOADREG. */
/* If we have a secondary reload, pick up the secondary register
and icode, if any. If OLDEQUIV and OLD are different or
@@ -7646,12 +7714,7 @@ gen_reload (rtx out, rtx in, int opnum,
This entire process is made complex because reload will never
process the insns we generate here and so we must ensure that
- they will fit their constraints and also by the fact that parts of
- IN might be being reloaded separately and replaced with spill registers.
- Because of this, we are, in some sense, just guessing the right approach
- here. The one listed above seems to work.
-
- ??? At some point, this whole thing needs to be rethought. */
+ they will fit their constraints. */
if (GET_CODE (in) == PLUS
&& (REG_P (XEXP (in, 0))
@@ -7678,8 +7741,8 @@ gen_reload (rtx out, rtx in, int opnum,
rtx op0, op1, tem, insn;
int code;
- op0 = find_replacement (&XEXP (in, 0));
- op1 = find_replacement (&XEXP (in, 1));
+ op0 = XEXP (in, 0);
+ op1 = XEXP (in, 1);
/* Since constraint checking is strict, commutativity won't be
checked, so we need to do that here to avoid spurious failure