https://gcc.gnu.org/g:5a3ad9374a73df7df7e8a00b1c06fbf30ad7298c

commit r17-3944-g5a3ad9374a73df7df7e8a00b1c06fbf30ad7298c
Author: Philipp Tomsich <[email protected]>
Date:   Sun Jul 26 14:03:26 2026 +0200

    tree-data-ref: use DR_PTR_INFO points-to info in dr_may_alias_p [PR127201]
    
    Pointer SSA names created after the last points-to computation (e.g. by
    PRE re-materializing a load, gated on flag_tree_pre || flag_code_hoisting)
    carry no SSA_NAME_PTR_INFO.  When dr_analyze_innermost re-expresses a
    data reference's base, DR_BASE_OBJECT can root at such a name, and
    ptr_derefs_may_alias_p then returns may-alias for lack of information.
    
    dr_analyze_alias already records that original solution in
    DR_PTR_INFO.  Intersect the recorded solutions with
    pt_solutions_intersect before falling back to the rewritten base
    object.  This is valid for cross-iteration queries because a points-to
    solution covers every dynamic value of the SSA name.  The vectorizer
    already relies on this when it stamps DR_PTR_INFO onto the data-ref
    pointers it synthesizes (vect_duplicate_ssa_name_ptr_info).
    
    On SPEC CPU 2026's 722.palm_r, file advec_ws.fppized.f90, this removed
    (in one run measured on Aarch64) approx. 28.5% of the required runtime
    alias checks (3952 -> 2824) and all 18 in the hot loop, which then
    vectorized with no versioning at all.
    
    Bootstrapped and tested on x86_64-pc-linux-gnu.
    
            PR tree-optimization/127201
    
    gcc/ChangeLog:
    
            * tree-data-ref.cc (dr_may_alias_p): Consult DR_PTR_INFO of both
            data references before falling back to base-object analysis.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/vect/vect-alias-check-ptr-info-1.c: New test.
            * gcc.dg/vect/vect-alias-check-ptr-info-2.c: New test.

Diff:
---
 .../gcc.dg/vect/vect-alias-check-ptr-info-1.c      | 42 +++++++++++++++++
 .../gcc.dg/vect/vect-alias-check-ptr-info-2.c      | 52 ++++++++++++++++++++++
 gcc/tree-data-ref.cc                               | 12 +++++
 3 files changed, 106 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-1.c 
b/gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-1.c
new file mode 100644
index 000000000000..9c65922311ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-1.c
@@ -0,0 +1,42 @@
+/* Base pointers re-materialized by PRE after the last points-to run carry
+   no SSA_NAME_PTR_INFO; dr_may_alias_p must fall back to the points-to
+   solution recorded on the data reference (DR_PTR_INFO) instead of
+   emitting runtime alias checks between provably disjoint objects.  */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-O3 -ffast-math" } */
+
+struct desc { double *data; long span; };
+struct desc g;
+int lo, hi;
+double res;
+
+void
+f (int c)
+{
+  int n = hi - lo + 2;
+  double t[n], u[n];           /* VLAs -> __builtin_alloca_with_align */
+
+  /* g.data is loaded on both arms, so PRE materialises it as a fresh
+     "pretmp" pointer SSA name -- after the last points-to run.  */
+  if (c)
+    res = g.data[0];
+  else
+    res = g.data[1];
+
+  for (int k = 2; k < n - 2; k++)
+    {
+      u[k] = g.data[k + 1] + g.data[k];
+      t[k] = u[k] * (37.0 * (g.data[k + 1] + g.data[k])
+                    - 8.0 * (g.data[k + 2] + g.data[k - 1]));
+    }
+
+  double s = 0;
+  for (int k = 2; k < n - 2; k++)
+    s += t[k] + u[k];
+  res += s;
+}
+
+/* The local VLAs cannot alias the global-reached g.data; no runtime
+   alias checks may be required.  */
+/* { dg-final { scan-tree-dump-not "versioning for alias required" "vect" } } 
*/
diff --git a/gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-2.c 
b/gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-2.c
new file mode 100644
index 000000000000..5bb4dac69e3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-2.c
@@ -0,0 +1,52 @@
+/* An info-less pointer (re-materialized by PRE after the last points-to
+   run) may still point to a non-escaped local; the dependence against
+   that local must be preserved.  Execution test: the store stream
+   through 'tab[idx & 1]' aliases 't' when idx is even.  */
+/* { dg-do run } */
+/* { dg-additional-options "-O3 -ffast-math" } */
+
+extern void abort (void);
+
+double res;
+int lo, hi, idx;
+
+void __attribute__ ((noipa))
+f (int c)
+{
+  int n = hi - lo + 2;
+  double t[n], u[n];
+  double *tab[2] = { t, u };
+
+  /* Load tab[idx&1] on both arms so PRE hoists it into a pretmp.  */
+  if (c)
+    res = tab[idx & 1][0];
+  else
+    res = tab[idx & 1][1];
+
+  for (int k = 0; k < n; k++)
+    t[k] = u[k] = k;
+
+  for (int k = 3; k < n - 2; k++)
+    {
+      tab[idx & 1][k] = t[k - 1] + 1.0;   /* stores TO t when idx is even */
+      res += t[k];                        /* must observe those stores    */
+    }
+
+  double s = 0;
+  for (int k = 2; k < n - 2; k++)
+    s += t[k] + u[k];
+  res += s;
+}
+
+int
+main (void)
+{
+  lo = 0; hi = 14; idx = 0;   /* idx even: store stream aliases t */
+  res = 0;
+  f (1);
+  double expect = 0.0 + (3+4+5+6+7+8+9+10+11+12+13)
+                 + 2.0 * (2+3+4+5+6+7+8+9+10+11+12+13);
+  if (res != expect)
+    abort ();
+  return 0;
+}
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 8e9d78713482..db77e4ead727 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -3059,6 +3059,18 @@ dr_may_alias_p (const struct data_reference *a, const 
struct data_reference *b,
        return false;
     }
 
+  /* Try the points-to information recorded for the base pointers the
+     references were originally analyzed from.  DR_BASE_OBJECT can be less
+     precise, rooting at another SSA name or at one created after points-to
+     information was computed and thus without SSA_NAME_PTR_INFO.  A
+     recorded solution is not revalidated.  It covers every dynamic value
+     of its SSA name, so it holds for cross-iteration queries as well.  */
+  struct ptr_info_def *pi_a = DR_PTR_INFO (a);
+  struct ptr_info_def *pi_b = DR_PTR_INFO (b);
+  if (pi_a && pi_b
+      && !pt_solutions_intersect (&pi_a->pt, &pi_b->pt))
+    return false;
+
   if ((TREE_CODE (addr_a) == MEM_REF || TREE_CODE (addr_a) == TARGET_MEM_REF)
       && (TREE_CODE (addr_b) == MEM_REF || TREE_CODE (addr_b) == 
TARGET_MEM_REF)
       /* For cross-iteration dependences the cliques must be valid for the

Reply via email to