re PR tree-optimization/23855 (loop header should also be pulled out of the inner...
authorRichard Biener <rguenther@suse.de>
Wed, 17 Aug 2016 08:11:32 +0000 (08:11 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 17 Aug 2016 08:11:32 +0000 (08:11 +0000)
2016-08-17  Richard Biener  <rguenther@suse.de>

PR tree-optimization/23855
* tree-ssa-loop-unswitch.c: Include tree-ssa-loop-manip.h.
(tree_unswitch_outer_loop): Iterate find_loop_guard as long as we
find guards to hoist.  Do not update SSA form but rewrite virtuals
into loop closed SSA.
(find_loop_guard): Adjust to skip already hoisted guards.  Do
not mark virtuals for renaming or update SSA form.

* gcc.dg/loop-unswitch-2.c: Adjust.

From-SVN: r239523

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/loop-unswitch-2.c
gcc/tree-ssa-loop-unswitch.c

index edbac57728b1a1d92cbebc022f499434202247d2..467f016514b1a94f60e37ab59da40df8e8a7a004 100644 (file)
@@ -1,3 +1,13 @@
+2016-08-17  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/23855
+       * tree-ssa-loop-unswitch.c: Include tree-ssa-loop-manip.h.
+       (tree_unswitch_outer_loop): Iterate find_loop_guard as long as we
+       find guards to hoist.  Do not update SSA form but rewrite virtuals
+       into loop closed SSA.
+       (find_loop_guard): Adjust to skip already hoisted guards.  Do
+       not mark virtuals for renaming or update SSA form.
+
 2016-08-17  Martin Liska  <mliska@suse.cz>
 
        * coverage.c (get_gcov_type): Replace GCOV_TYPE_SIZE with
index cd0463f4d43c950d48000fc8a35cce4710ca1798..ffa81389d16c4707dc691f7311bd7218ede4e76d 100644 (file)
@@ -1,3 +1,8 @@
+2016-08-17  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/23855
+       * gcc.dg/loop-unswitch-2.c: Adjust.
+
 2016-08-16  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/72817
index 5ebf6087fcde9c8fff252a37f2a26aa1c2bd7c90..77900f9e955e722b9b352adfb725adc149abd253 100644 (file)
@@ -11,5 +11,5 @@ void foo (float **a, float **b, float *c, int n, int m, int l)
        c[i] += a[i][k] * b[k][j];
 }
 
-/* { dg-final { scan-tree-dump-times "guard hoisted" 2 "unswitch" } } */
+/* { dg-final { scan-tree-dump-times "guard hoisted" 3 "unswitch" } } */
 
index 73bdc6eab7d24c7d2fa9f7174663699557687510..40905af45eb55e1b68907a063615c20542e1b98b 100644 (file)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-inline.h"
 #include "gimple-iterator.h"
 #include "cfghooks.h"
+#include "tree-ssa-loop-manip.h"
 
 /* This file implements the loop unswitching, i.e. transformation of loops like
 
@@ -451,14 +452,15 @@ tree_unswitch_outer_loop (struct loop *loop)
       return false;
     }
 
-  guard = find_loop_guard (loop);
-  if (guard)
+  bool changed = false;
+  while ((guard = find_loop_guard (loop)))
     {
+      if (! changed)
+       rewrite_virtuals_into_loop_closed_ssa (loop);
       hoist_guard (loop, guard);
-      update_ssa (TODO_update_ssa);
-      return true;
+      changed = true;
     }
-  return false;
+  return changed;
 }
 
 /* Checks if the body of the LOOP is within an invariant guard.  If this
@@ -501,13 +503,28 @@ find_loop_guard (struct loop *loop)
        b) anything defined in something1, something2 and something3
           is not used outside of the loop.  */
 
-  while (single_succ_p (header))
-    header = single_succ (header);
-  if (!last_stmt (header)
-      || gimple_code (last_stmt (header)) != GIMPLE_COND)
-    return NULL;
-
-  extract_true_false_edges_from_block (header, &te, &fe);
+  gcond *cond;
+  do
+    {
+      if (single_succ_p (header))
+       header = single_succ (header);
+      else
+       {
+         cond = dyn_cast <gcond *> (last_stmt (header));
+         if (! cond)
+           return NULL;
+         extract_true_false_edges_from_block (header, &te, &fe);
+         /* Make sure to skip earlier hoisted guards that are left
+            in place as if (true).  */
+         if (gimple_cond_true_p (cond))
+           header = te->dest;
+         else if (gimple_cond_false_p (cond))
+           header = fe->dest;
+         else
+           break;
+       }
+    }
+  while (1);
   if (!flow_bb_inside_loop_p (loop, te->dest)
       || !flow_bb_inside_loop_p (loop, fe->dest))
     return NULL;
@@ -549,7 +566,7 @@ find_loop_guard (struct loop *loop)
             guard_edge->src->index, guard_edge->dest->index, loop->num);
   /* Check if condition operands do not have definitions inside loop since
      any bb copying is not performed.  */
-  FOR_EACH_SSA_TREE_OPERAND (use, last_stmt (header), iter, SSA_OP_USE)
+  FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)
     {
       gimple *def = SSA_NAME_DEF_STMT (use);
       basic_block def_bb = gimple_bb (def);
@@ -762,8 +779,6 @@ hoist_guard (struct loop *loop, edge guard)
        }
     }
 
-  mark_virtual_operands_for_renaming (cfun);
-  update_ssa (TODO_update_ssa);
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "  guard hoisted.\n");
 }