Hi,
Function generate_loops_for_partition chooses arbitrary path when removing exit
condition not in partition.  This is fine for now because it's impossible to 
have
loop exit condition in case of innermost distribution.  After extending to loop
nest distribution, we must choose exit edge/path for inner loop's exit 
condition,
otherwise an infinite empty loop will be generated.  Test case added.

Bootstrap and test in patch set on x86_64 and AArch64, is it OK?

Thanks,
bin
2017-10-04  Bin Cheng  <bin.ch...@arm.com>

        * tree-loop-distribution.c (generate_loops_for_partition): Remove
        inner loop's exit stmt by making it always exit the loop, otherwise
        we would generate an infinite empty loop.

gcc/testsuite/ChangeLog
2017-10-04  Bin Cheng  <bin.ch...@arm.com>

        * gcc.dg/tree-ssa/ldist-27.c: New test.
From 29f15d5a166b139d8d2dad2ee798c4d0a338f820 Mon Sep 17 00:00:00 2001
From: Bin Cheng <binch...@e108451-lin.cambridge.arm.com>
Date: Mon, 25 Sep 2017 16:52:42 +0100
Subject: [PATCH 4/7] loop_nest-exit-cond-distribution.txt

---
 gcc/testsuite/gcc.dg/tree-ssa/ldist-27.c | 38 ++++++++++++++++++++++++++++++++
 gcc/tree-loop-distribution.c             | 16 +++++++++++---
 2 files changed, 51 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ldist-27.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-27.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-27.c
new file mode 100644
index 0000000..3580c65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-27.c
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -ftree-loop-distribute-patterns -fdump-tree-ldist-details" } */
+
+#define M (300)
+#define N (200)
+
+struct st
+{
+  double a[M];
+  double b[M];
+  double c[M][N];
+};
+
+int __attribute__ ((noinline)) foo (struct st *s)
+{
+  int i, j;
+  for (i = 0; i != M;)
+    {
+      s->a[i] = 0.0;
+      s->b[i] = 1.0;
+      for (j = 0; 1; ++j)
+	{
+	  if (j == N) goto L2;
+	  s->c[i][j] = 0.0;
+	}
+L2:
+      ++i;
+    }
+  return 0;
+}
+
+int main (void)
+{
+  struct st s;
+  return foo (&s);
+}
+
+/* { dg-final { scan-tree-dump "distributed: split to " "ldist" } } */
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 3db3d6e..999b32e 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -830,6 +830,10 @@ generate_loops_for_partition (struct loop *loop, partition *partition,
   for (i = 0; i < loop->num_nodes; i++)
     {
       basic_block bb = bbs[i];
+      edge inner_exit = NULL;
+
+      if (loop != bb->loop_father)
+	inner_exit = single_exit (bb->loop_father);
 
       for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi);)
 	{
@@ -848,11 +852,17 @@ generate_loops_for_partition (struct loop *loop, partition *partition,
 	      && !is_gimple_debug (stmt)
 	      && !bitmap_bit_p (partition->stmts, gimple_uid (stmt)))
 	    {
-	      /* Choose an arbitrary path through the empty CFG part
-		 that this unnecessary control stmt controls.  */
+	      /* In distribution of loop nest, if bb is inner loop's exit_bb,
+		 we choose its exit edge/path in order to avoid generating
+		 infinite loop.  For all other cases, we choose an arbitrary
+		 path through the empty CFG part that this unnecessary
+		 control stmt controls.  */
 	      if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
 		{
-		  gimple_cond_make_false (cond_stmt);
+		  if (inner_exit && inner_exit->flags & EDGE_TRUE_VALUE)
+		    gimple_cond_make_true (cond_stmt);
+		  else
+		    gimple_cond_make_false (cond_stmt);
 		  update_stmt (stmt);
 		}
 	      else if (gimple_code (stmt) == GIMPLE_SWITCH)
-- 
1.9.1

Reply via email to