Commit d7f88d86 by Bernd Schmidt Committed by Bernd Schmidt

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
parent ae973d6a
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> 2005-06-14 Richard Sandiford <richard@codesourcery.com>
* config/mips/mips.c (machine_function): Add varargs_size field. * 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) \ ...@@ -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) $(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) \ 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) \ $(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) \ output.h function.h $(INSN_ATTR_H) toplev.h except.h reload.h $(TM_P_H) \
$(INTEGRATE_H) $(GGC_H) $(INTEGRATE_H)
bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_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) $(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) \ global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
......
...@@ -170,6 +170,13 @@ extern rtx *reg_equiv_memory_loc; ...@@ -170,6 +170,13 @@ extern rtx *reg_equiv_memory_loc;
extern rtx *reg_equiv_address; extern rtx *reg_equiv_address;
extern rtx *reg_equiv_mem; 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 /* All the "earlyclobber" operands of the current insn
are recorded here. */ are recorded here. */
extern int n_earlyclobbers; extern int n_earlyclobbers;
......
...@@ -120,7 +120,8 @@ static unsigned int *reg_max_ref_width; ...@@ -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 /* Element N is the list of insns that initialized reg N from its equivalent
constant or memory slot. */ 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. */ /* Vector to remember old contents of reg_renumber before spilling. */
static short *reg_old_renumber; static short *reg_old_renumber;
...@@ -693,7 +694,6 @@ reload (rtx first, int global) ...@@ -693,7 +694,6 @@ reload (rtx first, int global)
reg_equiv_constant = xcalloc (max_regno, sizeof (rtx)); reg_equiv_constant = xcalloc (max_regno, sizeof (rtx));
reg_equiv_mem = 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_equiv_address = xcalloc (max_regno, sizeof (rtx));
reg_max_ref_width = xcalloc (max_regno, sizeof (int)); reg_max_ref_width = xcalloc (max_regno, sizeof (int));
reg_old_renumber = xcalloc (max_regno, sizeof (short)); reg_old_renumber = xcalloc (max_regno, sizeof (short));
...@@ -719,101 +719,88 @@ reload (rtx first, int global) ...@@ -719,101 +719,88 @@ reload (rtx first, int global)
&& GET_MODE (insn) != VOIDmode) && GET_MODE (insn) != VOIDmode)
PUT_MODE (insn, VOIDmode); PUT_MODE (insn, VOIDmode);
if (INSN_P (insn))
scan_paradoxical_subregs (PATTERN (insn));
if (set != 0 && REG_P (SET_DEST (set))) if (set != 0 && REG_P (SET_DEST (set)))
{ {
rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX); rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
if (note rtx x;
&& (! function_invariant_p (XEXP (note, 0))
|| ! flag_pic if (! note)
/* A function invariant is often CONSTANT_P but may continue;
include a register. We promise to only pass
CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P. */ i = REGNO (SET_DEST (set));
|| (CONSTANT_P (XEXP (note, 0)) x = XEXP (note, 0);
&& LEGITIMATE_PIC_OPERAND_P (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); /* It can happen that a REG_EQUIV note contains a MEM
i = REGNO (SET_DEST (set)); that is not a legitimate memory operand. As later
if (i > LAST_VIRTUAL_REGISTER) 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 /* Always unshare the equivalence, so we can
that is not a legitimate memory operand. As later substitute into this insn without touching the
stages of reload assume that all addresses found equivalence. */
in the reg_equiv_* arrays were originally legitimate, reg_equiv_memory_loc[i] = copy_rtx (x);
}
It can also happen that a REG_EQUIV note contains a else if (function_invariant_p (x))
readonly memory location. If the destination pseudo {
is set from some other value (typically a different if (GET_CODE (x) == PLUS)
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 /* This is PLUS of frame pointer and a constant,
substitute into this insn without touching the and might be shared. Unshare it. */
equivalence. */ reg_equiv_constant[i] = copy_rtx (x);
reg_equiv_memory_loc[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) reg_equiv_constant[i] = x;
{ num_eliminable_invariants++;
/* 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;
}
} }
else if (LEGITIMATE_CONSTANT_P (x))
reg_equiv_constant[i] = x;
else else
continue; {
reg_equiv_memory_loc[i]
/* If this register is being made equivalent to a MEM = force_const_mem (GET_MODE (SET_DEST (set)), x);
and the MEM is not SET_SRC, the equivalencing insn if (! reg_equiv_memory_loc[i])
is one with the MEM as a SET_DEST and it occurs later. reg_equiv_init[i] = NULL_RTX;
So don't mark this insn now. */ }
if (!MEM_P (x) }
|| rtx_equal_p (SET_SRC (set), x)) else
reg_equiv_init[i] {
= gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]); 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 (); init_elim_table ();
first_label_num = get_first_label_num (); first_label_num = get_first_label_num ();
...@@ -1260,7 +1247,7 @@ reload (rtx first, int global) ...@@ -1260,7 +1247,7 @@ reload (rtx first, int global)
free (offsets_at); free (offsets_at);
free (reg_equiv_mem); free (reg_equiv_mem);
free (reg_equiv_init); reg_equiv_init = 0;
free (reg_equiv_address); free (reg_equiv_address);
free (reg_max_ref_width); free (reg_max_ref_width);
free (reg_old_renumber); free (reg_old_renumber);
......
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