[gcc(refs/users/aoliva/heads/testme)] alias/cselib: check alias/overlap preservation of lookup result
Alexandre Oliva
aoliva@gcc.gnu.org
Tue Dec 16 02:44:40 GMT 2025
https://gcc.gnu.org/g:dd755cf1cc95d83e213923d0fa7d825037e29754
commit dd755cf1cc95d83e213923d0fa7d825037e29754
Author: Alexandre Oliva <oliva@gnu.org>
Date: Sat Dec 13 04:12:39 2025 -0300
alias/cselib: check alias/overlap preservation of lookup result
Diff:
---
gcc/alias.cc | 92 ++++++++++++++++++++++++++++++++++++++++++++++++-----
gcc/cselib.cc | 63 +++++++++++++++++++++++++++++++++++-
gcc/rtl.def | 3 ++
gcc/var-tracking.cc | 1 +
4 files changed, 150 insertions(+), 9 deletions(-)
diff --git a/gcc/alias.cc b/gcc/alias.cc
index a23396eaa35e..866d305225a5 100644
--- a/gcc/alias.cc
+++ b/gcc/alias.cc
@@ -1659,6 +1659,16 @@ get_reg_base_value (unsigned int regno)
return (*reg_base_value)[regno];
}
+rtx
+get_reg_base_value_checked (unsigned int regno)
+{
+ if (!reg_base_value)
+ return NULL_RTX;
+ if (regno >= reg_base_value->length ())
+ return NULL_RTX;
+ return get_reg_base_value (regno);
+}
+
/* If a value is known for REGNO, return it. */
rtx
@@ -1964,6 +1974,12 @@ find_base_term (rtx x, vec<std::pair<cselib_val *,
return temp;
}
+ case VALUE_ADDRESS:
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != VALUE)
+ return x;
+ /* Fall through. */
+
case VALUE:
val = CSELIB_VAL_PTR (x);
ret = NULL_RTX;
@@ -2070,6 +2086,13 @@ find_base_term (rtx x)
return res;
}
+rtx
+find_value_base_term (rtx x)
+{
+ gcc_checking_assert (GET_CODE (x) == VALUE);
+ return find_base_term (x);
+}
+
/* Return true if accesses to address X may alias accesses based
on the stack pointer. */
@@ -2315,8 +2338,16 @@ get_addr (rtx x)
for (l = v->locs; l; l = l->next)
if (CONSTANT_P (l->loc))
return l->loc;
+#if 0
+ else if (GET_CODE (l->loc) == VALUE_ADDRESS)
+ return x;
+#endif
for (l = v->locs; l; l = l->next)
if (!REG_P (l->loc) && !MEM_P (l->loc)
+ /* ENTRY_VALUEs are not useful addresses, we can't get aliasing
+ information from them. */
+ && GET_CODE (l->loc) != ENTRY_VALUE
+ && GET_CODE (l->loc) != VALUE_ADDRESS
/* Avoid infinite recursion when potentially dealing with
var-tracking artificial equivalences, by skipping the
equivalences themselves, and not choosing expressions
@@ -2330,6 +2361,8 @@ get_addr (rtx x)
for (l = v->locs; l; l = l->next)
if (REG_P (l->loc)
|| (GET_CODE (l->loc) != VALUE
+ && GET_CODE (l->loc) != ENTRY_VALUE
+ && GET_CODE (l->loc) != VALUE_ADDRESS
&& !refs_newer_value_p (l->loc, x)))
return l->loc;
/* Return the canonical value. */
@@ -3080,6 +3113,38 @@ canon_true_dependence (const_rtx mem, machine_mode mem_mode, rtx mem_addr,
x, x_addr, /*mem_canonicalized=*/true);
}
+/* Return true iff x and m are addresses with the same base term, and that are
+ equivalent memrefs. Both are presumed canonicalized. */
+bool
+same_base_term_known_overlap_p (rtx x, rtx m, poly_int64 size)
+{
+ rtx tx = get_addr (x);
+ rtx tm = get_addr (m);
+
+ rtx bx = find_base_term (tx);
+ rtx bm = find_base_term (tm);
+
+ if (bx != bm && bx && bm
+ && !(GET_CODE (bx) == ADDRESS
+ && GET_CODE (bm) == ADDRESS
+ && bx->u.fld[0].rt_int <= 0
+ && bm->u.fld[0].rt_int <= 0)
+ /* libgo runtime may different decls for the same symbol used within the
+ same function, because they come from different units compiled
+ together. */
+ && !(GET_CODE (bx) == SYMBOL_REF
+ && GET_CODE (bm) == SYMBOL_REF
+ && XSTR (bx, 0) == XSTR (bm, 0))
+ return false;
+
+#if 0
+ x = canon_rtx (tx);
+ m = canon_rtx (tm);
+#endif
+
+ return memrefs_conflict_p (size, x, size, m, 0) != 0;
+}
+
/* Returns true if a write to X might alias a previous read from
(or, if WRITEP is true, a write to) MEM.
If X_CANONCALIZED is true, then X_ADDR is the canonicalized address of X,
@@ -3290,16 +3355,25 @@ init_alias_target (void)
&& targetm.hard_regno_mode_ok (i, Pmode))
static_reg_base_value[i] = arg_base_value;
- /* RTL code is required to be consistent about whether it uses the
- stack pointer, the frame pointer or the argument pointer to
- access a given area of the frame. We can therefore use the
- base address to distinguish between the different areas. */
+ /* RTL code is required to be consistent about whether it uses the stack
+ pointer, the frame pointer or the argument pointer to access a given area
+ of the frame. We can therefore use the base address to distinguish
+ between the different areas. However, after register allocation and
+ especially prologue generation, cselib makes all these areas part of the
+ same cluster of VALUEs, making it hard to distinguish the areas, so make
+ them all share the same base term then. */
static_reg_base_value[STACK_POINTER_REGNUM]
- = unique_base_value (UNIQUE_BASE_VALUE_SP);
+ = (reload_completed
+ ? arg_base_value
+ : unique_base_value (UNIQUE_BASE_VALUE_SP));
static_reg_base_value[ARG_POINTER_REGNUM]
- = unique_base_value (UNIQUE_BASE_VALUE_ARGP);
+ = (reload_completed
+ ? arg_base_value
+ : unique_base_value (UNIQUE_BASE_VALUE_ARGP));
static_reg_base_value[FRAME_POINTER_REGNUM]
- = unique_base_value (UNIQUE_BASE_VALUE_FP);
+ = (reload_completed
+ ? arg_base_value
+ : unique_base_value (UNIQUE_BASE_VALUE_FP));
/* The above rules extend post-reload, with eliminations applying
consistently to each of the three pointers. Cope with cases in
@@ -3307,7 +3381,9 @@ init_alias_target (void)
rather than the stack pointer. */
if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
static_reg_base_value[HARD_FRAME_POINTER_REGNUM]
- = unique_base_value (UNIQUE_BASE_VALUE_HFP);
+ = (reload_completed
+ ? arg_base_value
+ : unique_base_value (UNIQUE_BASE_VALUE_HFP));
}
/* Set MEMORY_MODIFIED when X modifies DATA (that is assumed
diff --git a/gcc/cselib.cc b/gcc/cselib.cc
index c6628abf2a98..a6cae62bb2fe 100644
--- a/gcc/cselib.cc
+++ b/gcc/cselib.cc
@@ -2505,6 +2505,8 @@ cselib_lookup (rtx x, machine_mode mode,
static void
cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l)
{
+ extern rtx get_reg_base_value_checked (unsigned);
+ rtx value_address = get_reg_base_value_checked (regno);
cselib_val *v = (*l)->elt;
if (*l == REG_VALUES (regno))
{
@@ -2517,7 +2519,12 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l)
l = &(*l)->next;
}
else
- unchain_one_elt_list (l);
+ {
+ if (value_address
+ && GET_MODE (value_address) != GET_MODE (v->val_rtx))
+ value_address = NULL_RTX;
+ unchain_one_elt_list (l);
+ }
v = canonical_cselib_val (v);
@@ -2533,6 +2540,56 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l)
if (REG_P (x) && REGNO (x) == regno)
{
unchain_one_elt_loc_list (p);
+
+ extern rtx find_value_base_term (rtx);
+ /* Preserve the VALUE_ADDRESS associated with the regno previously
+ held in v, if we can't identify it any longer. */
+ rtx found_value_address = find_value_base_term (v->val_rtx);
+ cselib_val *add_address_to = NULL;
+ if (value_address && found_value_address != value_address)
+ add_address_to = v;
+
+ rtx wanted_value_address
+ = value_address ? value_address : found_value_address;
+
+ if (wanted_value_address)
+ {
+ cselib_val *addrv = v;
+ for (;;)
+ {
+ rtx addr = canon_rtx (get_addr (addrv->val_rtx));
+ if (addr == addrv->val_rtx
+ || GET_CODE (addr) != PLUS
+ || GET_CODE (XEXP (addr, 0)) != VALUE
+ || !CONSTANT_P (XEXP (addr, 1)))
+ break;
+
+ rtx addr_value_address
+ = find_value_base_term (XEXP (addr, 0));
+ if (addr_value_address)
+ break;
+ else
+ {
+ gcc_checking_assert (addr_value_address
+ != wanted_value_address);
+ addrv = add_address_to
+ = canonical_cselib_val (CSELIB_VAL_PTR (XEXP (addr, 0)));
+ }
+ }
+ }
+
+ if (add_address_to)
+ {
+ if (add_address_to != v)
+ p = &add_address_to->locs;
+
+ elt_loc_list *n = *p;
+ *p = elt_loc_list_pool.allocate ();
+ (*p)->loc = gen_rtx_VALUE_ADDRESS (GET_MODE (v->val_rtx),
+ wanted_value_address);
+ (*p)->setting_insn = setting_insn;
+ (*p)->next = n;
+ }
break;
}
}
@@ -2628,6 +2685,10 @@ cselib_invalidate_mem (rtx mem_rtx)
if ((v = cselib_lookup (mem_addr, GET_MODE (mem_addr),
0, GET_MODE (mem_rtx))))
{
+ extern bool same_base_term_known_overlap_p (rtx, rtx, poly_int64);
+ gcc_checking_assert (same_base_term_known_overlap_p
+ (mem_addr, v->val_rtx,
+ GET_MODE_SIZE (GET_MODE (mem_rtx))));
mem_addr = v->val_rtx;
mem_rtx = replace_equiv_address_nv (mem_rtx, mem_addr);
}
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 15ae7d10fcc1..b1f68fb00d25 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -128,6 +128,9 @@ DEF_RTL_EXPR(SEQUENCE, "sequence", "E", RTX_EXTRA)
/* Represents a non-global base address. This is only used in alias.cc. */
DEF_RTL_EXPR(ADDRESS, "address", "i", RTX_EXTRA)
+/* Represents a base address within a cselib table. */
+DEF_RTL_EXPR(VALUE_ADDRESS, "value_address", "e", RTX_OBJ)
+
/* ----------------------------------------------------------------------
Expression types used for things in the instruction chain.
diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc
index 8732c3ba62aa..21cde6b0a7b6 100644
--- a/gcc/var-tracking.cc
+++ b/gcc/var-tracking.cc
@@ -2442,6 +2442,7 @@ unsuitable_loc (rtx loc)
case SCRATCH:
case ASM_INPUT:
case ASM_OPERANDS:
+ case VALUE_ADDRESS:
return true;
default:
More information about the Gcc-cvs
mailing list