Commit 367b1cf5 by Bernd Schmidt Committed by Bernd Schmidt

Break up emit_reload_insns.

From-SVN: r31052
parent ca098a1d
1999-12-21 Bernd Schmidt <bernds@cygnus.co.uk>
* reload1.c (emit_reload_insns): Break out code and variables into...
(input_reload_insns, other_input_address_reload_insns,
other_input_reload_insns, input_address_reload_insns,
inpaddr_address_reload_insns, output_reload_insns,
output_address_reload_insns, outaddr_address_reload_insns,
operand_reload_insns, other_operand_reload_insns,
other_output_reload_insns): ... new static variables, and...
(emit_input_reload_insns, emit_output_reload_insns, do_input_reload,
do_output_reload): ... new functions.
Tue Dec 21 07:06:36 1999 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* pa.h (FUNCTION_ARG_BOUNDARY): Never return 0.
......
......@@ -414,6 +414,14 @@ static int set_reload_reg PROTO((int, int));
static void choose_reload_regs_init PROTO((struct insn_chain *, rtx *));
static void choose_reload_regs PROTO((struct insn_chain *));
static void merge_assigned_reloads PROTO((rtx));
static void emit_input_reload_insns PROTO((struct insn_chain *,
struct reload *, rtx, int));
static void emit_output_reload_insns PROTO((struct insn_chain *,
struct reload *, int));
static void do_input_reload PROTO((struct insn_chain *,
struct reload *, int));
static void do_output_reload PROTO((struct insn_chain *,
struct reload *, int));
static void emit_reload_insns PROTO((struct insn_chain *));
static void delete_output_reload PROTO((rtx, int, int));
static void delete_address_reloads PROTO((rtx, rtx));
......@@ -5834,76 +5842,43 @@ merge_assigned_reloads (insn)
}
/* Output insns to reload values in and out of the chosen reload regs. */
/* These arrays are filled by emit_reload_insns and its subroutines. */
static rtx input_reload_insns[MAX_RECOG_OPERANDS];
static rtx other_input_address_reload_insns = 0;
static rtx other_input_reload_insns = 0;
static rtx input_address_reload_insns[MAX_RECOG_OPERANDS];
static rtx inpaddr_address_reload_insns[MAX_RECOG_OPERANDS];
static rtx output_reload_insns[MAX_RECOG_OPERANDS];
static rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
static rtx outaddr_address_reload_insns[MAX_RECOG_OPERANDS];
static rtx operand_reload_insns = 0;
static rtx other_operand_reload_insns = 0;
static rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
/* Values to be put in spill_reg_store are put here first. */
static rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
static HARD_REG_SET reg_reloaded_died;
/* 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_reload_insns (chain)
emit_input_reload_insns (chain, rl, old, j)
struct insn_chain *chain;
struct reload *rl;
rtx old;
int j;
{
rtx insn = chain->insn;
register int j;
rtx input_reload_insns[MAX_RECOG_OPERANDS];
rtx other_input_address_reload_insns = 0;
rtx other_input_reload_insns = 0;
rtx input_address_reload_insns[MAX_RECOG_OPERANDS];
rtx inpaddr_address_reload_insns[MAX_RECOG_OPERANDS];
rtx output_reload_insns[MAX_RECOG_OPERANDS];
rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
rtx outaddr_address_reload_insns[MAX_RECOG_OPERANDS];
rtx operand_reload_insns = 0;
rtx other_operand_reload_insns = 0;
rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
rtx following_insn = NEXT_INSN (insn);
rtx before_insn = PREV_INSN (insn);
int special;
/* Values to be put in spill_reg_store are put here first. */
rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
HARD_REG_SET reg_reloaded_died;
CLEAR_HARD_REG_SET (reg_reloaded_died);
for (j = 0; j < reload_n_operands; j++)
input_reload_insns[j] = input_address_reload_insns[j]
= inpaddr_address_reload_insns[j]
= output_reload_insns[j] = output_address_reload_insns[j]
= outaddr_address_reload_insns[j]
= other_output_reload_insns[j] = 0;
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
since reloads of base and index registers precede reloads of operands
and the operands may need the base and index registers reloaded. */
for (j = 0; j < n_reloads; j++)
{
register rtx old;
register rtx reloadreg = rl->reg_rtx;
rtx oldequiv_reg = 0;
rtx this_reload_insn = 0;
int expect_occurrences = 1;
if (rld[j].reg_rtx
&& REGNO (rld[j].reg_rtx) < FIRST_PSEUDO_REGISTER)
new_spill_reg_store[REGNO (rld[j].reg_rtx)] = 0;
old = (rld[j].in && GET_CODE (rld[j].in) == MEM
? rld[j].in_reg : rld[j].in);
if (old != 0
/* AUTO_INC reloads need to be handled even if inherited. We got an
AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
&& (! reload_inherited[j] || (rld[j].out && ! rld[j].out_reg))
&& ! rtx_equal_p (rld[j].reg_rtx, old)
&& rld[j].reg_rtx != 0)
{
register rtx reloadreg = rld[j].reg_rtx;
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 (rld[J].inmode).
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.
......@@ -5935,7 +5910,7 @@ emit_reload_insns (chain)
mode = GET_MODE (old);
if (mode == VOIDmode)
mode = rld[j].inmode;
mode = rl->inmode;
#ifdef SECONDARY_INPUT_RELOAD_CLASS
/* If we need a secondary register for this operation, see if
......@@ -5943,12 +5918,12 @@ emit_reload_insns (chain)
do this if the secondary register will be used as a scratch
register. */
if (rld[j].secondary_in_reload >= 0
&& rld[j].secondary_in_icode == CODE_FOR_nothing
if (rl->secondary_in_reload >= 0
&& rl->secondary_in_icode == CODE_FOR_nothing
&& optimize)
oldequiv
= find_equiv_reg (old, insn,
rld[rld[j].secondary_in_reload].class,
rld[rl->secondary_in_reload].class,
-1, NULL_PTR, 0, mode);
#endif
......@@ -5974,9 +5949,9 @@ emit_reload_insns (chain)
/* Don't use OLDEQUIV if any other reload changes it at an
earlier stage of this insn or at this stage. */
if (! reload_reg_free_for_value_p (regno, rld[j].opnum,
rld[j].when_needed,
rld[j].in, const0_rtx, j,
if (! reload_reg_free_for_value_p (regno, rl->opnum,
rl->when_needed,
rl->in, const0_rtx, j,
0))
oldequiv = 0;
......@@ -5986,18 +5961,18 @@ emit_reload_insns (chain)
or memory. */
if (oldequiv != 0
&& ((REGNO_REG_CLASS (regno) != rld[j].class
&& ((REGNO_REG_CLASS (regno) != rl->class
&& (REGISTER_MOVE_COST (REGNO_REG_CLASS (regno),
rld[j].class)
>= MEMORY_MOVE_COST (mode, rld[j].class, 1)))
rl->class)
>= MEMORY_MOVE_COST (mode, rl->class, 1)))
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (rld[j].class,
|| (SECONDARY_INPUT_RELOAD_CLASS (rl->class,
mode, oldequiv)
!= NO_REGS)
#endif
#ifdef SECONDARY_MEMORY_NEEDED
|| SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (regno),
rld[j].class,
rl->class,
mode)
#endif
))
......@@ -6010,10 +5985,10 @@ emit_reload_insns (chain)
find the pseudo in RELOAD_IN_REG. */
if (oldequiv == 0
&& reload_override_in[j]
&& GET_CODE (rld[j].in_reg) == REG)
&& GET_CODE (rl->in_reg) == REG)
{
oldequiv = old;
old = rld[j].in_reg;
old = rl->in_reg;
}
if (oldequiv == 0)
oldequiv = old;
......@@ -6032,7 +6007,7 @@ emit_reload_insns (chain)
&& GET_CODE (old) == REG
&& (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)])
|| rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
rld[j].out_reg)))
rl->out_reg)))
delete_output_reload (insn, j, REGNO (oldequiv));
/* Encapsulate both RELOADREG and OLDEQUIV into that mode,
......@@ -6050,25 +6025,25 @@ emit_reload_insns (chain)
oldequiv = gen_rtx_SUBREG (mode, oldequiv, 0);
/* Switch to the right place to emit the reload insns. */
switch (rld[j].when_needed)
switch (rl->when_needed)
{
case RELOAD_OTHER:
where = &other_input_reload_insns;
break;
case RELOAD_FOR_INPUT:
where = &input_reload_insns[rld[j].opnum];
where = &input_reload_insns[rl->opnum];
break;
case RELOAD_FOR_INPUT_ADDRESS:
where = &input_address_reload_insns[rld[j].opnum];
where = &input_address_reload_insns[rl->opnum];
break;
case RELOAD_FOR_INPADDR_ADDRESS:
where = &inpaddr_address_reload_insns[rld[j].opnum];
where = &inpaddr_address_reload_insns[rl->opnum];
break;
case RELOAD_FOR_OUTPUT_ADDRESS:
where = &output_address_reload_insns[rld[j].opnum];
where = &output_address_reload_insns[rl->opnum];
break;
case RELOAD_FOR_OUTADDR_ADDRESS:
where = &outaddr_address_reload_insns[rld[j].opnum];
where = &outaddr_address_reload_insns[rl->opnum];
break;
case RELOAD_FOR_OPERAND_ADDRESS:
where = &operand_reload_insns;
......@@ -6084,21 +6059,20 @@ emit_reload_insns (chain)
}
push_to_sequence (*where);
special = 0;
/* Auto-increment addresses must be reloaded in a special way. */
if (rld[j].out && ! rld[j].out_reg)
if (rl->out && ! rl->out_reg)
{
/* We are not going to bother supporting the case where a
incremented register can't be copied directly from
OLDEQUIV since this seems highly unlikely. */
if (rld[j].secondary_in_reload >= 0)
if (rl->secondary_in_reload >= 0)
abort ();
if (reload_inherited[j])
oldequiv = reloadreg;
old = XEXP (rld[j].in_reg, 0);
old = XEXP (rl->in_reg, 0);
if (optimize && GET_CODE (oldequiv) == REG
&& REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
......@@ -6114,8 +6088,8 @@ emit_reload_insns (chain)
special = 1;
/* Output a special code sequence for this case. */
new_spill_reg_store[REGNO (reloadreg)]
= inc_for_reload (reloadreg, oldequiv, rld[j].out,
rld[j].inc);
= inc_for_reload (reloadreg, oldequiv, rl->out,
rl->inc);
}
/* If we are reloading a pseudo-register that was set by the previous
......@@ -6128,9 +6102,9 @@ emit_reload_insns (chain)
/* This is unsafe if some other reload
uses the same reg first. */
&& reload_reg_free_for_value_p (REGNO (reloadreg),
rld[j].opnum,
rld[j].when_needed,
old, rld[j].out,
rl->opnum,
rl->when_needed,
old, rl->out,
j, 0))
{
rtx temp = PREV_INSN (insn);
......@@ -6170,21 +6144,16 @@ emit_reload_insns (chain)
if (REG_N_DEATHS (REGNO (old)) == 1
&& REG_N_SETS (REGNO (old)) == 1)
{
reg_renumber[REGNO (old)] = REGNO (rld[j].reg_rtx);
reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
alter_reg (REGNO (old), -1);
}
special = 1;
return;
}
}
/* We can't do that, so output an insn to load RELOADREG. */
if (! special)
{
#ifdef SECONDARY_INPUT_RELOAD_CLASS
rtx second_reload_reg = 0;
enum insn_code icode;
/* If we have a secondary reload, pick up the secondary register
and icode, if any. If OLDEQUIV and OLD are different or
if this is an in-out reload, recompute whether or not we
......@@ -6196,12 +6165,14 @@ emit_reload_insns (chain)
because we don't make such reloads when both the input and
output need secondary reload registers. */
if (rld[j].secondary_in_reload >= 0)
if (rl->secondary_in_reload >= 0)
{
int secondary_reload = rld[j].secondary_in_reload;
rtx second_reload_reg = 0;
int secondary_reload = rl->secondary_in_reload;
rtx real_oldequiv = oldequiv;
rtx real_old = old;
rtx tmp;
enum insn_code icode;
/* If OLDEQUIV is a pseudo with a MEM, get the real MEM
and similarly for OLD.
......@@ -6227,7 +6198,7 @@ emit_reload_insns (chain)
if (! reg_equiv_mem[REGNO (tmp)]
|| num_not_at_initial_offset
|| GET_CODE (oldequiv) == SUBREG)
real_oldequiv = rld[j].in;
real_oldequiv = rl->in;
else
real_oldequiv = reg_equiv_mem[REGNO (tmp)];
}
......@@ -6243,19 +6214,19 @@ emit_reload_insns (chain)
if (! reg_equiv_mem[REGNO (tmp)]
|| num_not_at_initial_offset
|| GET_CODE (old) == SUBREG)
real_old = rld[j].in;
real_old = rl->in;
else
real_old = reg_equiv_mem[REGNO (tmp)];
}
second_reload_reg = rld[secondary_reload].reg_rtx;
icode = rld[j].secondary_in_icode;
icode = rl->secondary_in_icode;
if ((old != oldequiv && ! rtx_equal_p (old, oldequiv))
|| (rld[j].in != 0 && rld[j].out != 0))
|| (rl->in != 0 && rl->out != 0))
{
enum reg_class new_class
= SECONDARY_INPUT_RELOAD_CLASS (rld[j].class,
= SECONDARY_INPUT_RELOAD_CLASS (rl->class,
mode, real_oldequiv);
if (new_class == NO_REGS)
......@@ -6312,7 +6283,7 @@ emit_reload_insns (chain)
{
emit_insn (GEN_FCN (icode) (reloadreg, real_oldequiv,
second_reload_reg));
special = 1;
return;
}
else
{
......@@ -6332,8 +6303,8 @@ emit_reload_insns (chain)
}
else
gen_reload (second_reload_reg, real_oldequiv,
rld[j].opnum,
rld[j].when_needed);
rl->opnum,
rl->when_needed);
oldequiv = second_reload_reg;
}
......@@ -6341,7 +6312,7 @@ emit_reload_insns (chain)
}
#endif
if (! special && ! rtx_equal_p (reloadreg, oldequiv))
if (! rtx_equal_p (reloadreg, oldequiv))
{
rtx real_oldequiv = oldequiv;
......@@ -6357,14 +6328,11 @@ emit_reload_insns (chain)
[REGNO (SUBREG_REG (oldequiv))] != 0)
|| (reg_equiv_constant
[REGNO (SUBREG_REG (oldequiv))] != 0))))
real_oldequiv = rld[j].in;
gen_reload (reloadreg, real_oldequiv, rld[j].opnum,
rld[j].when_needed);
real_oldequiv = rl->in;
gen_reload (reloadreg, real_oldequiv, rl->opnum,
rl->when_needed);
}
}
this_reload_insn = get_last_insn ();
/* End this sequence. */
*where = get_insns ();
end_sequence ();
......@@ -6373,142 +6341,31 @@ emit_reload_insns (chain)
can see the actual register usage. */
if (oldequiv_reg)
reload_override_in[j] = oldequiv;
}
/* When inheriting a wider reload, we have a MEM in rld[j].in,
e.g. inheriting a SImode output reload for
(mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */
if (optimize && reload_inherited[j] && rld[j].in
&& GET_CODE (rld[j].in) == MEM
&& GET_CODE (rld[j].in_reg) == MEM
&& reload_spill_index[j] >= 0
&& TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
{
expect_occurrences
= count_occurrences (PATTERN (insn), rld[j].in) == 1 ? 0 : -1;
rld[j].in
= regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
}
/* If we are reloading a register that was recently stored in with an
output-reload, see if we can prove there was
actually no need to store the old value in it. */
if (optimize
&& (reload_inherited[j] || reload_override_in[j])
&& rld[j].reg_rtx
&& GET_CODE (rld[j].reg_rtx) == REG
&& spill_reg_store[REGNO (rld[j].reg_rtx)] != 0
#if 0
/* There doesn't seem to be any reason to restrict this to pseudos
and doing so loses in the case where we are copying from a
register of the wrong class. */
&& (REGNO (spill_reg_stored_to[REGNO (rld[j].reg_rtx)])
>= FIRST_PSEUDO_REGISTER)
#endif
/* The insn might have already some references to stackslots
replaced by MEMs, while reload_out_reg still names the
original pseudo. */
&& (dead_or_set_p (insn,
spill_reg_stored_to[REGNO (rld[j].reg_rtx)])
|| rtx_equal_p (spill_reg_stored_to[REGNO (rld[j].reg_rtx)],
rld[j].out_reg)))
delete_output_reload (insn, j, REGNO (rld[j].reg_rtx));
/* Input-reloading is done. Now do output-reloading,
storing the value from the reload-register after the main insn
if rld[j].out is nonzero.
??? At some point we need to support handling output reloads of
JUMP_INSNs or insns that set cc0. */
/* If this is an output reload that stores something that is
not loaded in this same reload, see if we can eliminate a previous
store. */
{
rtx pseudo = rld[j].out_reg;
if (pseudo
&& GET_CODE (pseudo) == REG
&& ! rtx_equal_p (rld[j].in_reg, pseudo)
&& REGNO (pseudo) >= FIRST_PSEUDO_REGISTER
&& reg_last_reload_reg[REGNO (pseudo)])
{
int pseudo_no = REGNO (pseudo);
int last_regno = REGNO (reg_last_reload_reg[pseudo_no]);
/* We don't need to test full validity of last_regno for
inherit here; we only want to know if the store actually
matches the pseudo. */
if (reg_reloaded_contents[last_regno] == pseudo_no
&& spill_reg_store[last_regno]
&& rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
delete_output_reload (insn, j, last_regno);
}
}
}
old = rld[j].out_reg;
if (old != 0
&& rld[j].reg_rtx != old
&& rld[j].reg_rtx != 0)
{
register rtx reloadreg = rld[j].reg_rtx;
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
register rtx second_reloadreg = 0;
#endif
rtx note, p;
enum machine_mode mode;
/* Generate insns to for the output reload RL, which is for the insn described
by CHAIN and has the number J. */
static void
emit_output_reload_insns (chain, rl, j)
struct insn_chain *chain;
struct reload *rl;
int j;
{
rtx reloadreg = rl->reg_rtx;
rtx insn = chain->insn;
int special = 0;
rtx old = rl->out;
enum machine_mode mode = GET_MODE (old);
rtx p;
/* An output operand that dies right away does need a reload,
but need not be copied from it. Show the new location in the
REG_UNUSED note. */
if ((GET_CODE (old) == REG || GET_CODE (old) == SCRATCH)
&& (note = find_reg_note (insn, REG_UNUSED, old)) != 0)
{
XEXP (note, 0) = rld[j].reg_rtx;
continue;
}
/* Likewise for a SUBREG of an operand that dies. */
else if (GET_CODE (old) == SUBREG
&& GET_CODE (SUBREG_REG (old)) == REG
&& 0 != (note = find_reg_note (insn, REG_UNUSED,
SUBREG_REG (old))))
{
XEXP (note, 0) = gen_lowpart_common (GET_MODE (old),
rld[j].reg_rtx);
continue;
}
else if (GET_CODE (old) == SCRATCH)
/* If we aren't optimizing, there won't be a REG_UNUSED note,
but we don't want to make an output reload. */
continue;
#if 0
/* Strip off of OLD any size-increasing SUBREGs such as
(SUBREG:SI foo:QI 0). */
while (GET_CODE (old) == SUBREG && SUBREG_WORD (old) == 0
&& (GET_MODE_SIZE (GET_MODE (old))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (old)))))
old = SUBREG_REG (old);
#endif
/* If is a JUMP_INSN, we can't support output reloads yet. */
if (GET_CODE (insn) == JUMP_INSN)
abort ();
if (rld[j].when_needed == RELOAD_OTHER)
if (rl->when_needed == RELOAD_OTHER)
start_sequence ();
else
push_to_sequence (output_reload_insns[rld[j].opnum]);
old = rld[j].out;
push_to_sequence (output_reload_insns[rl->opnum]);
/* Determine the mode to reload in.
See comments above (for input reloading). */
mode = GET_MODE (old);
if (mode == VOIDmode)
{
/* VOIDmode should never happen for an output. */
......@@ -6530,7 +6387,7 @@ emit_reload_insns (chain)
one, since it will be stored into OLD. We might need a secondary
register only for an input reload, so check again here. */
if (rld[j].secondary_out_reload >= 0)
if (rl->secondary_out_reload >= 0)
{
rtx real_old = old;
......@@ -6538,18 +6395,18 @@ emit_reload_insns (chain)
&& reg_equiv_mem[REGNO (old)] != 0)
real_old = reg_equiv_mem[REGNO (old)];
if((SECONDARY_OUTPUT_RELOAD_CLASS (rld[j].class,
if ((SECONDARY_OUTPUT_RELOAD_CLASS (rl->class,
mode, real_old)
!= NO_REGS))
{
second_reloadreg = reloadreg;
reloadreg = rld[rld[j].secondary_out_reload].reg_rtx;
rtx second_reloadreg = reloadreg;
reloadreg = rld[rl->secondary_out_reload].reg_rtx;
/* See if RELOADREG is to be used as a scratch register
or as an intermediate register. */
if (rld[j].secondary_out_icode != CODE_FOR_nothing)
if (rl->secondary_out_icode != CODE_FOR_nothing)
{
emit_insn ((GEN_FCN (rld[j].secondary_out_icode)
emit_insn ((GEN_FCN (rl->secondary_out_icode)
(real_old, second_reloadreg, reloadreg)));
special = 1;
}
......@@ -6558,7 +6415,7 @@ emit_reload_insns (chain)
/* See if we need both a scratch and intermediate reload
register. */
int secondary_reload = rld[j].secondary_out_reload;
int secondary_reload = rl->secondary_out_reload;
enum insn_code tertiary_icode
= rld[secondary_reload].secondary_out_icode;
......@@ -6587,7 +6444,7 @@ emit_reload_insns (chain)
real_old = SUBREG_REG (real_old), reloadreg = tem;
gen_reload (reloadreg, second_reloadreg,
rld[j].opnum, rld[j].when_needed);
rl->opnum, rl->when_needed);
emit_insn ((GEN_FCN (tertiary_icode)
(real_old, reloadreg, third_reloadreg)));
special = 1;
......@@ -6598,7 +6455,7 @@ emit_reload_insns (chain)
OUT later. */
gen_reload (reloadreg, second_reloadreg,
rld[j].opnum, rld[j].when_needed);
rl->opnum, rl->when_needed);
}
}
}
......@@ -6617,8 +6474,8 @@ emit_reload_insns (chain)
|| rtx_equal_p (old, SET_DEST (set))
|| !reg_mentioned_p (old, SET_SRC (set))
|| !regno_clobbered_p (REGNO (old), insn))
gen_reload (old, reloadreg, rld[j].opnum,
rld[j].when_needed);
gen_reload (old, reloadreg, rl->opnum,
rl->when_needed);
}
/* Look at all insns we emitted, just to be safe. */
......@@ -6633,12 +6490,12 @@ emit_reload_insns (chain)
reg_has_output_reload will make this do nothing. */
note_stores (pat, forget_old_reloads_1, NULL);
if (reg_mentioned_p (rld[j].reg_rtx, pat))
if (reg_mentioned_p (rl->reg_rtx, pat))
{
rtx set = single_set (insn);
if (reload_spill_index[j] < 0
&& set
&& SET_SRC (set) == rld[j].reg_rtx)
&& SET_SRC (set) == rl->reg_rtx)
{
int src = REGNO (SET_SRC (set));
......@@ -6647,9 +6504,9 @@ emit_reload_insns (chain)
if (find_regno_note (insn, REG_DEAD, src))
SET_HARD_REG_BIT (reg_reloaded_died, src);
}
if (REGNO (rld[j].reg_rtx) < FIRST_PSEUDO_REGISTER)
if (REGNO (rl->reg_rtx) < FIRST_PSEUDO_REGISTER)
{
int s = rld[j].secondary_out_reload;
int s = rl->secondary_out_reload;
set = single_set (p);
/* If this reload copies only to the secondary reload
register, the secondary reload does the actual
......@@ -6659,7 +6516,7 @@ emit_reload_insns (chain)
has and where the actual store to the pseudo is
made; leave new_spill_reg_store alone. */
else if (s >= 0
&& SET_SRC (set) == rld[j].reg_rtx
&& SET_SRC (set) == rl->reg_rtx
&& SET_DEST (set) == rld[s].reg_rtx)
{
/* Usually the next instruction will be the
......@@ -6668,8 +6525,8 @@ emit_reload_insns (chain)
that insn will allow an extra optimization. */
rtx s_reg = rld[s].reg_rtx;
rtx next = NEXT_INSN (p);
rld[s].out = rld[j].out;
rld[s].out_reg = rld[j].out_reg;
rld[s].out = rl->out;
rld[s].out_reg = rl->out_reg;
set = single_set (next);
if (set && SET_SRC (set) == s_reg
&& ! new_spill_reg_store[REGNO (s_reg)])
......@@ -6680,21 +6537,196 @@ emit_reload_insns (chain)
}
}
else
new_spill_reg_store[REGNO (rld[j].reg_rtx)] = p;
new_spill_reg_store[REGNO (rl->reg_rtx)] = p;
}
}
}
if (rld[j].when_needed == RELOAD_OTHER)
if (rl->when_needed == RELOAD_OTHER)
{
emit_insns (other_output_reload_insns[rld[j].opnum]);
other_output_reload_insns[rld[j].opnum] = get_insns ();
emit_insns (other_output_reload_insns[rl->opnum]);
other_output_reload_insns[rl->opnum] = get_insns ();
}
else
output_reload_insns[rld[j].opnum] = get_insns ();
output_reload_insns[rl->opnum] = get_insns ();
end_sequence ();
}
/* Do input reloading for reload RL, which is for the insn described by CHAIN
and has the number J. */
static void
do_input_reload (chain, rl, j)
struct insn_chain *chain;
struct reload *rl;
int j;
{
int expect_occurrences = 1;
rtx insn = chain->insn;
rtx old = (rl->in && GET_CODE (rl->in) == MEM
? rl->in_reg : rl->in);
if (old != 0
/* AUTO_INC reloads need to be handled even if inherited. We got an
AUTO_INC reload if reload_out is set but reload_out_reg isn't. */
&& (! reload_inherited[j] || (rl->out && ! rl->out_reg))
&& ! rtx_equal_p (rl->reg_rtx, old)
&& rl->reg_rtx != 0)
{
emit_input_reload_insns (chain, rld + j, old, j);
}
/* When inheriting a wider reload, we have a MEM in rl->in,
e.g. inheriting a SImode output reload for
(mem:HI (plus:SI (reg:SI 14 fp) (const_int 10))) */
if (optimize && reload_inherited[j] && rl->in
&& GET_CODE (rl->in) == MEM
&& GET_CODE (rl->in_reg) == MEM
&& reload_spill_index[j] >= 0
&& TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
{
expect_occurrences
= count_occurrences (PATTERN (insn), rl->in) == 1 ? 0 : -1;
rl->in
= regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
}
/* If we are reloading a register that was recently stored in with an
output-reload, see if we can prove there was
actually no need to store the old value in it. */
if (optimize
&& (reload_inherited[j] || reload_override_in[j])
&& rl->reg_rtx
&& GET_CODE (rl->reg_rtx) == REG
&& spill_reg_store[REGNO (rl->reg_rtx)] != 0
#if 0
/* There doesn't seem to be any reason to restrict this to pseudos
and doing so loses in the case where we are copying from a
register of the wrong class. */
&& (REGNO (spill_reg_stored_to[REGNO (rl->reg_rtx)])
>= FIRST_PSEUDO_REGISTER)
#endif
/* The insn might have already some references to stackslots
replaced by MEMs, while reload_out_reg still names the
original pseudo. */
&& (dead_or_set_p (insn,
spill_reg_stored_to[REGNO (rl->reg_rtx)])
|| rtx_equal_p (spill_reg_stored_to[REGNO (rl->reg_rtx)],
rl->out_reg)))
delete_output_reload (insn, j, REGNO (rl->reg_rtx));
}
/* Do output reloading for reload RL, which is for the insn described by
CHAIN and has the number J.
??? At some point we need to support handling output reloads of
JUMP_INSNs or insns that set cc0. */
static void
do_output_reload (chain, rl, j)
struct insn_chain *chain;
struct reload *rl;
int j;
{
rtx note, old;
rtx insn = chain->insn;
/* If this is an output reload that stores something that is
not loaded in this same reload, see if we can eliminate a previous
store. */
rtx pseudo = rl->out_reg;
if (pseudo
&& GET_CODE (pseudo) == REG
&& ! rtx_equal_p (rl->in_reg, pseudo)
&& REGNO (pseudo) >= FIRST_PSEUDO_REGISTER
&& reg_last_reload_reg[REGNO (pseudo)])
{
int pseudo_no = REGNO (pseudo);
int last_regno = REGNO (reg_last_reload_reg[pseudo_no]);
/* We don't need to test full validity of last_regno for
inherit here; we only want to know if the store actually
matches the pseudo. */
if (reg_reloaded_contents[last_regno] == pseudo_no
&& spill_reg_store[last_regno]
&& rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
delete_output_reload (insn, j, last_regno);
}
old = rl->out_reg;
if (old == 0
|| rl->reg_rtx == old
|| rl->reg_rtx == 0)
return;
/* An output operand that dies right away does need a reload,
but need not be copied from it. Show the new location in the
REG_UNUSED note. */
if ((GET_CODE (old) == REG || GET_CODE (old) == SCRATCH)
&& (note = find_reg_note (insn, REG_UNUSED, old)) != 0)
{
XEXP (note, 0) = rl->reg_rtx;
return;
}
/* Likewise for a SUBREG of an operand that dies. */
else if (GET_CODE (old) == SUBREG
&& GET_CODE (SUBREG_REG (old)) == REG
&& 0 != (note = find_reg_note (insn, REG_UNUSED,
SUBREG_REG (old))))
{
XEXP (note, 0) = gen_lowpart_common (GET_MODE (old),
rl->reg_rtx);
return;
}
else if (GET_CODE (old) == SCRATCH)
/* If we aren't optimizing, there won't be a REG_UNUSED note,
but we don't want to make an output reload. */
return;
/* If is a JUMP_INSN, we can't support output reloads yet. */
if (GET_CODE (insn) == JUMP_INSN)
abort ();
emit_output_reload_insns (chain, rld + j, j);
}
/* Output insns to reload values in and out of the chosen reload regs. */
static void
emit_reload_insns (chain)
struct insn_chain *chain;
{
rtx insn = chain->insn;
register int j;
rtx following_insn = NEXT_INSN (insn);
rtx before_insn = PREV_INSN (insn);
CLEAR_HARD_REG_SET (reg_reloaded_died);
for (j = 0; j < reload_n_operands; j++)
input_reload_insns[j] = input_address_reload_insns[j]
= inpaddr_address_reload_insns[j]
= output_reload_insns[j] = output_address_reload_insns[j]
= outaddr_address_reload_insns[j]
= other_output_reload_insns[j] = 0;
other_input_address_reload_insns = 0;
other_input_reload_insns = 0;
operand_reload_insns = 0;
other_operand_reload_insns = 0;
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
since reloads of base and index registers precede reloads of operands
and the operands may need the base and index registers reloaded. */
for (j = 0; j < n_reloads; j++)
{
if (rld[j].reg_rtx
&& REGNO (rld[j].reg_rtx) < FIRST_PSEUDO_REGISTER)
new_spill_reg_store[REGNO (rld[j].reg_rtx)] = 0;
do_input_reload (chain, rld + j, j);
do_output_reload (chain, rld + j, j);
}
/* Now write all the insns we made for reloads in the order expected by
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment