Makefile.in (local-alloc.o): Depend on $(GGC_H) and reload.h.
* Makefile.in (local-alloc.o): Depend on $(GGC_H) and reload.h. * local-alloc.c: Include "ggc.h" and "reload.h". (struct equivalence): New member is_arg_equivalence. (local_alloc): Always call update_equiv_regs. (update_equiv_regs): Allocate reg_equiv_init; set reg_equiv_init_size. Detect equivalences made by stores to memory in a second pass. Return early if not optimizing. Initialize reg_equiv_init for all equivalences; treat equivalences for REG_EQUIV notes existing before this pass specially. (no_equiv): Don't clear reg_equiv_init or remove notes if the is_arg_equivalence field is set. * reload.h (reg_equiv_init, reg_equiv_init_size): Declare. * reload1.c (reg_equiv_init): No longer static. (reg_equiv_init_size): New variable. (reload): Don't allocate reg_equiv_init; don't free it when done but clear it. Restructure equivalence set up code not to set reg_equiv_init, but to clear it when we can't use an equivalence. Undo change disabling equivalences for MEM_READONLY_P memrefs. Dump equivalencing insns to dump_file. From-SVN: r100975
This commit is contained in:
parent
ae973d6ae8
commit
d7f88d8648
@ -1,3 +1,26 @@
|
||||
2005-06-15 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* Makefile.in (local-alloc.o): Depend on $(GGC_H) and reload.h.
|
||||
* local-alloc.c: Include "ggc.h" and "reload.h".
|
||||
(struct equivalence): New member is_arg_equivalence.
|
||||
(local_alloc): Always call update_equiv_regs.
|
||||
(update_equiv_regs): Allocate reg_equiv_init; set reg_equiv_init_size.
|
||||
Detect equivalences made by stores to memory in a second pass.
|
||||
Return early if not optimizing.
|
||||
Initialize reg_equiv_init for all equivalences; treat equivalences for
|
||||
REG_EQUIV notes existing before this pass specially.
|
||||
(no_equiv): Don't clear reg_equiv_init or remove notes if the
|
||||
is_arg_equivalence field is set.
|
||||
* reload.h (reg_equiv_init, reg_equiv_init_size): Declare.
|
||||
* reload1.c (reg_equiv_init): No longer static.
|
||||
(reg_equiv_init_size): New variable.
|
||||
(reload): Don't allocate reg_equiv_init; don't free it when done but
|
||||
clear it.
|
||||
Restructure equivalence set up code not to set reg_equiv_init, but to
|
||||
clear it when we can't use an equivalence.
|
||||
Undo change disabling equivalences for MEM_READONLY_P memrefs.
|
||||
Dump equivalencing insns to dump_file.
|
||||
|
||||
2005-06-14 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* config/mips/mips.c (machine_function): Add varargs_size field.
|
||||
|
@ -2241,8 +2241,8 @@ regclass.o : regclass.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(TM_P_H) $(EXPR_H) $(TIMEVAR_H) gt-regclass.h $(HASHTAB_H)
|
||||
local-alloc.o : local-alloc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(FLAGS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
|
||||
output.h function.h $(INSN_ATTR_H) toplev.h except.h $(TM_P_H) \
|
||||
$(INTEGRATE_H)
|
||||
output.h function.h $(INSN_ATTR_H) toplev.h except.h reload.h $(TM_P_H) \
|
||||
$(GGC_H) $(INTEGRATE_H)
|
||||
bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(FLAGS_H) $(GGC_H) gt-bitmap.h bitmap.h $(OBSTACK_H)
|
||||
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
|
@ -76,6 +76,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "toplev.h"
|
||||
#include "except.h"
|
||||
#include "integrate.h"
|
||||
#include "reload.h"
|
||||
#include "ggc.h"
|
||||
|
||||
/* Next quantity number available for allocation. */
|
||||
|
||||
@ -260,6 +262,10 @@ struct equivalence
|
||||
/* The list of each instruction which initializes this register. */
|
||||
|
||||
rtx init_insns;
|
||||
|
||||
/* Nonzero if this had a preexisting REG_EQUIV note. */
|
||||
|
||||
int is_arg_equivalence;
|
||||
};
|
||||
|
||||
/* reg_equiv[N] (where N is a pseudo reg number) is the equivalence
|
||||
@ -344,8 +350,7 @@ local_alloc (void)
|
||||
|
||||
/* Promote REG_EQUAL notes to REG_EQUIV notes and adjust status of affected
|
||||
registers. */
|
||||
if (optimize)
|
||||
update_equiv_regs ();
|
||||
update_equiv_regs ();
|
||||
|
||||
/* This sets the maximum number of quantities we can have. Quantity
|
||||
numbers start at zero and we can have one for each pseudo. */
|
||||
@ -761,7 +766,9 @@ memref_used_between_p (rtx memref, rtx start, rtx end)
|
||||
|
||||
If such a register is only referenced once, try substituting its value
|
||||
into the using insn. If it succeeds, we can eliminate the register
|
||||
completely. */
|
||||
completely.
|
||||
|
||||
Initialize the REG_EQUIV_INIT array of initializing insns. */
|
||||
|
||||
static void
|
||||
update_equiv_regs (void)
|
||||
@ -774,6 +781,8 @@ update_equiv_regs (void)
|
||||
|
||||
reg_equiv = xcalloc (max_regno, sizeof *reg_equiv);
|
||||
INIT_REG_SET (&cleared_regs);
|
||||
reg_equiv_init = ggc_alloc_cleared (max_regno * sizeof (rtx));
|
||||
reg_equiv_init_size = max_regno;
|
||||
|
||||
init_alias_analysis ();
|
||||
|
||||
@ -824,44 +833,30 @@ update_equiv_regs (void)
|
||||
dest = SET_DEST (set);
|
||||
src = SET_SRC (set);
|
||||
|
||||
/* If this sets a MEM to the contents of a REG that is only used
|
||||
in a single basic block, see if the register is always equivalent
|
||||
to that memory location and if moving the store from INSN to the
|
||||
insn that set REG is safe. If so, put a REG_EQUIV note on the
|
||||
initializing insn.
|
||||
|
||||
Don't add a REG_EQUIV note if the insn already has one. The existing
|
||||
REG_EQUIV is likely more useful than the one we are adding.
|
||||
|
||||
If one of the regs in the address has reg_equiv[REGNO].replace set,
|
||||
then we can't add this REG_EQUIV note. The reg_equiv[REGNO].replace
|
||||
optimization may move the set of this register immediately before
|
||||
insn, which puts it after reg_equiv[REGNO].init_insns, and hence
|
||||
the mention in the REG_EQUIV note would be to an uninitialized
|
||||
pseudo. */
|
||||
/* ????? This test isn't good enough; we might see a MEM with a use of
|
||||
a pseudo register before we see its setting insn that will cause
|
||||
reg_equiv[].replace for that pseudo to be set.
|
||||
Equivalences to MEMs should be made in another pass, after the
|
||||
reg_equiv[].replace information has been gathered. */
|
||||
|
||||
if (MEM_P (dest) && REG_P (src)
|
||||
&& (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
|
||||
&& REG_BASIC_BLOCK (regno) >= 0
|
||||
&& REG_N_SETS (regno) == 1
|
||||
&& reg_equiv[regno].init_insns != 0
|
||||
&& reg_equiv[regno].init_insns != const0_rtx
|
||||
&& ! find_reg_note (XEXP (reg_equiv[regno].init_insns, 0),
|
||||
REG_EQUIV, NULL_RTX)
|
||||
&& ! contains_replace_regs (XEXP (dest, 0)))
|
||||
/* See if this is setting up the equivalence between an argument
|
||||
register and its stack slot. */
|
||||
note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
|
||||
if (note)
|
||||
{
|
||||
rtx init_insn = XEXP (reg_equiv[regno].init_insns, 0);
|
||||
if (validate_equiv_mem (init_insn, src, dest)
|
||||
&& ! memref_used_between_p (dest, init_insn, insn))
|
||||
REG_NOTES (init_insn)
|
||||
= gen_rtx_EXPR_LIST (REG_EQUIV, dest, REG_NOTES (init_insn));
|
||||
gcc_assert (REG_P (dest));
|
||||
regno = REGNO (dest);
|
||||
|
||||
/* Note that we don't want to clear reg_equiv_init even if there
|
||||
are multiple sets of this register. */
|
||||
reg_equiv[regno].is_arg_equivalence = 1;
|
||||
|
||||
/* Record for reload that this is an equivalencing insn. */
|
||||
if (rtx_equal_p (src, XEXP (note, 0)))
|
||||
reg_equiv_init[regno]
|
||||
= gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[regno]);
|
||||
|
||||
/* Continue normally in case this is a candidate for
|
||||
replacements. */
|
||||
}
|
||||
|
||||
if (!optimize)
|
||||
continue;
|
||||
|
||||
/* We only handle the case of a pseudo register being set
|
||||
once, or always to the same value. */
|
||||
/* ??? The mn10200 port breaks if we add equivalences for
|
||||
@ -878,7 +873,7 @@ update_equiv_regs (void)
|
||||
|| (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
|
||||
|| reg_equiv[regno].init_insns == const0_rtx
|
||||
|| (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
|
||||
&& MEM_P (src)))
|
||||
&& MEM_P (src) && ! reg_equiv[regno].is_arg_equivalence))
|
||||
{
|
||||
/* This might be setting a SUBREG of a pseudo, a pseudo that is
|
||||
also set somewhere else to a constant. */
|
||||
@ -944,20 +939,27 @@ update_equiv_regs (void)
|
||||
if (note)
|
||||
{
|
||||
int regno = REGNO (dest);
|
||||
rtx x = XEXP (note, 0);
|
||||
|
||||
/* If we haven't done so, record for reload that this is an
|
||||
equivalencing insn. */
|
||||
if (!reg_equiv[regno].is_arg_equivalence
|
||||
&& (!MEM_P (x) || rtx_equal_p (src, x)))
|
||||
reg_equiv_init[regno]
|
||||
= gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[regno]);
|
||||
|
||||
/* Record whether or not we created a REG_EQUIV note for a LABEL_REF.
|
||||
We might end up substituting the LABEL_REF for uses of the
|
||||
pseudo here or later. That kind of transformation may turn an
|
||||
indirect jump into a direct jump, in which case we must rerun the
|
||||
jump optimizer to ensure that the JUMP_LABEL fields are valid. */
|
||||
if (GET_CODE (XEXP (note, 0)) == LABEL_REF
|
||||
|| (GET_CODE (XEXP (note, 0)) == CONST
|
||||
&& GET_CODE (XEXP (XEXP (note, 0), 0)) == PLUS
|
||||
&& (GET_CODE (XEXP (XEXP (XEXP (note, 0), 0), 0))
|
||||
== LABEL_REF)))
|
||||
if (GET_CODE (x) == LABEL_REF
|
||||
|| (GET_CODE (x) == CONST
|
||||
&& GET_CODE (XEXP (x, 0)) == PLUS
|
||||
&& (GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)))
|
||||
recorded_label_ref = 1;
|
||||
|
||||
reg_equiv[regno].replacement = XEXP (note, 0);
|
||||
reg_equiv[regno].replacement = x;
|
||||
reg_equiv[regno].src_p = &SET_SRC (set);
|
||||
reg_equiv[regno].loop_depth = loop_depth;
|
||||
|
||||
@ -968,7 +970,6 @@ update_equiv_regs (void)
|
||||
in local-alloc! */
|
||||
REG_LIVE_LENGTH (regno) *= 2;
|
||||
|
||||
|
||||
/* If the register is referenced exactly twice, meaning it is
|
||||
set once and used once, indicate that the reference may be
|
||||
replaced by the equivalence we computed above. Do this
|
||||
@ -978,17 +979,79 @@ update_equiv_regs (void)
|
||||
and to reduce the number of registers alive across
|
||||
calls. */
|
||||
|
||||
if (REG_N_REFS (regno) == 2
|
||||
&& (rtx_equal_p (XEXP (note, 0), src)
|
||||
|| ! equiv_init_varies_p (src))
|
||||
&& NONJUMP_INSN_P (insn)
|
||||
&& equiv_init_movable_p (PATTERN (insn), regno))
|
||||
reg_equiv[regno].replace = 1;
|
||||
if (REG_N_REFS (regno) == 2
|
||||
&& (rtx_equal_p (x, src)
|
||||
|| ! equiv_init_varies_p (src))
|
||||
&& NONJUMP_INSN_P (insn)
|
||||
&& equiv_init_movable_p (PATTERN (insn), regno))
|
||||
reg_equiv[regno].replace = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!optimize)
|
||||
goto out;
|
||||
|
||||
/* A second pass, to gather additional equivalences with memory. This needs
|
||||
to be done after we know which registers we are going to replace. */
|
||||
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
rtx set, src, dest;
|
||||
unsigned regno;
|
||||
|
||||
if (! INSN_P (insn))
|
||||
continue;
|
||||
|
||||
set = single_set (insn);
|
||||
if (! set)
|
||||
continue;
|
||||
|
||||
dest = SET_DEST (set);
|
||||
src = SET_SRC (set);
|
||||
|
||||
/* If this sets a MEM to the contents of a REG that is only used
|
||||
in a single basic block, see if the register is always equivalent
|
||||
to that memory location and if moving the store from INSN to the
|
||||
insn that set REG is safe. If so, put a REG_EQUIV note on the
|
||||
initializing insn.
|
||||
|
||||
Don't add a REG_EQUIV note if the insn already has one. The existing
|
||||
REG_EQUIV is likely more useful than the one we are adding.
|
||||
|
||||
If one of the regs in the address has reg_equiv[REGNO].replace set,
|
||||
then we can't add this REG_EQUIV note. The reg_equiv[REGNO].replace
|
||||
optimization may move the set of this register immediately before
|
||||
insn, which puts it after reg_equiv[REGNO].init_insns, and hence
|
||||
the mention in the REG_EQUIV note would be to an uninitialized
|
||||
pseudo. */
|
||||
|
||||
if (MEM_P (dest) && REG_P (src)
|
||||
&& (regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER
|
||||
&& REG_BASIC_BLOCK (regno) >= 0
|
||||
&& REG_N_SETS (regno) == 1
|
||||
&& reg_equiv[regno].init_insns != 0
|
||||
&& reg_equiv[regno].init_insns != const0_rtx
|
||||
&& ! find_reg_note (XEXP (reg_equiv[regno].init_insns, 0),
|
||||
REG_EQUIV, NULL_RTX)
|
||||
&& ! contains_replace_regs (XEXP (dest, 0)))
|
||||
{
|
||||
rtx init_insn = XEXP (reg_equiv[regno].init_insns, 0);
|
||||
if (validate_equiv_mem (init_insn, src, dest)
|
||||
&& ! memref_used_between_p (dest, init_insn, insn))
|
||||
{
|
||||
REG_NOTES (init_insn)
|
||||
= gen_rtx_EXPR_LIST (REG_EQUIV, dest,
|
||||
REG_NOTES (init_insn));
|
||||
/* This insn makes the equivalence, not the one initializing
|
||||
the register. */
|
||||
reg_equiv_init[regno]
|
||||
= gen_rtx_INSN_LIST (VOIDmode, insn, NULL_RTX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now scan all regs killed in an insn to see if any of them are
|
||||
registers only used that once. If so, see if we can replace the
|
||||
reference with the equivalent form. If we can, delete the
|
||||
@ -1082,6 +1145,7 @@ update_equiv_regs (void)
|
||||
info. */
|
||||
SET_REGNO_REG_SET (&cleared_regs, regno);
|
||||
clear_regnos++;
|
||||
reg_equiv_init[regno] = NULL_RTX;
|
||||
}
|
||||
/* Move the initialization of the register to just before
|
||||
INSN. Update the flow information. */
|
||||
@ -1113,6 +1177,7 @@ update_equiv_regs (void)
|
||||
info. */
|
||||
SET_REGNO_REG_SET (&cleared_regs, regno);
|
||||
clear_regnos++;
|
||||
reg_equiv_init[regno] = NULL_RTX;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1146,6 +1211,7 @@ update_equiv_regs (void)
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
/* Clean up. */
|
||||
end_alias_analysis ();
|
||||
CLEAR_REG_SET (&cleared_regs);
|
||||
@ -1171,13 +1237,18 @@ no_equiv (rtx reg, rtx store ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
|
||||
list = reg_equiv[regno].init_insns;
|
||||
if (list == const0_rtx)
|
||||
return;
|
||||
reg_equiv[regno].init_insns = const0_rtx;
|
||||
reg_equiv[regno].replacement = NULL_RTX;
|
||||
/* This doesn't matter for equivalences made for argument registers, we
|
||||
should keep their initialization insns. */
|
||||
if (reg_equiv[regno].is_arg_equivalence)
|
||||
return;
|
||||
reg_equiv_init[regno] = NULL_RTX;
|
||||
for (; list; list = XEXP (list, 1))
|
||||
{
|
||||
rtx insn = XEXP (list, 0);
|
||||
remove_note (insn, find_reg_note (insn, REG_EQUIV, NULL_RTX));
|
||||
}
|
||||
reg_equiv[regno].init_insns = const0_rtx;
|
||||
reg_equiv[regno].replacement = NULL_RTX;
|
||||
}
|
||||
|
||||
/* Allocate hard regs to the pseudo regs used only within block number B.
|
||||
|
@ -170,6 +170,13 @@ extern rtx *reg_equiv_memory_loc;
|
||||
extern rtx *reg_equiv_address;
|
||||
extern rtx *reg_equiv_mem;
|
||||
|
||||
/* Element N is the list of insns that initialized reg N from its equivalent
|
||||
constant or memory slot. */
|
||||
extern GTY((length("reg_equiv_init_size"))) rtx *reg_equiv_init;
|
||||
|
||||
/* The size of the previous array, for GC purposes. */
|
||||
extern GTY(()) int reg_equiv_init_size;
|
||||
|
||||
/* All the "earlyclobber" operands of the current insn
|
||||
are recorded here. */
|
||||
extern int n_earlyclobbers;
|
||||
|
153
gcc/reload1.c
153
gcc/reload1.c
@ -120,7 +120,8 @@ static unsigned int *reg_max_ref_width;
|
||||
|
||||
/* Element N is the list of insns that initialized reg N from its equivalent
|
||||
constant or memory slot. */
|
||||
static rtx *reg_equiv_init;
|
||||
rtx *reg_equiv_init;
|
||||
int reg_equiv_init_size;
|
||||
|
||||
/* Vector to remember old contents of reg_renumber before spilling. */
|
||||
static short *reg_old_renumber;
|
||||
@ -693,7 +694,6 @@ reload (rtx first, int global)
|
||||
|
||||
reg_equiv_constant = xcalloc (max_regno, sizeof (rtx));
|
||||
reg_equiv_mem = xcalloc (max_regno, sizeof (rtx));
|
||||
reg_equiv_init = xcalloc (max_regno, sizeof (rtx));
|
||||
reg_equiv_address = xcalloc (max_regno, sizeof (rtx));
|
||||
reg_max_ref_width = xcalloc (max_regno, sizeof (int));
|
||||
reg_old_renumber = xcalloc (max_regno, sizeof (short));
|
||||
@ -719,101 +719,88 @@ reload (rtx first, int global)
|
||||
&& GET_MODE (insn) != VOIDmode)
|
||||
PUT_MODE (insn, VOIDmode);
|
||||
|
||||
if (INSN_P (insn))
|
||||
scan_paradoxical_subregs (PATTERN (insn));
|
||||
|
||||
if (set != 0 && REG_P (SET_DEST (set)))
|
||||
{
|
||||
rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
|
||||
if (note
|
||||
&& (! function_invariant_p (XEXP (note, 0))
|
||||
|| ! flag_pic
|
||||
/* A function invariant is often CONSTANT_P but may
|
||||
include a register. We promise to only pass
|
||||
CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */
|
||||
|| (CONSTANT_P (XEXP (note, 0))
|
||||
&& LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))))
|
||||
rtx x;
|
||||
|
||||
if (! note)
|
||||
continue;
|
||||
|
||||
i = REGNO (SET_DEST (set));
|
||||
x = XEXP (note, 0);
|
||||
|
||||
if (i <= LAST_VIRTUAL_REGISTER)
|
||||
continue;
|
||||
|
||||
if (! function_invariant_p (x)
|
||||
|| ! flag_pic
|
||||
/* A function invariant is often CONSTANT_P but may
|
||||
include a register. We promise to only pass
|
||||
CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */
|
||||
|| (CONSTANT_P (x)
|
||||
&& LEGITIMATE_PIC_OPERAND_P (x)))
|
||||
{
|
||||
rtx x = XEXP (note, 0);
|
||||
i = REGNO (SET_DEST (set));
|
||||
if (i > LAST_VIRTUAL_REGISTER)
|
||||
/* It can happen that a REG_EQUIV note contains a MEM
|
||||
that is not a legitimate memory operand. As later
|
||||
stages of reload assume that all addresses found
|
||||
in the reg_equiv_* arrays were originally legitimate,
|
||||
we ignore such REG_EQUIV notes. */
|
||||
if (memory_operand (x, VOIDmode))
|
||||
{
|
||||
/* It can happen that a REG_EQUIV note contains a MEM
|
||||
that is not a legitimate memory operand. As later
|
||||
stages of reload assume that all addresses found
|
||||
in the reg_equiv_* arrays were originally legitimate,
|
||||
|
||||
It can also happen that a REG_EQUIV note contains a
|
||||
readonly memory location. If the destination pseudo
|
||||
is set from some other value (typically a different
|
||||
pseudo), and the destination pseudo does not get a
|
||||
hard reg, then reload will replace the destination
|
||||
pseudo with its equivalent memory location. This
|
||||
is horribly bad as it creates a store to a readonly
|
||||
memory location and a runtime segfault. To avoid
|
||||
this problem we reject readonly memory locations
|
||||
for equivalences. This is overly conservative as
|
||||
we could find all sets of the destination pseudo
|
||||
and remove them as they should be redundant. */
|
||||
if (memory_operand (x, VOIDmode) && ! MEM_READONLY_P (x))
|
||||
/* Always unshare the equivalence, so we can
|
||||
substitute into this insn without touching the
|
||||
equivalence. */
|
||||
reg_equiv_memory_loc[i] = copy_rtx (x);
|
||||
}
|
||||
else if (function_invariant_p (x))
|
||||
{
|
||||
if (GET_CODE (x) == PLUS)
|
||||
{
|
||||
/* Always unshare the equivalence, so we can
|
||||
substitute into this insn without touching the
|
||||
equivalence. */
|
||||
reg_equiv_memory_loc[i] = copy_rtx (x);
|
||||
/* This is PLUS of frame pointer and a constant,
|
||||
and might be shared. Unshare it. */
|
||||
reg_equiv_constant[i] = copy_rtx (x);
|
||||
num_eliminable_invariants++;
|
||||
}
|
||||
else if (function_invariant_p (x))
|
||||
else if (x == frame_pointer_rtx
|
||||
|| x == arg_pointer_rtx)
|
||||
{
|
||||
if (GET_CODE (x) == PLUS)
|
||||
{
|
||||
/* This is PLUS of frame pointer and a constant,
|
||||
and might be shared. Unshare it. */
|
||||
reg_equiv_constant[i] = copy_rtx (x);
|
||||
num_eliminable_invariants++;
|
||||
}
|
||||
else if (x == frame_pointer_rtx
|
||||
|| x == arg_pointer_rtx)
|
||||
{
|
||||
reg_equiv_constant[i] = x;
|
||||
num_eliminable_invariants++;
|
||||
}
|
||||
else if (LEGITIMATE_CONSTANT_P (x))
|
||||
reg_equiv_constant[i] = x;
|
||||
else
|
||||
{
|
||||
reg_equiv_memory_loc[i]
|
||||
= force_const_mem (GET_MODE (SET_DEST (set)), x);
|
||||
if (!reg_equiv_memory_loc[i])
|
||||
continue;
|
||||
}
|
||||
reg_equiv_constant[i] = x;
|
||||
num_eliminable_invariants++;
|
||||
}
|
||||
else if (LEGITIMATE_CONSTANT_P (x))
|
||||
reg_equiv_constant[i] = x;
|
||||
else
|
||||
continue;
|
||||
|
||||
/* If this register is being made equivalent to a MEM
|
||||
and the MEM is not SET_SRC, the equivalencing insn
|
||||
is one with the MEM as a SET_DEST and it occurs later.
|
||||
So don't mark this insn now. */
|
||||
if (!MEM_P (x)
|
||||
|| rtx_equal_p (SET_SRC (set), x))
|
||||
reg_equiv_init[i]
|
||||
= gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]);
|
||||
{
|
||||
reg_equiv_memory_loc[i]
|
||||
= force_const_mem (GET_MODE (SET_DEST (set)), x);
|
||||
if (! reg_equiv_memory_loc[i])
|
||||
reg_equiv_init[i] = NULL_RTX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_equiv_init[i] = NULL_RTX;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
reg_equiv_init[i] = NULL_RTX;
|
||||
}
|
||||
|
||||
/* If this insn is setting a MEM from a register equivalent to it,
|
||||
this is the equivalencing insn. */
|
||||
else if (set && MEM_P (SET_DEST (set))
|
||||
&& REG_P (SET_SRC (set))
|
||||
&& reg_equiv_memory_loc[REGNO (SET_SRC (set))]
|
||||
&& rtx_equal_p (SET_DEST (set),
|
||||
reg_equiv_memory_loc[REGNO (SET_SRC (set))]))
|
||||
reg_equiv_init[REGNO (SET_SRC (set))]
|
||||
= gen_rtx_INSN_LIST (VOIDmode, insn,
|
||||
reg_equiv_init[REGNO (SET_SRC (set))]);
|
||||
|
||||
if (INSN_P (insn))
|
||||
scan_paradoxical_subregs (PATTERN (insn));
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
|
||||
if (reg_equiv_init[i])
|
||||
{
|
||||
fprintf (dump_file, "init_insns for %u: ", i);
|
||||
print_inline_rtx (dump_file, reg_equiv_init[i], 20);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
init_elim_table ();
|
||||
|
||||
first_label_num = get_first_label_num ();
|
||||
@ -1260,7 +1247,7 @@ reload (rtx first, int global)
|
||||
free (offsets_at);
|
||||
|
||||
free (reg_equiv_mem);
|
||||
free (reg_equiv_init);
|
||||
reg_equiv_init = 0;
|
||||
free (reg_equiv_address);
|
||||
free (reg_max_ref_width);
|
||||
free (reg_old_renumber);
|
||||
|
Loading…
Reference in New Issue
Block a user