aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/local-alloc.c20
-rw-r--r--gcc/reload1.c40
-rw-r--r--gcc/rtl.h1
4 files changed, 71 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 74a9a59..ee4b9ff 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index e8110ac..f112713 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -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
diff --git a/gcc/reload1.c b/gcc/reload1.c
index e4dee18..08f5375 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -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)
diff --git a/gcc/rtl.h b/gcc/rtl.h
index bf9a603..93e7842 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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));