https://gcc.gnu.org/g:0beee147dd96e0c32ec687dbec3f7d2dfe436a21

commit 0beee147dd96e0c32ec687dbec3f7d2dfe436a21
Author: Alexandre Oliva <[email protected]>
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..f6f59c8e1311 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:

Reply via email to