This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix alpha gc bootstrap problem
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 24 Mar 2004 17:02:13 -0800
- Subject: fix alpha gc bootstrap problem
No idea why this is happening now, and apparently only to me, but
the fact is that data gets put into reg_known_value and a call to
ggc_collect happens before end_alias_analysis. The call to collect
happens during CSE, and is protected by a ggc_push_context, but it
still doesn't seem terribly safe.
Bootstrapped on alphaev6-linux.
r~
* 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.
Index: alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.222
diff -c -p -d -r1.222 alias.c
*** alias.c 23 Mar 2004 20:43:38 -0000 1.222
--- alias.c 25 Mar 2004 00:52:39 -0000
*************** static GTY (()) rtx static_reg_base_valu
*** 181,197 ****
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
! init_alias_analysis, and does not change until end_alias_analysis
! is called. */
! rtx *reg_known_value;
/* Indicates number of valid entries in reg_known_value. */
! static 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
--- 181,196 ----
Because this array contains only pseudo registers it has no effect
after reload. */
! 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. */
! static GTY((length("reg_known_value_size"))) rtx *reg_known_value;
/* Indicates number of valid entries in reg_known_value. */
! 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
*************** static unsigned int reg_known_value_size
*** 205,211 ****
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;
/* True when scanning insns from the start of the rtl to the
NOTE_INSN_FUNCTION_BEG note. */
--- 204,210 ----
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. */
! static bool *reg_known_equiv_p;
/* True when scanning insns from the start of the rtl to the
NOTE_INSN_FUNCTION_BEG note. */
*************** clear_reg_alias_info (rtx reg)
*** 1075,1084 ****
{
unsigned int regno = REGNO (reg);
! if (regno < reg_known_value_size && regno >= FIRST_PSEUDO_REGISTER)
! reg_known_value[regno] = reg;
}
/* 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
--- 1074,1143 ----
{
unsigned int regno = 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
*************** rtx
*** 1088,1098 ****
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)
{
rtx x0 = canon_rtx (XEXP (x, 0));
rtx x1 = canon_rtx (XEXP (x, 1));
--- 1147,1162 ----
canon_rtx (rtx x)
{
/* Recursively look for equivalences. */
! 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));
*************** init_alias_analysis (void)
*** 2736,2749 ****
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;
/* Overallocate reg_base_value to allow some growth during loop
optimization. Loop unrolling can create a large number of
--- 2800,2808 ----
timevar_push (TV_ALIAS_ANALYSIS);
! 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
*************** init_alias_analysis (void)
*** 2861,2866 ****
--- 2920,2926 ----
{
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
*************** init_alias_analysis (void)
*** 2868,2896 ****
|| (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_known_value[regno] = XEXP (note, 0);
! 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))])
&& 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;
}
else if (REG_N_SETS (regno) == 1
&& ! rtx_varies_p (src, 1))
{
! reg_known_value[regno] = src;
! reg_known_equiv_p[regno] = 0;
}
}
}
--- 2928,2955 ----
|| (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)))
{
! 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
! && (t = get_reg_known_value (REGNO (XEXP (src, 0))))
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
{
! 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))
{
! set_reg_known_value (regno, src);
! set_reg_known_equiv_p (regno, 0);
}
}
}
*************** init_alias_analysis (void)
*** 2917,2925 ****
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
/* Fill in the remaining entries. */
! for (i = FIRST_PSEUDO_REGISTER; i < (int)maxreg; i++)
if (reg_known_value[i] == 0)
! reg_known_value[i] = regno_reg_rtx[i];
/* Simplify the reg_base_value array so that no register refers to
another register, except to special registers indirectly through
--- 2976,2984 ----
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
/* Fill in the remaining entries. */
! for (i = 0; i < (int)reg_known_value_size; i++)
if (reg_known_value[i] == 0)
! 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
*************** void
*** 2965,2974 ****
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;
if (alias_invariant)
{
--- 3024,3033 ----
end_alias_analysis (void)
{
old_reg_base_value = reg_base_value;
! ggc_free (reg_known_value);
reg_known_value = 0;
reg_known_value_size = 0;
! free (reg_known_equiv_p);
reg_known_equiv_p = 0;
if (alias_invariant)
{
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.466
diff -c -p -d -r1.466 rtl.h
*** rtl.h 20 Mar 2004 23:08:57 -0000 1.466
--- rtl.h 25 Mar 2004 00:52:40 -0000
*************** extern rtx addr_side_effect_eval (rtx, i
*** 2423,2428 ****
--- 2423,2430 ----
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 {
Index: sched-deps.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/sched-deps.c,v
retrieving revision 1.71
diff -c -p -d -r1.71 sched-deps.c
*** sched-deps.c 4 Mar 2004 19:03:02 -0000 1.71
--- sched-deps.c 25 Mar 2004 00:52:40 -0000
*************** Software Foundation, 59 Temple Place - S
*** 44,51 ****
#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;
--- 44,49 ----
*************** deps_may_trap_p (rtx mem)
*** 113,122 ****
{
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)];
return rtx_addr_can_trap_p (addr);
}
--- 111,122 ----
{
rtx addr = XEXP (mem, 0);
! 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);
}
*************** sched_analyze_1 (struct deps *deps, rtx
*** 523,532 ****
/* 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);
/* Don't let it cross a call after scheduling if it doesn't
already cross one. */
--- 523,534 ----
/* 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 && 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. */
*************** sched_analyze_2 (struct deps *deps, rtx
*** 659,668 ****
/* 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 the register does not already cross any calls, then add this
insn to the sched_before_next_call list so that it will still
--- 661,672 ----
/* 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 && 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