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.
---
.../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(+)
create mode 100644 gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-1.c
create mode 100644 gcc/testsuite/gcc.dg/vect/vect-alias-check-ptr-info-2.c
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
--
2.34.1