diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ad09c1471d6..f82691862ee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2004-03-24 Richard Henderson + + * alias.c (alias_invariant, alias_invariant_size): Mark GTY. + (reg_known_value, reg_known_value_size): Likewise; make static. + (reg_known_equiv_p): Make static. + (clear_reg_alias_info): Update for new indexing. + (get_reg_known_value, set_reg_known_value): New. + (get_reg_known_equiv_p, set_reg_known_equiv_p): New. + (canon_rtx): Use them. + (init_alias_analysis): Likewise. Allocate reg_known_value with gc. + Don't play queer offsetting games with reg_known_value and + reg_known_equiv_p. + (end_alias_analysis): Free reg_known_value with gc. + * rtl.h (get_reg_known_value, get_reg_known_equiv_p): Declare. + * sched-deps.c (reg_known_equiv_p, reg_known_value): Remove. + (deps_may_trap_p, sched_analyze_1, sched_analyze_2): Use the new + functions instead. + 2004-03-24 Kazu Hirata * dwarf2asm.c, loop.h, pretty-print.c, pretty-print.h, diff --git a/gcc/alias.c b/gcc/alias.c index 22e1e70ade4..f2bf80661f6 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -181,17 +181,16 @@ static GTY (()) rtx static_reg_base_value[FIRST_PSEUDO_REGISTER]; 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 @@ -205,7 +204,7 @@ static unsigned int reg_known_value_size; 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. */ @@ -1075,10 +1074,70 @@ clear_reg_alias_info (rtx reg) { 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 @@ -1088,11 +1147,16 @@ rtx 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)); @@ -2736,14 +2800,9 @@ init_alias_analysis (void) 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 @@ -2861,6 +2920,7 @@ init_alias_analysis (void) { 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 @@ -2868,29 +2928,28 @@ init_alias_analysis (void) || (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); } } } @@ -2917,9 +2976,9 @@ init_alias_analysis (void) 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 @@ -2965,10 +3024,10 @@ void 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) { diff --git a/gcc/rtl.h b/gcc/rtl.h index 26466a954e4..d17325c2b9d 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2423,6 +2423,8 @@ extern rtx addr_side_effect_eval (rtx, int, int); extern bool memory_modified_in_insn_p (rtx, rtx); extern rtx find_base_term (rtx); extern rtx gen_hard_reg_clobber (enum machine_mode, unsigned int); +extern rtx get_reg_known_value (unsigned int); +extern bool get_reg_known_equiv_p (unsigned int); /* In sibcall.c */ typedef enum { diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index ad96281b093..7802bf23e61 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -44,8 +44,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #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; @@ -113,10 +111,12 @@ deps_may_trap_p (rtx mem) { 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); } @@ -523,10 +523,12 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn) /* 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. */ @@ -659,10 +661,12 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn) /* 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