diff mbox

Fix PR63168

Message ID alpine.LSU.2.11.1410161106570.20733@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener Oct. 16, 2014, 9:09 a.m. UTC
We can fail to copy loop headers if the loop looks proper to us
(empty latch) even when the latch really isn't empty and just
contains a PHI node.  In this case cfgcleanup should have merged
it with the previous block but it fails to do that because of
an overly strict check.  Fixed by only "preserving" loop latches
when required and the result wouldn't be a simple latch.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2014-10-16  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/63168
	* tree-cfg.c (gimple_can_merge_blocks_p): Only protect
	latches if after merging they are no longer simple.
	* cfghooks.c (merge_blocks): Handle merging a latch block
	into another block.

	* gcc.dg/tree-ssa/loop-40.c: New testcase.
diff mbox

Patch

Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 216258)
+++ gcc/tree-cfg.c	(working copy)
@@ -1674,8 +1678,12 @@  gimple_can_merge_blocks_p (basic_block a
 	return false;
     }
 
-  /* Protect the loop latches.  */
-  if (current_loops && b->loop_father->latch == b)
+  /* Protect simple loop latches.  We only want to avoid merging
+     the latch with the loop header in this case.  */
+  if (current_loops
+      && b->loop_father->latch == b
+      && loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES)
+      && b->loop_father->header == a)
     return false;
 
   /* It must be possible to eliminate all phi nodes in B.  If ssa form
Index: gcc/cfghooks.c
===================================================================
--- gcc/cfghooks.c	(revision 216258)
+++ gcc/cfghooks.c	(working copy)
@@ -766,6 +766,11 @@  merge_blocks (basic_block a, basic_block
 	  add_bb_to_loop  (a, b->loop_father);
 	  a->loop_father->header = a;
 	}
+      /* If we merge a loop latch into its predecessor, update the loop
+         structure.  */
+      if (b->loop_father->latch
+	  && b->loop_father->latch == b)
+	b->loop_father->latch = a;
       remove_bb_from_loops (b);
     }
 
Index: gcc/testsuite/gcc.dg/tree-ssa/loop-40.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/loop-40.c	(revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/loop-40.c	(working copy)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ch-details" } */
+
+int mymax2(int *it, int *end)
+{
+  int max = *it;
+  while (++it != end)
+    if (*it > max)
+      max = *it;
+  return max;
+}
+
+/* { dg-final { scan-tree-dump "Duplicating header" "ch" } } */
+/* { dg-final { cleanup-tree-dump "ch" } } */