tree-optimization/112281 - loop distribution and zero dependence distances

Message ID 20231120140036.CEB293882060@sourceware.org
State Accepted
Headers
Series tree-optimization/112281 - loop distribution and zero dependence distances |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Richard Biener Nov. 20, 2023, 2 p.m. UTC
  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
  

Patch

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;