]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/112859 - bogus loop distribution
authorRichard Biener <rguenther@suse.de>
Thu, 23 Jan 2025 12:10:17 +0000 (13:10 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 27 Jan 2025 12:31:35 +0000 (13:31 +0100)
When we get a zero distance vector we still have to check for the
situation of a common inner loop with zero distance.  But we can
still allow a zero distance for the loop we distribute
(gcc.dg/tree-ssa/ldist-33.c is such a case).  This is because
zero distances in non-outermost loops are a misrepresentation
of dependence by dependence analysis.

Note that test coverage of loop distribution of loop nests is
very low.

PR tree-optimization/112859
PR tree-optimization/115347
* tree-loop-distribution.cc
(loop_distribution::pg_add_dependence_edges): For a zero
distance vector still make sure to not have an inner
loop with zero distance.

* gcc.dg/torture/pr112859.c: New testcase.
* gcc.dg/torture/pr115347.c: Likewise.

gcc/testsuite/gcc.dg/torture/pr112859.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr115347.c [new file with mode: 0644]
gcc/tree-loop-distribution.cc

diff --git a/gcc/testsuite/gcc.dg/torture/pr112859.c b/gcc/testsuite/gcc.dg/torture/pr112859.c
new file mode 100644 (file)
index 0000000..18f5bf4
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-loop-distribution" } */
+
+struct a {
+  char b;
+  int c;
+} f, *i = &f;
+static struct a e[4];
+int *d, **g = &d;
+static int h, j;
+int main()
+{
+  for (; h < 1; h++) {
+    struct a k = {1, 1};
+    for (j = 0; j < 2; j++) {
+      *i = e[h];
+      e[h] = k;
+    }
+    *g = 0;
+  }
+  if (f.c != 1)
+    __builtin_abort();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr115347.c b/gcc/testsuite/gcc.dg/torture/pr115347.c
new file mode 100644 (file)
index 0000000..2299495
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-loop-distribution" } */
+
+struct a {
+  int b;
+  int c;
+} d, e[2];
+int f, g, h;
+int main()
+{
+  for (; f < 1; f++) {
+    for (h = 0; h < 2; h++) {
+      d = e[f];
+      g = e[1].c;
+      e[f].c = 1;
+    }
+  }
+  if (d.c != 1)
+    __builtin_abort();
+  return 0;
+}
index 7c0e4a868e513c0893c40f08dd11ef9175066bd0..9d9d2ae592b3dfa56e0cca44af2e831a011785fb 100644 (file)
@@ -2178,25 +2178,30 @@ loop_distribution::pg_add_dependence_edges (struct graph *rdg, int dir,
                 gcc.dg/tree-ssa/pr94969.c.  */
              if (DDR_NUM_DIST_VECTS (ddr) != 1)
                this_dir = 2;
-             /* If the overlap is exact preserve stmt order.  */
-             else if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0),
-                                           DDR_NB_LOOPS (ddr)))
-               ;
-             /* Else as the distance vector is lexicographic positive swap
-                the dependence direction.  */
              else
                {
-                 if (DDR_REVERSED_P (ddr))
-                   this_dir = -this_dir;
-                 this_dir = -this_dir;
-
+                 /* If the overlap is exact preserve stmt order.  */
+                 if (lambda_vector_zerop (DDR_DIST_VECT (ddr, 0),
+                                          DDR_NB_LOOPS (ddr)))
+                   ;
+                 /* Else as the distance vector is lexicographic positive swap
+                    the dependence direction.  */
+                 else
+                   {
+                     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)
+                 if (DDR_DIST_VECT (ddr, 0)[idx] == 0
+                     /* Unless it is the outermost loop which is the one
+                        we eventually distribute.  */
+                     && idx != 0)
                    this_dir = 2;
                }
            }