+2002-06-10 Jeffrey Law <law@redhat.com>
+
+ * alias.c (static_reg_base_value): New to hold RTL for
+ items allocated once per function for the aliasing code.
+ (init_alias_once_per_function): Initialize static_reg_base_value.
+ (init_alias_analysis): Avoid throw-away allocations of RTL by
+ using pre-computed values in static_reg_base_value.
+ * function.c (prepare_function_start): Call
+ init_alias_once_per_function appropriately.
+ * rtl.h (init_alias_once_per_function): Declare.
+ * caller-save (init_caller_save): Restructure slightly to
+ avoid lots of silly RTL generation.
+ * expr.c (init_expr_once): Likewise.
+ * reload1.c (reload_cse_regs_1): Allocate throw-away register
+ RTL object here. Pass it into children.
+ (reload_cse_simplify_operands): Use passed-in register RTL
+ object.
+ (reload_cse_simplify): Pass through throw-away register
+ RTL object.
+
2002-06-10 Daniel Berlin <dberlin@dberlin.org>
* Makefile.in (ssa.o): Add dependency on $(RTL_H), which was missing.
static rtx *new_reg_base_value;
static unsigned int reg_base_value_size; /* size of reg_base_value array */
+/* Static hunks of RTL used by the aliasing code; these are initialized
+ once per function to avoid unnecessary RTL allocations. */
+static GTY (()) rtx static_reg_base_value[FIRST_PSEUDO_REGISTER];
+
#define REG_BASE_VALUE(X) \
(REGNO (X) < reg_base_value_size \
? reg_base_value[REGNO (X)] : 0)
alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
}
+/* Per-function initializer for the aliasing code.
+
+ Allocate RTL for argument and other special use registers once
+ per function here intead of multiple times per function in
+ init_alias_analysis. */
+
+void
+init_alias_once_per_function ()
+{
+ int i;
+
+ /* Generate and mark all hard registers which may contain an address.
+ The stack, frame and argument pointers may contain an address.
+ An argument register which can hold a Pmode value may contain
+ an address even if it is not in BASE_REGS.
+
+ The address expression is VOIDmode for an argument and
+ Pmode for other registers. */
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (argument_registers, i))
+ static_reg_base_value[i]
+ = gen_rtx_ADDRESS (VOIDmode, gen_rtx_REG (Pmode, i));
+
+
+ static_reg_base_value[STACK_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx);
+ static_reg_base_value[ARG_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
+ static_reg_base_value[FRAME_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ static_reg_base_value[HARD_FRAME_POINTER_REGNUM]
+ = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
+#endif
+}
+
/* Initialize the aliasing machinery. Initialize the REG_KNOWN_VALUE
array. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (argument_registers, i))
- new_reg_base_value[i] = gen_rtx_ADDRESS (VOIDmode,
- gen_rtx_REG (Pmode, i));
+ new_reg_base_value[i] = static_reg_base_value[i];
new_reg_base_value[STACK_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, stack_pointer_rtx);
+ = static_reg_base_value[STACK_POINTER_REGNUM];
new_reg_base_value[ARG_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, arg_pointer_rtx);
+ = static_reg_base_value[ARG_POINTER_REGNUM];
new_reg_base_value[FRAME_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, frame_pointer_rtx);
+ = static_reg_base_value[FRAME_POINTER_REGNUM];
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
new_reg_base_value[HARD_FRAME_POINTER_REGNUM]
- = gen_rtx_ADDRESS (Pmode, hard_frame_pointer_rtx);
+ = static_reg_base_value[HARD_FRAME_POINTER_REGNUM];
#endif
-
/* Walk the insns adding values to the new_reg_base_value array. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx address;
int i, j;
enum machine_mode mode;
+ rtx savepat, restpat;
+ rtx test_reg, test_mem;
+ rtx saveinsn, restinsn;
/* First find all the registers that we need to deal with and all
the modes that they can have. If we can't find a mode to use,
address = addr_reg;
/* Next we try to form an insn to save and restore the register. We
- see if such an insn is recognized and meets its constraints. */
+ see if such an insn is recognized and meets its constraints.
+
+ To avoid lots of unnecessary RTL allocation, we construct all the RTL
+ once, then modify the memory and register operands in-place. */
+
+ test_reg = gen_rtx_REG (VOIDmode, 0);
+ test_mem = gen_rtx_MEM (VOIDmode, address);
+ savepat = gen_rtx_SET (VOIDmode, test_mem, test_reg);
+ restpat = gen_rtx_SET (VOIDmode, test_reg, test_mem);
+ saveinsn = emit_insn (savepat);
+ restinsn = emit_insn (restpat);
start_sequence ();
for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
if (HARD_REGNO_MODE_OK (i, mode))
{
- rtx mem = gen_rtx_MEM (mode, address);
- rtx reg = gen_rtx_REG (mode, i);
- rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
- rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
- rtx saveinsn = emit_insn (savepat);
- rtx restinsn = emit_insn (restpat);
int ok;
+ /* Update the register number and modes of the register
+ and memory operand. */
+ REGNO (test_reg) = i;
+ PUT_MODE (test_reg, mode);
+ PUT_MODE (test_mem, mode);
+
reg_save_code[i][mode] = recog_memoized (saveinsn);
reg_restore_code[i][mode] = recog_memoized (restinsn);
enum machine_mode mode;
int num_clobbers;
rtx mem, mem1;
+ rtx reg;
/* Try indexing by frame ptr and try by stack ptr.
It is known that on the Convex the stack ptr isn't a valid index.
mem = gen_rtx_MEM (VOIDmode, stack_pointer_rtx);
mem1 = gen_rtx_MEM (VOIDmode, frame_pointer_rtx);
+ /* A scratch register we can modify in-place below to avoid
+ useless RTL allocations. */
+ reg = gen_rtx_REG (VOIDmode, -1);
+
insn = rtx_alloc (INSN);
pat = gen_rtx_SET (0, NULL_RTX, NULL_RTX);
PATTERN (insn) = pat;
mode = (enum machine_mode) ((int) mode + 1))
{
int regno;
- rtx reg;
direct_load[(int) mode] = direct_store[(int) mode] = 0;
PUT_MODE (mem, mode);
PUT_MODE (mem1, mode);
+ PUT_MODE (reg, mode);
/* See if there is some register that can be used in this mode and
directly loaded or stored from memory. */
if (! HARD_REGNO_MODE_OK (regno, mode))
continue;
- reg = gen_rtx_REG (mode, regno);
+ REGNO (reg) = regno;
SET_SRC (pat) = mem;
SET_DEST (pat) = reg;
/* Initialize the RTL mechanism. */
init_emit ();
+ /* Do per-function initialization of the alias analyzer. */
+ init_alias_once_per_function ();
+
/* Initialize the queue of pending postincrement and postdecrements,
and some other info in expr.c. */
init_expr ();
static void reload_cse_regs_1 PARAMS ((rtx));
static int reload_cse_noop_set_p PARAMS ((rtx));
static int reload_cse_simplify_set PARAMS ((rtx, rtx));
-static int reload_cse_simplify_operands PARAMS ((rtx));
+static int reload_cse_simplify_operands PARAMS ((rtx, rtx));
static void reload_combine PARAMS ((void));
static void reload_combine_note_use PARAMS ((rtx *, rtx));
static void reload_combine_note_store PARAMS ((rtx, rtx, void *));
HOST_WIDE_INT));
static void failed_reload PARAMS ((rtx, int));
static int set_reload_reg PARAMS ((int, int));
-static void reload_cse_simplify PARAMS ((rtx));
+static void reload_cse_simplify PARAMS ((rtx, rtx));
void fixup_abnormal_edges PARAMS ((void));
extern void dump_needs PARAMS ((struct insn_chain *));
\f
/* Try to simplify INSN. */
static void
-reload_cse_simplify (insn)
+reload_cse_simplify (insn, testreg)
rtx insn;
+ rtx testreg;
{
rtx body = PATTERN (insn);
if (count > 0)
apply_change_group ();
else
- reload_cse_simplify_operands (insn);
+ reload_cse_simplify_operands (insn, testreg);
}
else if (GET_CODE (body) == PARALLEL)
{
if (count > 0)
apply_change_group ();
else
- reload_cse_simplify_operands (insn);
+ reload_cse_simplify_operands (insn, testreg);
}
}
rtx first;
{
rtx insn;
+ rtx testreg = gen_rtx_REG (VOIDmode, -1);
cselib_init ();
init_alias_analysis ();
for (insn = first; insn; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
- reload_cse_simplify (insn);
+ reload_cse_simplify (insn, testreg);
cselib_process_insn (insn);
}
hard registers. */
static int
-reload_cse_simplify_operands (insn)
+reload_cse_simplify_operands (insn, testreg)
rtx insn;
+ rtx testreg;
{
int i, j;
int *op_alt_regno[MAX_RECOG_OPERANDS];
/* Array of alternatives, sorted in order of decreasing desirability. */
int *alternative_order;
- rtx reg = gen_rtx_REG (VOIDmode, -1);
extract_insn (insn);
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
- REGNO (reg) = regno;
- PUT_MODE (reg, mode);
+ REGNO (testreg) = regno;
+ PUT_MODE (testreg, mode);
/* We found a register equal to this operand. Now look for all
alternatives that can accept this register and have not been
alternative yet and the operand being replaced is not
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
- && reg_fits_class_p (reg, class, 0, mode)
+ && reg_fits_class_p (testreg, class, 0, mode)
&& (GET_CODE (recog_data.operand[i]) != CONST_INT
|| (rtx_cost (recog_data.operand[i], SET)
- > rtx_cost (reg, SET))))
+ > rtx_cost (testreg, SET))))
{
alternative_nregs[j]++;
op_alt_regno[i][j] = regno;
extern int output_dependence PARAMS ((rtx, rtx));
extern void mark_constant_function PARAMS ((void));
extern void init_alias_once PARAMS ((void));
+extern void init_alias_once_per_function PARAMS ((void));
extern void init_alias_analysis PARAMS ((void));
extern void end_alias_analysis PARAMS ((void));
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));