alias.c (alias_invariant, [...]): Mark GTY.
* 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. From-SVN: r79945
This commit is contained in:
parent
bbcb76f264
commit
bb1acb3e8f
|
@ -1,3 +1,21 @@
|
||||||
|
2004-03-24 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
|
* 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 <kazu@cs.umass.edu>
|
2004-03-24 Kazu Hirata <kazu@cs.umass.edu>
|
||||||
|
|
||||||
* dwarf2asm.c, loop.h, pretty-print.c, pretty-print.h,
|
* dwarf2asm.c, loop.h, pretty-print.c, pretty-print.h,
|
||||||
|
|
137
gcc/alias.c
137
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
|
Because this array contains only pseudo registers it has no effect
|
||||||
after reload. */
|
after reload. */
|
||||||
static rtx *alias_invariant;
|
static GTY((length("alias_invariant_size"))) rtx *alias_invariant;
|
||||||
unsigned int alias_invariant_size;
|
unsigned GTY(()) int alias_invariant_size;
|
||||||
|
|
||||||
/* Vector indexed by N giving the initial (unchanging) value known for
|
/* Vector indexed by N giving the initial (unchanging) value known for
|
||||||
pseudo-register N. This array is initialized in
|
pseudo-register N. This array is initialized in init_alias_analysis,
|
||||||
init_alias_analysis, and does not change until end_alias_analysis
|
and does not change until end_alias_analysis is called. */
|
||||||
is called. */
|
static GTY((length("reg_known_value_size"))) rtx *reg_known_value;
|
||||||
rtx *reg_known_value;
|
|
||||||
|
|
||||||
/* Indicates number of valid entries in 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
|
/* 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 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
|
REG_EQUIV notes. One could argue that the REG_EQUIV notes are
|
||||||
wrong, but solving the problem in the scheduler will likely give
|
wrong, but solving the problem in the scheduler will likely give
|
||||||
better code, so we do it here. */
|
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
|
/* True when scanning insns from the start of the rtl to the
|
||||||
NOTE_INSN_FUNCTION_BEG note. */
|
NOTE_INSN_FUNCTION_BEG note. */
|
||||||
|
@ -1075,10 +1074,70 @@ clear_reg_alias_info (rtx reg)
|
||||||
{
|
{
|
||||||
unsigned int regno = REGNO (reg);
|
unsigned int regno = REGNO (reg);
|
||||||
|
|
||||||
if (regno < reg_known_value_size && regno >= FIRST_PSEUDO_REGISTER)
|
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||||
reg_known_value[regno] = reg;
|
{
|
||||||
|
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
|
/* 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,
|
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
|
and the register has a known value (say a SYMBOL_REF), then a MEM
|
||||||
|
@ -1088,11 +1147,16 @@ rtx
|
||||||
canon_rtx (rtx x)
|
canon_rtx (rtx x)
|
||||||
{
|
{
|
||||||
/* Recursively look for equivalences. */
|
/* Recursively look for equivalences. */
|
||||||
if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
|
if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
|
||||||
&& REGNO (x) < reg_known_value_size)
|
{
|
||||||
return reg_known_value[REGNO (x)] == x
|
rtx t = get_reg_known_value (REGNO (x));
|
||||||
? x : canon_rtx (reg_known_value[REGNO (x)]);
|
if (t == x)
|
||||||
else if (GET_CODE (x) == PLUS)
|
return x;
|
||||||
|
if (t)
|
||||||
|
return canon_rtx (t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_CODE (x) == PLUS)
|
||||||
{
|
{
|
||||||
rtx x0 = canon_rtx (XEXP (x, 0));
|
rtx x0 = canon_rtx (XEXP (x, 0));
|
||||||
rtx x1 = canon_rtx (XEXP (x, 1));
|
rtx x1 = canon_rtx (XEXP (x, 1));
|
||||||
|
@ -2736,14 +2800,9 @@ init_alias_analysis (void)
|
||||||
|
|
||||||
timevar_push (TV_ALIAS_ANALYSIS);
|
timevar_push (TV_ALIAS_ANALYSIS);
|
||||||
|
|
||||||
reg_known_value_size = maxreg;
|
reg_known_value_size = maxreg - FIRST_PSEUDO_REGISTER;
|
||||||
|
reg_known_value = ggc_calloc (reg_known_value_size, sizeof (rtx));
|
||||||
reg_known_value
|
reg_known_equiv_p = xcalloc (reg_known_value_size, sizeof (bool));
|
||||||
= (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
|
/* Overallocate reg_base_value to allow some growth during loop
|
||||||
optimization. Loop unrolling can create a large number of
|
optimization. Loop unrolling can create a large number of
|
||||||
|
@ -2861,6 +2920,7 @@ init_alias_analysis (void)
|
||||||
{
|
{
|
||||||
unsigned int regno = REGNO (SET_DEST (set));
|
unsigned int regno = REGNO (SET_DEST (set));
|
||||||
rtx src = SET_SRC (set);
|
rtx src = SET_SRC (set);
|
||||||
|
rtx t;
|
||||||
|
|
||||||
if (REG_NOTES (insn) != 0
|
if (REG_NOTES (insn) != 0
|
||||||
&& (((note = find_reg_note (insn, REG_EQUAL, 0)) != 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)
|
|| (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
|
||||||
&& GET_CODE (XEXP (note, 0)) != EXPR_LIST
|
&& GET_CODE (XEXP (note, 0)) != EXPR_LIST
|
||||||
&& ! rtx_varies_p (XEXP (note, 0), 1)
|
&& ! 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);
|
set_reg_known_value (regno, XEXP (note, 0));
|
||||||
reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
|
set_reg_known_equiv_p (regno,
|
||||||
|
REG_NOTE_KIND (note) == REG_EQUIV);
|
||||||
}
|
}
|
||||||
else if (REG_N_SETS (regno) == 1
|
else if (REG_N_SETS (regno) == 1
|
||||||
&& GET_CODE (src) == PLUS
|
&& GET_CODE (src) == PLUS
|
||||||
&& GET_CODE (XEXP (src, 0)) == REG
|
&& GET_CODE (XEXP (src, 0)) == REG
|
||||||
&& REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
|
&& (t = get_reg_known_value (REGNO (XEXP (src, 0))))
|
||||||
&& (reg_known_value[REGNO (XEXP (src, 0))])
|
|
||||||
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
|
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
|
||||||
{
|
{
|
||||||
rtx op0 = XEXP (src, 0);
|
t = plus_constant (t, INTVAL (XEXP (src, 1)));
|
||||||
op0 = reg_known_value[REGNO (op0)];
|
set_reg_known_value (regno, t);
|
||||||
reg_known_value[regno]
|
set_reg_known_equiv_p (regno, 0);
|
||||||
= plus_constant (op0, INTVAL (XEXP (src, 1)));
|
|
||||||
reg_known_equiv_p[regno] = 0;
|
|
||||||
}
|
}
|
||||||
else if (REG_N_SETS (regno) == 1
|
else if (REG_N_SETS (regno) == 1
|
||||||
&& ! rtx_varies_p (src, 1))
|
&& ! rtx_varies_p (src, 1))
|
||||||
{
|
{
|
||||||
reg_known_value[regno] = src;
|
set_reg_known_value (regno, src);
|
||||||
reg_known_equiv_p[regno] = 0;
|
set_reg_known_equiv_p (regno, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2917,9 +2976,9 @@ init_alias_analysis (void)
|
||||||
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
|
while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
|
||||||
|
|
||||||
/* Fill in the remaining entries. */
|
/* 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)
|
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
|
/* Simplify the reg_base_value array so that no register refers to
|
||||||
another register, except to special registers indirectly through
|
another register, except to special registers indirectly through
|
||||||
|
@ -2965,10 +3024,10 @@ void
|
||||||
end_alias_analysis (void)
|
end_alias_analysis (void)
|
||||||
{
|
{
|
||||||
old_reg_base_value = reg_base_value;
|
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 = 0;
|
||||||
reg_known_value_size = 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_known_equiv_p = 0;
|
||||||
if (alias_invariant)
|
if (alias_invariant)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2423,6 +2423,8 @@ extern rtx addr_side_effect_eval (rtx, int, int);
|
||||||
extern bool memory_modified_in_insn_p (rtx, rtx);
|
extern bool memory_modified_in_insn_p (rtx, rtx);
|
||||||
extern rtx find_base_term (rtx);
|
extern rtx find_base_term (rtx);
|
||||||
extern rtx gen_hard_reg_clobber (enum machine_mode, unsigned int);
|
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 */
|
/* In sibcall.c */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
|
@ -44,8 +44,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
#include "cselib.h"
|
#include "cselib.h"
|
||||||
#include "df.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_sets_head;
|
||||||
static regset_head reg_pending_clobbers_head;
|
static regset_head reg_pending_clobbers_head;
|
||||||
|
@ -113,10 +111,12 @@ deps_may_trap_p (rtx mem)
|
||||||
{
|
{
|
||||||
rtx addr = XEXP (mem, 0);
|
rtx addr = XEXP (mem, 0);
|
||||||
|
|
||||||
if (REG_P (addr)
|
if (REG_P (addr) && REGNO (addr) >= FIRST_PSEUDO_REGISTER)
|
||||||
&& REGNO (addr) >= FIRST_PSEUDO_REGISTER
|
{
|
||||||
&& reg_known_value[REGNO (addr)])
|
rtx t = get_reg_known_value (REGNO (addr));
|
||||||
addr = reg_known_value[REGNO (addr)];
|
if (t)
|
||||||
|
addr = t;
|
||||||
|
}
|
||||||
return rtx_addr_can_trap_p (addr);
|
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
|
/* Pseudos that are REG_EQUIV to something may be replaced
|
||||||
by that during reloading. We need only add dependencies for
|
by that during reloading. We need only add dependencies for
|
||||||
the address in the REG_EQUIV note. */
|
the address in the REG_EQUIV note. */
|
||||||
if (!reload_completed
|
if (!reload_completed && get_reg_known_equiv_p (regno))
|
||||||
&& reg_known_equiv_p[regno]
|
{
|
||||||
&& GET_CODE (reg_known_value[regno]) == MEM)
|
rtx t = get_reg_known_value (regno);
|
||||||
sched_analyze_2 (deps, XEXP (reg_known_value[regno], 0), insn);
|
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
|
/* Don't let it cross a call after scheduling if it doesn't
|
||||||
already cross one. */
|
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
|
/* Pseudos that are REG_EQUIV to something may be replaced
|
||||||
by that during reloading. We need only add dependencies for
|
by that during reloading. We need only add dependencies for
|
||||||
the address in the REG_EQUIV note. */
|
the address in the REG_EQUIV note. */
|
||||||
if (!reload_completed
|
if (!reload_completed && get_reg_known_equiv_p (regno))
|
||||||
&& reg_known_equiv_p[regno]
|
{
|
||||||
&& GET_CODE (reg_known_value[regno]) == MEM)
|
rtx t = get_reg_known_value (regno);
|
||||||
sched_analyze_2 (deps, XEXP (reg_known_value[regno], 0), insn);
|
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
|
/* 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
|
insn to the sched_before_next_call list so that it will still
|
||||||
|
|
Loading…
Reference in New Issue