current function performs nonlocal memory memory references for the
purposes of marking the function as a constant function. */
-static GTY((length ("reg_base_value_size"))) rtx *reg_base_value;
+static GTY(()) varray_type reg_base_value;
static rtx *new_reg_base_value;
-static unsigned int reg_base_value_size; /* size of reg_base_value array */
+
+/* We preserve the copy of old array around to avoid amount of garbage
+ produced. About 8% of garbage produced were attributed to this
+ array. */
+static GTY((deletable (""))) varray_type old_reg_base_value;
/* 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)
+ (reg_base_value && REGNO (X) < VARRAY_SIZE (reg_base_value) \
+ ? VARRAY_RTX (reg_base_value, REGNO (X)) : 0)
/* Vector of known invariant relationships between registers. Set in
loop unrolling. Indexed by register number, if nonzero the value
Because this array contains only pseudo registers it has no effect
after reload. */
static rtx *alias_invariant;
+unsigned int alias_invariant_size;
/* Vector indexed by N giving the initial (unchanging) value known for
pseudo-register N. This array is initialized in
The test above is not sufficient because the scheduler may move
a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN. */
if ((regno >= FIRST_PSEUDO_REGISTER || fixed_regs[regno])
- && regno < reg_base_value_size)
+ && regno < VARRAY_SIZE (reg_base_value))
{
/* If we're inside init_alias_analysis, use new_reg_base_value
to reduce the number of relaxation iterations. */
&& REG_N_SETS (regno) == 1)
return new_reg_base_value[regno];
- if (reg_base_value[regno])
- return reg_base_value[regno];
+ if (VARRAY_RTX (reg_base_value, regno))
+ return VARRAY_RTX (reg_base_value, regno);
}
return 0;
regno = REGNO (dest);
- if (regno >= reg_base_value_size)
+ if (regno >= VARRAY_SIZE (reg_base_value))
abort ();
/* If this spans multiple hard registers, then we must indicate that every
void
record_base_value (unsigned int regno, rtx val, int invariant)
{
- if (regno >= reg_base_value_size)
- return;
-
- if (invariant && alias_invariant)
+ if (invariant && alias_invariant && regno < alias_invariant_size)
alias_invariant[regno] = val;
+ if (regno >= VARRAY_SIZE (reg_base_value))
+ VARRAY_GROW (reg_base_value, max_reg_num ());
+
if (GET_CODE (val) == REG)
{
- if (REGNO (val) < reg_base_value_size)
- reg_base_value[regno] = reg_base_value[REGNO (val)];
-
+ VARRAY_RTX (reg_base_value, regno)
+ = REG_BASE_VALUE (val);
return;
}
-
- reg_base_value[regno] = find_base_value (val);
+ VARRAY_RTX (reg_base_value, regno)
+ = find_base_value (val);
}
/* Clear alias info for a register. This is used if an RTL transformation
unsigned int r_x = REGNO (x), r_y = REGNO (y);
rtx i_x, i_y; /* invariant relationships of X and Y */
- i_x = r_x >= reg_base_value_size ? 0 : alias_invariant[r_x];
- i_y = r_y >= reg_base_value_size ? 0 : alias_invariant[r_y];
+ i_x = r_x >= alias_invariant_size ? 0 : alias_invariant[r_x];
+ i_y = r_y >= alias_invariant_size ? 0 : alias_invariant[r_y];
if (i_x == 0 && i_y == 0)
break;
void
init_alias_analysis (void)
{
- int maxreg = max_reg_num ();
+ unsigned int maxreg = max_reg_num ();
int changed, pass;
int i;
unsigned int ui;
/* Overallocate reg_base_value to allow some growth during loop
optimization. Loop unrolling can create a large number of
registers. */
- reg_base_value_size = maxreg * 2;
- reg_base_value = ggc_alloc_cleared (reg_base_value_size * sizeof (rtx));
+ if (old_reg_base_value)
+ {
+ reg_base_value = old_reg_base_value;
+ /* If varray gets large zeroing cost may get important. */
+ if (VARRAY_SIZE (reg_base_value) > 256
+ && VARRAY_SIZE (reg_base_value) > 4 * maxreg)
+ VARRAY_GROW (reg_base_value, maxreg);
+ VARRAY_CLEAR (reg_base_value);
+ if (VARRAY_SIZE (reg_base_value) < maxreg)
+ VARRAY_GROW (reg_base_value, maxreg);
+ }
+ else
+ {
+ VARRAY_RTX_INIT (reg_base_value, maxreg, "reg_base_value");
+ }
- new_reg_base_value = xmalloc (reg_base_value_size * sizeof (rtx));
- reg_seen = xmalloc (reg_base_value_size);
+ new_reg_base_value = xmalloc (maxreg * sizeof (rtx));
+ reg_seen = xmalloc (maxreg);
if (! reload_completed && flag_old_unroll_loops)
{
/* ??? Why are we realloc'ing if we're just going to zero it? */
alias_invariant = xrealloc (alias_invariant,
- reg_base_value_size * sizeof (rtx));
- memset (alias_invariant, 0, reg_base_value_size * sizeof (rtx));
+ maxreg * sizeof (rtx));
+ memset (alias_invariant, 0, maxreg * sizeof (rtx));
+ alias_invariant_size = maxreg;
}
/* The basic idea is that each pass through this loop will use the
copying_arguments = true;
/* Wipe the potential alias information clean for this pass. */
- memset (new_reg_base_value, 0, reg_base_value_size * sizeof (rtx));
+ memset (new_reg_base_value, 0, maxreg * sizeof (rtx));
/* Wipe the reg_seen array clean. */
- memset (reg_seen, 0, reg_base_value_size);
+ memset (reg_seen, 0, maxreg);
/* Mark all hard registers which may contain an address.
The stack, frame and argument pointers may contain an address.
}
/* Now propagate values from new_reg_base_value to reg_base_value. */
- for (ui = 0; ui < reg_base_value_size; ui++)
+ if (maxreg != (unsigned int) max_reg_num())
+ abort ();
+ for (ui = 0; ui < maxreg; ui++)
{
if (new_reg_base_value[ui]
- && new_reg_base_value[ui] != reg_base_value[ui]
- && ! rtx_equal_p (new_reg_base_value[ui], reg_base_value[ui]))
+ && new_reg_base_value[ui] != VARRAY_RTX (reg_base_value, ui)
+ && ! rtx_equal_p (new_reg_base_value[ui],
+ VARRAY_RTX (reg_base_value, ui)))
{
- reg_base_value[ui] = new_reg_base_value[ui];
+ VARRAY_RTX (reg_base_value, ui) = new_reg_base_value[ui];
changed = 1;
}
}
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
/* Fill in the remaining entries. */
- for (i = FIRST_PSEUDO_REGISTER; i < maxreg; i++)
+ for (i = FIRST_PSEUDO_REGISTER; i < (int)maxreg; i++)
if (reg_known_value[i] == 0)
reg_known_value[i] = regno_reg_rtx[i];
{
changed = 0;
pass++;
- for (ui = 0; ui < reg_base_value_size; ui++)
+ for (ui = 0; ui < maxreg; ui++)
{
- rtx base = reg_base_value[ui];
+ rtx base = VARRAY_RTX (reg_base_value, ui);
if (base && GET_CODE (base) == REG)
{
unsigned int base_regno = REGNO (base);
if (base_regno == ui) /* register set from itself */
- reg_base_value[ui] = 0;
+ VARRAY_RTX (reg_base_value, ui) = 0;
else
- reg_base_value[ui] = reg_base_value[base_regno];
+ VARRAY_RTX (reg_base_value, ui)
+ = VARRAY_RTX (reg_base_value, base_regno);
changed = 1;
}
}
void
end_alias_analysis (void)
{
+ old_reg_base_value = reg_base_value;
free (reg_known_value + FIRST_PSEUDO_REGISTER);
reg_known_value = 0;
reg_known_value_size = 0;
free (reg_known_equiv_p + FIRST_PSEUDO_REGISTER);
reg_known_equiv_p = 0;
- reg_base_value = 0;
- reg_base_value_size = 0;
if (alias_invariant)
{
free (alias_invariant);
alias_invariant = 0;
+ alias_invariant_size = 0;
}
}