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;
}