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.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Any comments?
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 | 24 ++++++++++++++++++++++
gcc/testsuite/gcc.dg/torture/pr115347.c | 21 +++++++++++++++++++
gcc/tree-loop-distribution.cc | 27 +++++++++++++++----------
3 files changed, 61 insertions(+), 11 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr112859.c
create mode 100644 gcc/testsuite/gcc.dg/torture/pr115347.c
diff --git a/gcc/testsuite/gcc.dg/torture/pr112859.c
b/gcc/testsuite/gcc.dg/torture/pr112859.c
new file mode 100644
index 00000000000..18f5bf40cb7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr112859.c
@@ -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
index 00000000000..2299495144b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr115347.c
@@ -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;
+}
diff --git a/gcc/tree-loop-distribution.cc b/gcc/tree-loop-distribution.cc
index 7c0e4a868e5..9d9d2ae592b 100644
--- a/gcc/tree-loop-distribution.cc
+++ b/gcc/tree-loop-distribution.cc
@@ -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;
}
}
--
2.43.0