@@ -2934,7 +2934,6 @@ true_dependence_1 (const_rtx mem, machine_mode mem_mode, rtx mem_addr,
const_rtx x, rtx x_addr, bool mem_canonicalized)
{
rtx true_mem_addr;
- rtx base;
int ret;
gcc_checking_assert (mem_canonicalized ? (mem_addr != NULL_RTX)
@@ -2981,13 +2980,17 @@ true_dependence_1 (const_rtx mem, machine_mode mem_mode, rtx mem_addr,
if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x))
return true;
- base = find_base_term (x_addr);
+ rtx base = MEM_BASE (x);
+ if (!base)
+ base = find_base_term (x_addr);
if (base && (GET_CODE (base) == LABEL_REF
|| (GET_CODE (base) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (base))))
return false;
- rtx mem_base = find_base_term (true_mem_addr);
+ rtx mem_base = MEM_BASE (mem);
+ if (!mem_base)
+ mem_base = find_base_term (true_mem_addr);
if (! base_alias_check (x_addr, base, true_mem_addr, mem_base,
GET_MODE (x), mem_mode))
return false;
@@ -3045,7 +3048,6 @@ write_dependence_p (const_rtx mem,
{
rtx mem_addr;
rtx true_mem_addr, true_x_addr;
- rtx base;
int ret;
gcc_checking_assert (x_canonicalized
@@ -3088,7 +3090,9 @@ write_dependence_p (const_rtx mem,
if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x))
return true;
- base = find_base_term (true_mem_addr);
+ rtx base = MEM_BASE (mem);
+ if (!base)
+ base = find_base_term (true_mem_addr);
if (! writep
&& base
&& (GET_CODE (base) == LABEL_REF
@@ -3096,7 +3100,9 @@ write_dependence_p (const_rtx mem,
&& CONSTANT_POOL_ADDRESS_P (base))))
return false;
- rtx x_base = find_base_term (true_x_addr);
+ rtx x_base = MEM_BASE (x);
+ if (!x_base)
+ x_base = find_base_term (true_x_addr);
if (! base_alias_check (true_x_addr, x_base, true_mem_addr, base,
GET_MODE (x), GET_MODE (mem)))
return false;
@@ -3211,8 +3217,12 @@ may_alias_p (const_rtx mem, const_rtx x)
if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x))
return true;
- rtx x_base = find_base_term (x_addr);
- rtx mem_base = find_base_term (mem_addr);
+ rtx x_base = MEM_BASE (x);
+ if (!x_base)
+ x_base = find_base_term (x_addr);
+ rtx mem_base = MEM_BASE (mem);
+ if (!mem_base)
+ mem_base = find_base_term (mem_addr);
if (! base_alias_check (x_addr, x_base, mem_addr, mem_base,
GET_MODE (x), GET_MODE (mem_addr)))
return false;
@@ -368,7 +368,10 @@ mem_attrs_eq_p (const class mem_attrs *p, const class mem_attrs *q)
&& p->addrspace == q->addrspace
&& (p->expr == q->expr
|| (p->expr != NULL_TREE && q->expr != NULL_TREE
- && operand_equal_p (p->expr, q->expr, 0))));
+ && operand_equal_p (p->expr, q->expr, 0)))
+ && (p->base == q->base
+ || (p->base != NULL_RTX && q->base != NULL_RTX
+ && rtx_equal_p (p->base, q->base))));
}
/* Set MEM's memory attributes so that they are the same as ATTRS. */
@@ -1828,6 +1831,7 @@ operand_subword_force (rtx op, poly_uint64 offset, machine_mode mode)
mem_attrs::mem_attrs ()
: expr (NULL_TREE),
+ base (NULL_RTX),
offset (0),
size (0),
alias (0),
@@ -1985,6 +1989,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
/* ??? Can this ever happen? Calling this routine on a MEM that
already carries memory attributes should probably be invalid. */
attrs.expr = refattrs->expr;
+ attrs.base = refattrs->base;
attrs.offset_known_p = refattrs->offset_known_p;
attrs.offset = refattrs->offset;
attrs.size_known_p = refattrs->size_known_p;
@@ -1997,6 +2002,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
{
defattrs = mode_mem_attrs[(int) GET_MODE (ref)];
gcc_assert (!defattrs->expr);
+ gcc_assert (!defattrs->base);
gcc_assert (!defattrs->offset_known_p);
/* Respect mode size. */
@@ -2264,6 +2270,16 @@ clear_mem_size (rtx mem)
attrs.size_known_p = false;
set_mem_attrs (mem, &attrs);
}
+
+/* Set the BASE of MEM. */
+
+void
+set_mem_base (rtx mem, rtx base)
+{
+ mem_attrs attrs (*get_mem_attrs (mem));
+ attrs.base = base;
+ set_mem_attrs (mem, &attrs);
+}
/* Return a memory reference like MEMREF, but with its mode changed to MODE
and its address changed to ADDR. (VOIDmode means don't change the mode.
@@ -361,6 +361,9 @@ extern void set_mem_addr_space (rtx, addr_space_t);
/* Set the expr for MEM to EXPR. */
extern void set_mem_expr (rtx, tree);
+/* Set the base for MEM to BASE. */
+extern void set_mem_base (rtx, rtx);
+
/* Set the offset for MEM to OFFSET. */
extern void set_mem_offset (rtx, poly_int64);
@@ -974,6 +974,12 @@ rtx_writer::print_rtx (const_rtx in_rtx)
if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (in_rtx)))
fprintf (m_outfile, " AS%u", MEM_ADDR_SPACE (in_rtx));
+ if (MEM_BASE (in_rtx))
+ {
+ fputc (' ', m_outfile);
+ print_rtx (MEM_BASE (in_rtx));
+ }
+
fputc (']', m_outfile);
break;
@@ -159,6 +159,10 @@ public:
(In other words, the MEM might access only part of the object.) */
tree expr;
+ /* A unique base this MEM accesses. This can be a SYMBOL_REF or
+ an ADDRESS RTX. */
+ rtx base;
+
/* The offset of the memory reference from the start of EXPR.
Only valid if OFFSET_KNOWN_P. */
poly_int64 offset;
@@ -2643,6 +2647,9 @@ do { \
refer to part of a DECL. It may also be a COMPONENT_REF. */
#define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
+/* For a MEM rtx, the ADDRESS or SYMBOL_REF it is based on. */
+#define MEM_BASE(RTX) (get_mem_attrs (RTX)->base)
+
/* For a MEM rtx, true if its MEM_OFFSET is known. */
#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset_known_p)