tree-loop-distribution.c (generate_loops_for_partition): Remove inner loop's exit...
authorBin Cheng <bin.cheng@arm.com>
Tue, 10 Oct 2017 09:02:13 +0000 (09:02 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Tue, 10 Oct 2017 09:02:13 +0000 (09:02 +0000)
* 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
* gcc.dg/tree-ssa/ldist-27.c: New test.

From-SVN: r253580

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ldist-27.c [new file with mode: 0644]
gcc/tree-loop-distribution.c

index 6ce0d73dc4711f622305d7fbcb2d55792a480e96..01482824f71e9a8c96bb42b02970c140039bb576 100644 (file)
@@ -1,3 +1,9 @@
+2017-10-10  Bin Cheng  <bin.cheng@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.
+
 2017-10-10  Bin Cheng  <bin.cheng@arm.com>
 
        * tree-vect-loop-manip.c (slpeel_tree_duplicate_loop_to_edge_cfg): Skip
index eb88b21c4311f13a4c5d152cda7a441f55f1f357..33a5cf553022045a743e1caf06eb21e26c0069e7 100644 (file)
@@ -1,3 +1,7 @@
+2017-10-10  Bin Cheng  <bin.cheng@arm.com>
+
+       * gcc.dg/tree-ssa/ldist-27.c: New test.
+
 2017-10-09  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        * gcc.target/powerpc/amo1.c: New test.
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 (file)
index 0000000..3580c65
--- /dev/null
@@ -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" } } */
index 3db3d6ec21ef4c0a784edd684a6b3a2a977247e5..999b32ef06cd856b8db4f9385920b230bec7f7b1 100644 (file)
@@ -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)