Because this array contains only pseudo registers it has no effect
after reload. */
-static rtx *alias_invariant;
-unsigned int alias_invariant_size;
+static GTY((length("alias_invariant_size"))) rtx *alias_invariant;
+unsigned GTY(()) int alias_invariant_size;
/* Vector indexed by N giving the initial (unchanging) value known for
- pseudo-register N. This array is initialized in
- init_alias_analysis, and does not change until end_alias_analysis
- is called. */
-rtx *reg_known_value;
+ pseudo-register N. This array is initialized in init_alias_analysis,
+ and does not change until end_alias_analysis is called. */
+static GTY((length("reg_known_value_size"))) rtx *reg_known_value;
/* Indicates number of valid entries in reg_known_value. */
-static unsigned int reg_known_value_size;
+static GTY(()) unsigned int reg_known_value_size;
/* Vector recording for each reg_known_value whether it is due to a
REG_EQUIV note. Future passes (viz., reload) may replace the
REG_EQUIV notes. One could argue that the REG_EQUIV notes are
wrong, but solving the problem in the scheduler will likely give
better code, so we do it here. */
-char *reg_known_equiv_p;
+static bool *reg_known_equiv_p;
/* True when scanning insns from the start of the rtl to the
NOTE_INSN_FUNCTION_BEG note. */
{
unsigned int regno = REGNO (reg);
- if (regno < reg_known_value_size && regno >= FIRST_PSEUDO_REGISTER)
- reg_known_value[regno] = reg;
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ regno -= FIRST_PSEUDO_REGISTER;
+ if (regno < reg_known_value_size)
+ {
+ reg_known_value[regno] = reg;
+ reg_known_equiv_p[regno] = false;
+ }
+ }
+}
+
+/* If a value is known for REGNO, return it. */
+
+rtx
+get_reg_known_value (unsigned int regno)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ regno -= FIRST_PSEUDO_REGISTER;
+ if (regno < reg_known_value_size)
+ return reg_known_value[regno];
+ }
+ return NULL;
}
+/* Set it. */
+
+static void
+set_reg_known_value (unsigned int regno, rtx val)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ regno -= FIRST_PSEUDO_REGISTER;
+ if (regno < reg_known_value_size)
+ reg_known_value[regno] = val;
+ }
+}
+
+/* Similarly for reg_known_equiv_p. */
+
+bool
+get_reg_known_equiv_p (unsigned int regno)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ regno -= FIRST_PSEUDO_REGISTER;
+ if (regno < reg_known_value_size)
+ return reg_known_equiv_p[regno];
+ }
+ return false;
+}
+
+static void
+set_reg_known_equiv_p (unsigned int regno, bool val)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ regno -= FIRST_PSEUDO_REGISTER;
+ if (regno < reg_known_value_size)
+ reg_known_equiv_p[regno] = val;
+ }
+}
+
+
/* Returns a canonical version of X, from the point of view alias
analysis. (For example, if X is a MEM whose address is a register,
and the register has a known value (say a SYMBOL_REF), then a MEM
canon_rtx (rtx x)
{
/* Recursively look for equivalences. */
- if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
- && REGNO (x) < reg_known_value_size)
- return reg_known_value[REGNO (x)] == x
- ? x : canon_rtx (reg_known_value[REGNO (x)]);
- else if (GET_CODE (x) == PLUS)
+ if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
+ {
+ rtx t = get_reg_known_value (REGNO (x));
+ if (t == x)
+ return x;
+ if (t)
+ return canon_rtx (t);
+ }
+
+ if (GET_CODE (x) == PLUS)
{
rtx x0 = canon_rtx (XEXP (x, 0));
rtx x1 = canon_rtx (XEXP (x, 1));
timevar_push (TV_ALIAS_ANALYSIS);
- reg_known_value_size = maxreg;
-
- reg_known_value
- = (rtx *) xcalloc ((maxreg - FIRST_PSEUDO_REGISTER), sizeof (rtx))
- - FIRST_PSEUDO_REGISTER;
- reg_known_equiv_p
- = (char*) xcalloc ((maxreg - FIRST_PSEUDO_REGISTER), sizeof (char))
- - FIRST_PSEUDO_REGISTER;
+ reg_known_value_size = maxreg - FIRST_PSEUDO_REGISTER;
+ reg_known_value = ggc_calloc (reg_known_value_size, sizeof (rtx));
+ reg_known_equiv_p = xcalloc (reg_known_value_size, sizeof (bool));
/* Overallocate reg_base_value to allow some growth during loop
optimization. Loop unrolling can create a large number of
{
unsigned int regno = REGNO (SET_DEST (set));
rtx src = SET_SRC (set);
+ rtx t;
if (REG_NOTES (insn) != 0
&& (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
|| (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
&& GET_CODE (XEXP (note, 0)) != EXPR_LIST
&& ! rtx_varies_p (XEXP (note, 0), 1)
- && ! reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
+ && ! reg_overlap_mentioned_p (SET_DEST (set),
+ XEXP (note, 0)))
{
- reg_known_value[regno] = XEXP (note, 0);
- reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
+ set_reg_known_value (regno, XEXP (note, 0));
+ set_reg_known_equiv_p (regno,
+ REG_NOTE_KIND (note) == REG_EQUIV);
}
else if (REG_N_SETS (regno) == 1
&& GET_CODE (src) == PLUS
&& GET_CODE (XEXP (src, 0)) == REG
- && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
- && (reg_known_value[REGNO (XEXP (src, 0))])
+ && (t = get_reg_known_value (REGNO (XEXP (src, 0))))
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
{
- rtx op0 = XEXP (src, 0);
- op0 = reg_known_value[REGNO (op0)];
- reg_known_value[regno]
- = plus_constant (op0, INTVAL (XEXP (src, 1)));
- reg_known_equiv_p[regno] = 0;
+ t = plus_constant (t, INTVAL (XEXP (src, 1)));
+ set_reg_known_value (regno, t);
+ set_reg_known_equiv_p (regno, 0);
}
else if (REG_N_SETS (regno) == 1
&& ! rtx_varies_p (src, 1))
{
- reg_known_value[regno] = src;
- reg_known_equiv_p[regno] = 0;
+ set_reg_known_value (regno, src);
+ set_reg_known_equiv_p (regno, 0);
}
}
}
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
/* Fill in the remaining entries. */
- for (i = FIRST_PSEUDO_REGISTER; i < (int)maxreg; i++)
+ for (i = 0; i < (int)reg_known_value_size; i++)
if (reg_known_value[i] == 0)
- reg_known_value[i] = regno_reg_rtx[i];
+ reg_known_value[i] = regno_reg_rtx[i + FIRST_PSEUDO_REGISTER];
/* Simplify the reg_base_value array so that no register refers to
another register, except to special registers indirectly through
end_alias_analysis (void)
{
old_reg_base_value = reg_base_value;
- free (reg_known_value + FIRST_PSEUDO_REGISTER);
+ ggc_free (reg_known_value);
reg_known_value = 0;
reg_known_value_size = 0;
- free (reg_known_equiv_p + FIRST_PSEUDO_REGISTER);
+ free (reg_known_equiv_p);
reg_known_equiv_p = 0;
if (alias_invariant)
{
#include "cselib.h"
#include "df.h"
-extern char *reg_known_equiv_p;
-extern rtx *reg_known_value;
static regset_head reg_pending_sets_head;
static regset_head reg_pending_clobbers_head;
{
rtx addr = XEXP (mem, 0);
- if (REG_P (addr)
- && REGNO (addr) >= FIRST_PSEUDO_REGISTER
- && reg_known_value[REGNO (addr)])
- addr = reg_known_value[REGNO (addr)];
+ if (REG_P (addr) && REGNO (addr) >= FIRST_PSEUDO_REGISTER)
+ {
+ rtx t = get_reg_known_value (REGNO (addr));
+ if (t)
+ addr = t;
+ }
return rtx_addr_can_trap_p (addr);
}
\f
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
the address in the REG_EQUIV note. */
- if (!reload_completed
- && reg_known_equiv_p[regno]
- && GET_CODE (reg_known_value[regno]) == MEM)
- sched_analyze_2 (deps, XEXP (reg_known_value[regno], 0), insn);
+ if (!reload_completed && get_reg_known_equiv_p (regno))
+ {
+ rtx t = get_reg_known_value (regno);
+ if (GET_CODE (t) == MEM)
+ sched_analyze_2 (deps, XEXP (t, 0), insn);
+ }
/* Don't let it cross a call after scheduling if it doesn't
already cross one. */
/* Pseudos that are REG_EQUIV to something may be replaced
by that during reloading. We need only add dependencies for
the address in the REG_EQUIV note. */
- if (!reload_completed
- && reg_known_equiv_p[regno]
- && GET_CODE (reg_known_value[regno]) == MEM)
- sched_analyze_2 (deps, XEXP (reg_known_value[regno], 0), insn);
+ if (!reload_completed && get_reg_known_equiv_p (regno))
+ {
+ rtx t = get_reg_known_value (regno);
+ if (GET_CODE (t) == MEM)
+ sched_analyze_2 (deps, XEXP (t, 0), insn);
+ }
/* If the register does not already cross any calls, then add this
insn to the sched_before_next_call list so that it will still