Preserve loops in tail-merge
authorvries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 Apr 2013 13:08:24 +0000 (13:08 +0000)
committervries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 29 Apr 2013 13:08:24 +0000 (13:08 +0000)
2013-04-29  Tom de Vries  <tom@codesourcery.com>

* tree-ssa-tail-merge.c (find_same_succ_bb): Skip loop latch bbs.
(replace_block_by): Don't set LOOPS_NEED_FIXUP.
(tail_merge_optimize): Handle current_loops == NULL.

* gcc.dg/pr50763.c: Update test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198414 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr50763.c
gcc/tree-ssa-tail-merge.c

index 05f2841..34dcd58 100644 (file)
@@ -1,3 +1,9 @@
+2013-04-29  Tom de Vries  <tom@codesourcery.com>
+
+       * tree-ssa-tail-merge.c (find_same_succ_bb): Skip loop latch bbs.
+       (replace_block_by): Don't set LOOPS_NEED_FIXUP.
+       (tail_merge_optimize): Handle current_loops == NULL.
+
 2013-04-26  Jeff Law  <law@redhat.com>
 
        * tree-vrp.c (range_fits_type_p): Move to earlier point in file.
index d7afacb..c1db93b 100644 (file)
@@ -1,3 +1,7 @@
+2013-04-29  Tom de Vries  <tom@codesourcery.com>
+
+       * gcc.dg/pr50763.c: Update test.
+
 2013-04-26  Jeff Law  <law@redhat.com>
 
        * gcc.dg/tree-ssa/vrp88.c: New test.
index 60025e3..695b61c 100644 (file)
@@ -12,5 +12,5 @@ foo (int c, int d)
   while (c == d);
 }
 
-/* { dg-final { scan-tree-dump-times "== 33" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "== 33" 2 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index d014b71..317fe4c 100644 (file)
@@ -691,7 +691,15 @@ find_same_succ_bb (basic_block bb, same_succ *same_p)
   edge_iterator ei;
   edge e;
 
-  if (bb == NULL)
+  if (bb == NULL
+      /* Be conservative with loop structure.  It's not evident that this test
+        is sufficient.  Before tail-merge, we've just called
+        loop_optimizer_finalize, and LOOPS_MAY_HAVE_MULTIPLE_LATCHES is now
+        set, so there's no guarantee that the loop->latch value is still valid.
+        But we assume that, since we've forced LOOPS_HAVE_SIMPLE_LATCHES at the
+        start of pre, we've kept that property intact throughout pre, and are
+        keeping it throughout tail-merge using this test.  */
+      || bb->loop_father->latch == bb)
     return;
   bitmap_set_bit (same->bbs, bb->index);
   FOR_EACH_EDGE (e, ei, bb->succs)
@@ -1462,17 +1470,6 @@ replace_block_by (basic_block bb1, basic_block bb2)
   /* Mark the basic block as deleted.  */
   mark_basic_block_deleted (bb1);
 
-  /* ???  If we merge the loop preheader with the loop latch we are creating
-     additional entries into the loop, eventually rotating it.
-     Mark loops for fixup in this case.
-     ???  This is a completely unwanted transform and will wreck most
-     loops at this point - but with just not considering loop latches as
-     merge candidates we fail to commonize the two loops in gcc.dg/pr50763.c.
-     A better fix to avoid that regression is needed.  */
-  if (current_loops
-      && bb2->loop_father->latch == bb2)
-    loops_state_set (LOOPS_NEED_FIXUP);
-
   /* Redirect the incoming edges of bb1 to bb2.  */
   for (i = EDGE_COUNT (bb1->preds); i > 0 ; --i)
     {
@@ -1614,7 +1611,19 @@ tail_merge_optimize (unsigned int todo)
   int iteration_nr = 0;
   int max_iterations = PARAM_VALUE (PARAM_MAX_TAIL_MERGE_ITERATIONS);
 
-  if (!flag_tree_tail_merge || max_iterations == 0)
+  if (!flag_tree_tail_merge
+      || max_iterations == 0
+      /* We try to be conservative with respect to loop structure, since:
+        - the cases where tail-merging could both affect loop structure and be
+          benificial are rare,
+        - it prevents us from having to fixup the loops using
+          loops_state_set (LOOPS_NEED_FIXUP), and
+        - keeping loop structure may allow us to simplify the pass.
+        In order to be conservative, we need loop information.  In rare cases
+        (about 7 test-cases in the g++ testsuite) there is none (because
+        loop_optimizer_finalize has been called before tail-merge, and
+        PROP_loops is not set), so we bail out.  */
+      || current_loops == NULL)
     return 0;
 
   timevar_push (TV_TREE_TAIL_MERGE);