+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.
return 0;
}
\f
+/* 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.
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]))))
/* 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
/* 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
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);
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
)
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]
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. */
}
}
+ 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:
/* 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)