This allows cfgcleanup to remove some of the extra CFG that exists just for loop analysis passes convenience (those can be and are easily re-created by passes doing loop_optimizer_init ()).
It may fix a regression uncovered in private communication. Untested - my original idea how to fix this (tree_forwarder_block_p hunk) ran into the issue in remove_forwarder_block which causes loops to be removed / re-discovered (losing meta-data). Richard. 2014-02-19 Richard Biener <rguent...@suse.de> * tree-cfgcleanup.c (tree_forwarder_block_p): Protect latches and preheaders only if requested. (remove_forwarder_block): Update loop structure if we removed a forwarder that is a loop latch. Index: gcc/tree-cfgcleanup.c =================================================================== *** gcc/tree-cfgcleanup.c (revision 207878) --- gcc/tree-cfgcleanup.c (working copy) *************** tree_forwarder_block_p (basic_block bb, *** 307,321 **** if (current_loops) { ! basic_block dest; ! /* Protect loop latches, headers and preheaders. */ if (bb->loop_father->header == bb) return false; - dest = EDGE_SUCC (bb, 0)->dest; ! if (dest->loop_father->header == dest) return false; } return true; } --- 307,324 ---- if (current_loops) { ! /* Protect loop headers. */ if (bb->loop_father->header == bb) return false; ! /* Protect loop latches and preheaders if requested. */ ! basic_block dest = EDGE_SUCC (bb, 0)->dest; ! if (dest->loop_father->header == dest ! && (loops_state_satisfies_p (LOOPS_HAVE_PREHEADERS) ! || loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES))) return false; } + return true; } *************** remove_forwarder_block (basic_block bb) *** 497,503 **** set_immediate_dominator (CDI_DOMINATORS, dest, dom); } ! /* And kill the forwarder block. */ delete_basic_block (bb); return true; --- 500,511 ---- set_immediate_dominator (CDI_DOMINATORS, dest, dom); } ! /* And kill the forwarder block, but first adjust its parent loop ! latch info as otherwise the cfg hook has a hard time not to ! kill the loop. */ ! if (current_loops ! && bb->loop_father->latch == bb) ! bb->loop_father->latch = dest; delete_basic_block (bb); return true;