+2000-03-31 Mark Mitchell <mark@codesourcery.com>
+
+ * alias.c (canon_rtx): Make it global.
+ (rtx_equal_for_memref_p): CONST_INT equality is now pointer
+ equality.
+ * cse.c (struct table_elt): Add canon_exp.
+ (insert): Clear it.
+ (invalidate): Canonicalize expressions only once.
+ * rtl.h (canon_rtx): Declare.
+
2000-03-30 Mark Mitchell <mark@codesourcery.com>
* Makefile.in (emit-rtl.o): Depend on HASHTAB_H.
splay_tree children;
} *alias_set_entry;
-static rtx canon_rtx PARAMS ((rtx));
static int rtx_equal_for_memref_p PARAMS ((rtx, rtx));
static rtx find_symbolic_term PARAMS ((rtx));
static rtx get_addr PARAMS ((rtx));
reg_base_value[regno] = find_base_value (val);
}
-static rtx
+/* 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
+ whose address is the SYMBOL_REF is returned.) */
+
+rtx
canon_rtx (x)
rtx x;
{
if (GET_MODE (x) != GET_MODE (y))
return 0;
- /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */
-
- if (code == REG)
- return REGNO (x) == REGNO (y);
- if (code == LABEL_REF)
- return XEXP (x, 0) == XEXP (y, 0);
- if (code == SYMBOL_REF)
- return XSTR (x, 0) == XSTR (y, 0);
- if (code == CONST_INT)
- return INTVAL (x) == INTVAL (y);
- /* There's no need to compare the contents of CONST_DOUBLEs because
- they're unique. */
- if (code == CONST_DOUBLE)
- return 0;
- if (code == ADDRESSOF)
- return (REGNO (XEXP (x, 0)) == REGNO (XEXP (y, 0))
- && XINT (x, 1) == XINT (y, 1));
+ /* Some RTL can be compared without a recursive examination. */
+ switch (code)
+ {
+ case REG:
+ return REGNO (x) == REGNO (y);
+
+ case LABEL_REF:
+ return XEXP (x, 0) == XEXP (y, 0);
+
+ case SYMBOL_REF:
+ return XSTR (x, 0) == XSTR (y, 0);
+
+ case CONST_INT:
+ case CONST_DOUBLE:
+ /* There's no need to compare the contents of CONST_DOUBLEs or
+ CONST_INTs because pointer equality is a good enough
+ comparison for these nodes. */
+ return 0;
+
+ case ADDRESSOF:
+ return (REGNO (XEXP (x, 0)) == REGNO (XEXP (y, 0))
+ && XINT (x, 1) == XINT (y, 1));
+
+ default:
+ break;
+ }
/* For commutative operations, the RTX match if the operand match in any
order. Also handle the simple binary and unary cases without a loop. */
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;
}
elt->exp = x;
+ elt->canon_exp = NULL_RTX;
elt->cost = COST (x);
elt->next_same_value = 0;
elt->prev_same_value = 0;
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;
#endif
/* In alias.c */
+extern rtx canon_rtx PARAMS ((rtx));
extern int true_dependence PARAMS ((rtx, enum machine_mode, rtx,
int (*)(rtx)));
extern int read_dependence PARAMS ((rtx, rtx));