add_multivariate_self_dist and add_other_self_distances detect a self
dependence that distance vectors cannot describe, with more than two
varying loops or an initial value or step that is not constant, but they
only clear DDR_AFFINE_P.  The relation stays dependent with the zero
vector saved before, and the users of the vectors take it as exact, so
for example the outer-loop vectorizer can miscompile.  Mark such a
relation as unknown and release its vectors.  Also release them at the
existing early-out for several subscripts, as unroll-and-jam reads the
vectors of a relation without checking for chrec_dont_know.

        PR tree-optimization/115869

gcc/ChangeLog:

        * tree-data-ref.cc (add_multivariate_self_dist): Set
        DDR_ARE_DEPENDENT to chrec_dont_know and release the distance
        vectors when the dependence cannot be represented.
        (add_other_self_distances): Likewise.  Release the distance
        vectors when giving up on several subscripts.

gcc/testsuite/ChangeLog:

        * gcc.dg/torture/pr115869-4.c: New test.

Signed-off-by: Rohith Kapelli <[email protected]>
---
 gcc/testsuite/gcc.dg/torture/pr115869-4.c | 33 +++++++++++++++++++++++
 gcc/tree-data-ref.cc                      | 17 ++++++++----
 2 files changed, 45 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr115869-4.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr115869-4.c 
b/gcc/testsuite/gcc.dg/torture/pr115869-4.c
new file mode 100644
index 000000000000..eebb1af4ce64
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr115869-4.c
@@ -0,0 +1,33 @@
+/* PR tree-optimization/115869 */
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+unsigned A0[16];
+unsigned B[6][1024];
+
+void __attribute__((noipa))
+foo (int n0, int n1, int n2, int n3)
+{
+  for (int i0 = 0; i0 < n0; i0++)
+    for (int i1 = 0; i1 < n1; i1++)
+      for (int i2 = 0; i2 < n2; i2++)
+       for (int i3 = 0; i3 < n3; i3++)
+         A0[i1 + i2 + i3]
+           = A0[i1 + i2 + i3] * 3u + B[i0][i1] + (unsigned) i3;
+}
+
+int
+main ()
+{
+  for (unsigned x = 0; x < 6 * 1024; x++)
+    ((unsigned *) B)[x] = x * 40503u + 117u;
+  for (unsigned x = 0; x < 16; x++)
+    A0[x] = x * 2654435761u + 117u;
+  foo (1, 1, 4, 2);
+  unsigned s = 0;
+  for (int x = 0; x < 16; x++)
+    s = s * 31 + A0[x];
+  if (s != 638080400u)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index d6da0fe58c37..31d324cb3abd 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -5310,6 +5310,8 @@ add_multivariate_self_dist (struct 
data_dependence_relation *ddr, tree c_2)
       || TREE_CODE (CHREC_RIGHT (c_2)) != INTEGER_CST)
     {
       DDR_AFFINE_P (ddr) = false;
+      DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
+      DDR_DIST_VECTS (ddr).release ();
       return;
     }
 
@@ -5360,6 +5362,7 @@ add_other_self_distances (struct data_dependence_relation 
*ddr)
              if (DDR_NUM_SUBSCRIPTS (ddr) != 1)
                {
                  DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
+                 DDR_DIST_VECTS (ddr).release ();
                  return;
                }
 
@@ -5368,11 +5371,15 @@ add_other_self_distances (struct 
data_dependence_relation *ddr)
              if (TREE_CODE (CHREC_LEFT (access_fun)) == POLYNOMIAL_CHREC)
                add_multivariate_self_dist (ddr, access_fun);
              else
-               /* The evolution step is not constant: it varies in
-                  the outer loop, so this cannot be represented by a
-                  distance vector.  For example in pr34635.c the
-                  evolution is {0, +, {0, +, 4}_1}_2.  */
-               DDR_AFFINE_P (ddr) = false;
+               {
+                 /* The evolution step is not constant: it varies in
+                    the outer loop, so this cannot be represented by a
+                    distance vector.  For example in pr34635.c the
+                    evolution is {0, +, {0, +, 4}_1}_2.  */
+                 DDR_AFFINE_P (ddr) = false;
+                 DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
+                 DDR_DIST_VECTS (ddr).release ();
+               }
 
              return;
            }

Reply via email to