From: Richard Henderson Date: Sat, 24 Apr 2004 19:40:46 +0000 (-0700) Subject: re PR bootstrap/14671 (caller-save.c:491: internal compiler error: Segmentation fault) X-Git-Tag: releases/gcc-3.3.4~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc644c0bcbd3ed1b2dd6b442781b7a69e882443d;p=thirdparty%2Fgcc.git re PR bootstrap/14671 (caller-save.c:491: internal compiler error: Segmentation fault) PR bootstrap/14671 * 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): Don't free reg_known_value. * 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. From-SVN: r81145 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fad2d5719f02..f8e5f32154d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2004-04-24 Richard Henderson + + PR bootstrap/14671 + * 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): Don't free reg_known_value. + * 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-04-21 John David Anglin * pa64-hpux.h (LIB_SPEC): Fix library specification used with GNU ld. diff --git a/gcc/alias.c b/gcc/alias.c index dd8426964026..3213f33ed906 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -173,16 +173,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; +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 @@ -196,7 +196,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. */ @@ -1029,7 +1029,7 @@ record_base_value (regno, val, 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 (GET_CODE (val) == REG) @@ -1054,10 +1054,70 @@ clear_reg_alias_info (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 @@ -1068,11 +1128,16 @@ canon_rtx (x) 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)); @@ -2698,14 +2763,9 @@ init_alias_analysis () unsigned int ui; rtx insn; - 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 @@ -2722,6 +2782,7 @@ init_alias_analysis () alias_invariant = (rtx *)xrealloc (alias_invariant, reg_base_value_size * sizeof (rtx)); memset ((char *)alias_invariant, 0, reg_base_value_size * sizeof (rtx)); + alias_invariant_size = reg_base_value_size; } /* The basic idea is that each pass through this loop will use the @@ -2810,6 +2871,7 @@ init_alias_analysis () { 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 @@ -2817,29 +2879,28 @@ init_alias_analysis () || (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); } } } @@ -2863,9 +2924,9 @@ init_alias_analysis () while (changed && ++pass < MAX_ALIAS_LOOP_PASSES); /* Fill in the remaining entries. */ - for (i = FIRST_PSEUDO_REGISTER; i < 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 @@ -2908,10 +2969,9 @@ init_alias_analysis () void end_alias_analysis () { - free (reg_known_value + FIRST_PSEUDO_REGISTER); 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; reg_base_value = 0; reg_base_value_size = 0; @@ -2919,6 +2979,7 @@ end_alias_analysis () { free (alias_invariant); alias_invariant = 0; + alias_invariant_size = 0; } } diff --git a/gcc/rtl.h b/gcc/rtl.h index 2d66fd79ad20..715febfddd92 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2258,6 +2258,8 @@ extern void init_alias_once 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)); +extern rtx get_reg_known_value PARAMS ((unsigned int)); +extern bool get_reg_known_equiv_p PARAMS ((unsigned int)); /* In sibcall.c */ typedef enum { diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index e261608cdfc5..1befd3deb4a7 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -41,8 +41,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "params.h" #include "cselib.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; @@ -101,10 +99,12 @@ deps_may_trap_p (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); } @@ -628,10 +628,12 @@ sched_analyze_1 (deps, x, 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. */ @@ -763,10 +765,12 @@ sched_analyze_2 (deps, x, 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