rtx const_insn;
rtx comparison_const;
int comparison_qty;
- int first_reg, last_reg;
+ unsigned int first_reg, last_reg;
enum machine_mode mode;
enum rtx_code comparison_code;
};
struct cse_reg_info *next;
/* Search key */
- int regno;
+ unsigned int regno;
/* The quantity number of the register's current contents. */
int reg_qty;
/* The last lookup we did into the cse_reg_info_tree. This allows us
to cache repeated lookups. */
-static int cached_regno;
+static unsigned int cached_regno;
static struct cse_reg_info *cached_cse_reg_info;
/* A HARD_REG_SET containing all the hard registers for which there is
each recording one expression's information.
That expression is in the `exp' field.
+ The canon_exp field contains a canonical (from the point of view of
+ alias analysis) version of the `exp' field.
+
Those elements with the same hash code are chained in both directions
through the `next_same_hash' and `prev_same_hash' fields.
struct table_elt
{
rtx exp;
+ rtx canon_exp;
struct table_elt *next_same_hash;
struct table_elt *prev_same_hash;
struct table_elt *next_same_value;
/* Determine if the quantity number for register X represents a valid index
into the qty_table. */
-#define REGNO_QTY_VALID_P(N) (REG_QTY (N) != (N))
+#define REGNO_QTY_VALID_P(N) (REG_QTY (N) != (int) (N))
#ifdef ADDRESS_COST
/* The ADDRESS_COST macro does not deal with ADDRESSOF nodes. But,
static int notreg_cost PARAMS ((rtx));
static void new_basic_block PARAMS ((void));
-static void make_new_qty PARAMS ((int, enum machine_mode));
-static void make_regs_eqv PARAMS ((int, int));
-static void delete_reg_equiv PARAMS ((int));
+static void make_new_qty PARAMS ((unsigned int, enum machine_mode));
+static void make_regs_eqv PARAMS ((unsigned int, unsigned int));
+static void delete_reg_equiv PARAMS ((unsigned int));
static int mention_regs PARAMS ((rtx));
static int insert_regs PARAMS ((rtx, struct table_elt *, int));
static void remove_from_table PARAMS ((struct table_elt *, unsigned));
struct table_elt *));
static void invalidate PARAMS ((rtx, enum machine_mode));
static int cse_rtx_varies_p PARAMS ((rtx));
-static void remove_invalid_refs PARAMS ((int));
-static void remove_invalid_subreg_refs PARAMS ((int, int, enum machine_mode));
+static void remove_invalid_refs PARAMS ((unsigned int));
+static void remove_invalid_subreg_refs PARAMS ((unsigned int, unsigned int,
+ enum machine_mode));
static void rehash_using_reg PARAMS ((rtx));
static void invalidate_memory PARAMS ((void));
static void invalidate_for_call PARAMS ((void));
static rtx cse_basic_block PARAMS ((rtx, rtx, struct branch_path *, int));
static void count_reg_usage PARAMS ((rtx, int *, rtx, int));
extern void dump_class PARAMS ((struct table_elt*));
-static struct cse_reg_info* get_cse_reg_info PARAMS ((int));
+static struct cse_reg_info * get_cse_reg_info PARAMS ((unsigned int));
static void flush_hash_table PARAMS ((void));
\f
\f
static struct cse_reg_info *
get_cse_reg_info (regno)
- int regno;
+ unsigned int regno;
{
struct cse_reg_info **hash_head = ®_hash[REGHASH_FN (regno)];
struct cse_reg_info *p;
static void
make_new_qty (reg, mode)
- register int reg;
- register enum machine_mode mode;
+ unsigned int reg;
+ enum machine_mode mode;
{
register int q;
register struct qty_table_elem *ent;
static void
make_regs_eqv (new, old)
- register int new, old;
+ unsigned int new, old;
{
- register int lastr, firstr;
- register int q = REG_QTY (old);
- register struct qty_table_elem *ent;
+ unsigned int lastr, firstr;
+ int q = REG_QTY (old);
+ struct qty_table_elem *ent;
ent = &qty_table[q];
static void
delete_reg_equiv (reg)
- register int reg;
+ unsigned int reg;
{
register struct qty_table_elem *ent;
register int q = REG_QTY (reg);
register int p, n;
/* If invalid, do nothing. */
- if (q == reg)
+ if (q == (int) reg)
return;
ent = &qty_table[q];
code = GET_CODE (x);
if (code == REG)
{
- register int regno = REGNO (x);
- register int endregno
+ unsigned int regno = REGNO (x);
+ unsigned int endregno
= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
: HARD_REGNO_NREGS (regno, GET_MODE (x)));
- int i;
+ unsigned int i;
for (i = regno; i < endregno; i++)
{
if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
{
- int i = REGNO (SUBREG_REG (x));
+ unsigned int i = REGNO (SUBREG_REG (x));
if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
{
{
if (GET_CODE (x) == REG)
{
- register int regno = REGNO (x);
- register int qty_valid;
+ unsigned int regno = REGNO (x);
+ int qty_valid;
/* If REGNO is in the equivalence table already but is of the
wrong mode for that equivalence, don't do anything here. */
else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
&& ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x))))
{
- int regno = REGNO (SUBREG_REG (x));
+ unsigned int regno = REGNO (SUBREG_REG (x));
insert_regs (SUBREG_REG (x), NULL_PTR, 0);
/* Mention_regs checks if REG_TICK is exactly one larger than
if (elt->related_value != 0 && elt->related_value != elt)
{
register struct table_elt *p = elt->related_value;
+
while (p->related_value != elt)
p = p->related_value;
p->related_value = elt->related_value;
if (GET_CODE (x) == REG)
{
- int regno = REGNO (x);
+ unsigned int regno = REGNO (x);
+
/* Don't check the machine mode when comparing registers;
invalidating (REG:SI 0) also invalidates (REG:DF 0). */
for (p = table[hash]; p; p = p->next_same_hash)
rtx x;
enum rtx_code code;
{
- register struct table_elt *p = lookup (x, safe_hash (x, VOIDmode) & HASH_MASK,
- GET_MODE (x));
+ register struct table_elt *p
+ = lookup (x, safe_hash (x, VOIDmode) & HASH_MASK, GET_MODE (x));
+
/* If we are looking for a CONST_INT, the mode doesn't really matter, as
long as we are narrowing. So if we looked in vain for a mode narrower
than word_mode before, look for word_mode now. */
return 0;
for (p = p->first_same_value; p; p = p->next_same_value)
- {
- if (GET_CODE (p->exp) == code
- /* Make sure this is a valid entry in the table. */
- && exp_equiv_p (p->exp, p->exp, 1, 0))
- return p->exp;
- }
+ if (GET_CODE (p->exp) == code
+ /* Make sure this is a valid entry in the table. */
+ && exp_equiv_p (p->exp, p->exp, 1, 0))
+ return p->exp;
return 0;
}
/* If X is a hard register, show it is being put in the table. */
if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
{
- int regno = REGNO (x);
- int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
- int i;
+ unsigned int regno = REGNO (x);
+ unsigned int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ unsigned int i;
for (i = regno; i < endregno; i++)
- SET_HARD_REG_BIT (hard_regs_in_table, i);
+ SET_HARD_REG_BIT (hard_regs_in_table, i);
}
/* If X is a label, show we recorded it. */
elt = free_element_chain;
if (elt)
- {
- free_element_chain = elt->next_same_hash;
- }
+ free_element_chain = elt->next_same_hash;
else
{
n_elements_made++;
}
elt->exp = x;
+ elt->canon_exp = NULL_RTX;
elt->cost = COST (x);
elt->next_same_value = 0;
elt->prev_same_value = 0;
/* Insert not at head of the class. */
/* Put it after the last element cheaper than X. */
register struct table_elt *p, *next;
+
for (p = classp; (next = p->next_same_value) && CHEAPER (next, elt);
p = next);
+
/* Put it after P and before NEXT. */
elt->next_same_value = next;
if (next)
next->prev_same_value = elt;
+
elt->prev_same_value = p;
p->next_same_value = elt;
elt->first_same_value = classp;
int x_q = REG_QTY (REGNO (x));
struct qty_table_elem *x_ent = &qty_table[x_q];
- x_ent->const_rtx = gen_lowpart_if_possible (GET_MODE (x), p->exp);
+ x_ent->const_rtx
+ = gen_lowpart_if_possible (GET_MODE (x), p->exp);
x_ent->const_insn = this_insn;
break;
}
for (elt = class2; elt; elt = next)
{
- unsigned hash;
+ unsigned int hash;
rtx exp = elt->exp;
enum machine_mode mode = elt->mode;
through the qty number mechanism. Just change the qty number of
the register, mark it as invalid for expressions that refer to it,
and remove it itself. */
- register int regno = REGNO (x);
- register unsigned hash = HASH (x, GET_MODE (x));
+ unsigned int regno = REGNO (x);
+ unsigned int hash = HASH (x, GET_MODE (x));
/* Remove REGNO from any quantity list it might be on and indicate
that its value might have changed. If it is a pseudo, remove its
{
HOST_WIDE_INT in_table
= TEST_HARD_REG_BIT (hard_regs_in_table, regno);
- int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
- int tregno, tendregno;
+ unsigned int endregno
+ = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+ unsigned int tregno, tendregno, rn;
register struct table_elt *p, *next;
CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
- for (i = regno + 1; i < endregno; i++)
+ for (rn = regno + 1; rn < endregno; rn++)
{
- in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, i);
- CLEAR_HARD_REG_BIT (hard_regs_in_table, i);
- delete_reg_equiv (i);
- REG_TICK (i)++;
+ in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, rn);
+ CLEAR_HARD_REG_BIT (hard_regs_in_table, rn);
+ delete_reg_equiv (rn);
+ REG_TICK (rn)++;
}
if (in_table)
return;
case MEM:
+ /* Calculate the canonical version of X here so that
+ true_dependence doesn't generate new RTL for X on each call. */
+ x = canon_rtx (x);
+
/* Remove all hash table elements that refer to overlapping pieces of
memory. */
if (full_mode == VOIDmode)
for (p = table[i]; p; p = next)
{
next = p->next_same_hash;
- if (p->in_memory
- && (GET_CODE (p->exp) != MEM
- || true_dependence (x, full_mode, p->exp,
- cse_rtx_varies_p)))
- remove_from_table (p, i);
+ if (p->in_memory)
+ {
+ if (GET_CODE (p->exp) != MEM)
+ remove_from_table (p, i);
+ else
+ {
+ /* Just canonicalize the expression once;
+ otherwise each time we call invalidate
+ true_dependence will canonicalize the
+ expression again. */
+ if (!p->canon_exp)
+ p->canon_exp = canon_rtx (p->exp);
+ if (true_dependence (x, full_mode, p->canon_exp,
+ cse_rtx_varies_p))
+ remove_from_table (p, i);
+ }
+ }
}
}
return;
static void
remove_invalid_refs (regno)
- int regno;
+ unsigned int regno;
{
- register int i;
- register struct table_elt *p, *next;
+ unsigned int i;
+ struct table_elt *p, *next;
for (i = 0; i < HASH_SIZE; i++)
for (p = table[i]; p; p = next)
/* Likewise for a subreg with subreg_reg WORD and mode MODE. */
static void
remove_invalid_subreg_refs (regno, word, mode)
- int regno;
- int word;
+ unsigned int regno;
+ unsigned int word;
enum machine_mode mode;
{
- register int i;
- register struct table_elt *p, *next;
- int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
+ unsigned int i;
+ struct table_elt *p, *next;
+ unsigned int end = word + (GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD;
for (i = 0; i < HASH_SIZE; i++)
for (p = table[i]; p; p = next)
static void
invalidate_for_call ()
{
- int regno, endregno;
- int i;
+ unsigned int regno, endregno;
+ unsigned int i;
unsigned hash;
struct table_elt *p, *next;
int in_table = 0;
{
case REG:
{
- register int regno = REGNO (x);
+ unsigned int regno = REGNO (x);
/* On some machines, we can't record any non-fixed hard register,
because extending its life will cause reload problems. We
do_not_record = 1;
return 0;
}
+
hash += ((unsigned) REG << 7) + (unsigned) REG_QTY (regno);
return hash;
}
{
case PC:
case CC0:
- return x == y;
-
case CONST_INT:
- return INTVAL (x) == INTVAL (y);
+ return x == y;
case LABEL_REF:
return XEXP (x, 0) == XEXP (y, 0);
case REG:
{
- int regno = REGNO (y);
- int endregno
+ unsigned int regno = REGNO (y);
+ unsigned int endregno
= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
: HARD_REGNO_NREGS (regno, GET_MODE (y)));
- int i;
+ unsigned int i;
/* If the quantities are not the same, the expressions are not
equivalent. If there are and we are not to validate, they
This code is similar to the REG case in mention_regs,
but it knows that reg_tick has been incremented, and
it leaves reg_in_table as -1 . */
- register int regno = REGNO (x);
- register int endregno
+ unsigned int regno = REGNO (x);
+ unsigned int endregno
= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
: HARD_REGNO_NREGS (regno, GET_MODE (x)));
- int i;
+ unsigned int i;
for (i = regno; i < endregno; i++)
{
/* If we have processed 1,000 insns, flush the hash table to
avoid extreme quadratic behavior. We must not include NOTEs
- in the count since there may be more or them when generating
+ in the count since there may be more of them when generating
debugging information. If we clear the table at different
times, code generated with -g -O might be different than code
generated with -O but not -g.
&& rtx_equal_p (SET_DEST (PATTERN (insn)),
SET_SRC (PATTERN (insn))))
;
+ else if (GET_CODE (SET_DEST (PATTERN (insn))) == STRICT_LOW_PART
+ && rtx_equal_p (XEXP (SET_DEST (PATTERN (insn)), 0),
+ SET_SRC (PATTERN (insn))))
+ ;
#ifdef HAVE_cc0
else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0