The following fixes an omission in dependence testing for loop
distribution. When the overall dependence distance is not zero but
the dependence direction in the innermost common loop is = there is
a conflict between the partitions and we have to merge them.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.
PR tree-optimization/112281
* tree-loop-distribution.cc
(loop_distribution::pg_add_dependence_edges): For = in the
innermost common loop record a partition conflict.
* gcc.dg/torture/pr112281-1.c: New testcase.
* gcc.dg/torture/pr112281-2.c: Likewise.
---
gcc/testsuite/gcc.dg/torture/pr112281-1.c | 18 ++++++++++++++++++
gcc/testsuite/gcc.dg/torture/pr112281-2.c | 18 ++++++++++++++++++
gcc/tree-loop-distribution.cc | 18 ++++++++++++++----
3 files changed, 50 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr112281-1.c
create mode 100644 gcc/testsuite/gcc.dg/torture/pr112281-2.c
diff --git a/gcc/testsuite/gcc.dg/torture/pr112281-1.c
b/gcc/testsuite/gcc.dg/torture/pr112281-1.c
new file mode 100644
index 00000000000..711f5663195
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr112281-1.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-loop-distribution" } */
+
+struct {
+ int : 8;
+ int a;
+} b, d[4] = {{0}, {0}, {0}, {5}};
+int c, e;
+int main() {
+ for (c = 2; c; c--)
+ for (e = 0; e < 2; e++) {
+ d[c] = b = d[c + 1];
+ d[c + 1].a = 0;
+ }
+ if (b.a != 0)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr112281-2.c
b/gcc/testsuite/gcc.dg/torture/pr112281-2.c
new file mode 100644
index 00000000000..d7671e3322b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr112281-2.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-loop-distribution" } */
+
+struct {
+ int : 8;
+ int a;
+} b, d[4] = {{5}, {0}, {0}, {0}};
+int c, e;
+int main() {
+ for (c = 0; c < 2; c++)
+ for (e = 0; e < 2; e++) {
+ d[c + 1] = b = d[c];
+ d[c].a = 0;
+ }
+ if (b.a != 0)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
index ffca535064b..95c1eea65be 100644
--- a/gcc/tree-loop-distribution.cc
+++ b/gcc/tree-loop-distribution.cc
@@ -2155,9 +2155,6 @@ loop_distribution::pg_add_dependence_edges (struct graph
*rdg, int dir,
}
else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
{
- if (DDR_REVERSED_P (ddr))
- this_dir = -this_dir;
-
/* Known dependences can still be unordered througout the
iteration space, see gcc.dg/tree-ssa/ldist-16.c and
gcc.dg/tree-ssa/pr94969.c. */
@@ -2170,7 +2167,20 @@ loop_distribution::pg_add_dependence_edges (struct graph
*rdg, int dir,
/* Else as the distance vector is lexicographic positive swap
the dependence direction. */
else
- this_dir = -this_dir;
+ {
+ if (DDR_REVERSED_P (ddr))
+ this_dir = -this_dir;
+ this_dir = -this_dir;
+
+ /* When then dependence distance of the innermost common
+ loop of the DRs is zero we have a conflict. */
+ auto l1 = gimple_bb (DR_STMT (dr1))->loop_father;
+ auto l2 = gimple_bb (DR_STMT (dr2))->loop_father;
+ int idx = index_in_loop_nest (find_common_loop (l1, l2)->num,
+ DDR_LOOP_NEST (ddr));
+ if (DDR_DIST_VECT (ddr, 0)[idx] == 0)
+ this_dir = 2;
+ }
}
else
this_dir = 0;
--
2.35.3