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 <rguent...@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. 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" } } */