local-alloc.c (function_invariant_p): New function.

* local-alloc.c (function_invariant_p): New function.
	(update_equiv_regs): Use function_invariant_p instead of CONSTANT_P
	to decide if an equivalence should be recorded.
	* reload1.c (num_eliminable_invariants): New static variable.
	(reload): Set it.  Use function_invariant_p instead of CONSTANT_P
	to decide if an equivalence should be recorded.
	Unshare PLUS.
	(calculate_needs_all_insns): Skip insns that only set an equivalence.
	Take num_eliminable_invariants into account when deciding
	if register elimination should be done.
	(reload_as_needed): Take num_eliminable_invariants into account
	when deciding if register elimination should be done.
	(eliminate_regs): Handle non-constant reg_equiv_constant.
	* rtl.h (function_invariant_p): Declare.

From-SVN: r24026
This commit is contained in:
J"orn Rennecke 1998-12-01 10:00:11 +00:00 committed by Joern Rennecke
parent bbe348cd18
commit 2b49ee3981
4 changed files with 71 additions and 7 deletions

View File

@ -1,3 +1,20 @@
Tue Dec 1 17:58:26 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
* local-alloc.c (function_invariant_p): New function.
(update_equiv_regs): Use function_invariant_p instead of CONSTANT_P
to decide if an equivalence should be recorded.
* reload1.c (num_eliminable_invariants): New static variable.
(reload): Set it. Use function_invariant_p instead of CONSTANT_P
to decide if an equivalence should be recorded.
Unshare PLUS.
(calculate_needs_all_insns): Skip insns that only set an equivalence.
Take num_eliminable_invariants into account when deciding
if register elimination should be done.
(reload_as_needed): Take num_eliminable_invariants into account
when deciding if register elimination should be done.
(eliminate_regs): Handle non-constant reg_equiv_constant.
* rtl.h (function_invariant_p): Declare.
Mon Nov 30 02:00:08 PST 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.

View File

@ -630,6 +630,22 @@ memref_used_between_p (memref, start, end)
return 0;
}
/* Return nonzero if the rtx X is invariant over the current function. */
int
function_invariant_p (x)
rtx x;
{
if (CONSTANT_P (x))
return 1;
if (x == frame_pointer_rtx || x == arg_pointer_rtx)
return 1;
if (GET_CODE (x) == PLUS
&& (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
&& CONSTANT_P (XEXP (x, 1)))
return 1;
return 0;
}
/* Find registers that are equivalent to a single value throughout the
compilation (either because they can be referenced in memory or are set once
from a single constant). Lower their priority for a register.
@ -798,7 +814,7 @@ update_equiv_regs ()
if (REG_N_SETS (regno) != 1
&& (! note
|| ! CONSTANT_P (XEXP (note, 0))
|| ! function_invariant_p (XEXP (note, 0))
|| (reg_equiv_replacement[regno]
&& ! rtx_equal_p (XEXP (note, 0),
reg_equiv_replacement[regno]))))
@ -812,7 +828,7 @@ update_equiv_regs ()
/* If this register is known to be equal to a constant, record that
it is always equivalent to the constant. */
if (note && CONSTANT_P (XEXP (note, 0)))
if (note && function_invariant_p (XEXP (note, 0)))
PUT_MODE (note, (enum machine_mode) REG_EQUIV);
/* If this insn introduces a "constant" register, decrease the priority

View File

@ -338,6 +338,9 @@ int num_not_at_initial_offset;
/* Count the number of registers that we may be able to eliminate. */
static int num_eliminable;
/* And the number of registers that are equivalent to a constant that
can be eliminated to frame_pointer / arg_pointer + constant. */
static int num_eliminable_invariants;
/* For each label, we record the offset of each elimination. If we reach
a label by more than one path and an offset differs, we cannot do the
@ -659,6 +662,7 @@ reload (first, global, dumpfile)
Also look for a "constant" NOTE_INSN_SETJMP. This means that all
caller-saved registers must be marked live. */
num_eliminable_invariants = 0;
for (insn = first; insn; insn = NEXT_INSN (insn))
{
rtx set = single_set (insn);
@ -674,7 +678,8 @@ reload (first, global, dumpfile)
rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
if (note
#ifdef LEGITIMATE_PIC_OPERAND_P
&& (! CONSTANT_P (XEXP (note, 0)) || ! flag_pic
&& (! function_invariant_p (XEXP (note, 0))
|| ! flag_pic
|| LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))
#endif
)
@ -692,9 +697,22 @@ reload (first, global, dumpfile)
reg_equiv_memory_loc[i] = x;
}
else if (CONSTANT_P (x))
else if (function_invariant_p (x))
{
if (LEGITIMATE_CONSTANT_P (x))
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]
@ -1335,9 +1353,16 @@ calculate_needs_all_insns (global)
rtx old_notes = REG_NOTES (insn);
int did_elimination = 0;
int operands_changed = 0;
rtx set = single_set (insn);
/* Skip insns that only set an equivalence. */
if (set && GET_CODE (SET_DEST (set)) == REG
&& reg_renumber[REGNO (SET_DEST (set))] < 0
&& reg_equiv_constant[REGNO (SET_DEST (set))])
continue;
/* If needed, eliminate any eliminable registers. */
if (num_eliminable)
if (num_eliminable || num_eliminable_invariants)
did_elimination = eliminate_regs_in_insn (insn, 0);
/* Analyze the instruction. */
@ -2698,6 +2723,11 @@ eliminate_regs (x, mem_mode, insn)
}
}
else if (reg_renumber[regno] < 0 && reg_equiv_constant
&& reg_equiv_constant[regno]
&& ! CONSTANT_P (reg_equiv_constant[regno]))
return eliminate_regs (copy_rtx (reg_equiv_constant[regno]),
mem_mode, insn);
return x;
case PLUS:
@ -4163,7 +4193,7 @@ reload_as_needed (live_known)
/* If we need to do register elimination processing, do so.
This might delete the insn, in which case we are done. */
if (num_eliminable && chain->need_elim)
if ((num_eliminable || num_eliminable_invariants) && chain->need_elim)
{
eliminate_regs_in_insn (insn, 1);
if (GET_CODE (insn) == NOTE)

View File

@ -1440,6 +1440,7 @@ extern void init_optabs PROTO ((void));
extern void dump_local_alloc PROTO ((FILE *));
#endif
extern void local_alloc PROTO ((void));
extern int function_invariant_p PROTO ((rtx));
/* In reload1.c */
extern void reload_cse_regs PROTO ((rtx));