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