The following patch makes sure we don't inline / copy a CFG with loops needing fixups. In the particular case function versioning after IPA-CP made a CFG portion dead, removing a loop.
The patch also makes the bogus loop removal detection unconditional as gengtype doesn't seem to be able to handle preprocessor conditional fields. Bootstrap and regtest pending on x86_64-unknown-linux-gnu. 2014-09-08 Richard Biener <rguent...@suse.de> PR ipa/63196 * cfgloop.c (mark_loop_for_removal): Track former header unconditionally. * cfgloop.h (struct loop): Add former_header member unconditionally. * loop-init.c (fix_loop_structure): Enable bogus loop removal diagnostic unconditionally. * tree-inline.c (copy_loops): The source loop header should always be non-NULL. (tree_function_versioning): If loops need fixup after removing unreachable blocks fix them. Index: gcc/cfgloop.c =================================================================== --- gcc/cfgloop.c (revision 215008) +++ gcc/cfgloop.c (working copy) @@ -1927,9 +1937,7 @@ bb_loop_depth (const_basic_block bb) void mark_loop_for_removal (loop_p loop) { -#ifdef ENABLE_CHECKING loop->former_header = loop->header; -#endif loop->header = NULL; loop->latch = NULL; loops_state_set (LOOPS_NEED_FIXUP); Index: gcc/cfgloop.h =================================================================== --- gcc/cfgloop.h (revision 215008) +++ gcc/cfgloop.h (working copy) @@ -194,13 +194,11 @@ struct GTY ((chain_next ("%h.next"))) lo /* Number of iteration analysis data for RTL. */ struct niter_desc *simple_loop_desc; -#ifdef ENABLE_CHECKING /* For sanity checking during loop fixup we record here the former loop header for loops marked for removal. Note that this prevents the basic-block from being collected but its index can still be reused. */ basic_block former_header; -#endif }; /* Flags for state of loop structure. */ Index: gcc/loop-init.c =================================================================== --- gcc/loop-init.c (revision 215008) +++ gcc/loop-init.c (working copy) @@ -245,12 +245,10 @@ fix_loop_structure (bitmap changed_bbs) } /* Remove the loop. */ -#ifdef ENABLE_CHECKING if (loop->header) loop->former_header = loop->header; else gcc_assert (loop->former_header != NULL); -#endif loop->header = NULL; flow_loop_tree_node_remove (loop); } @@ -278,7 +276,6 @@ fix_loop_structure (bitmap changed_bbs) FOR_EACH_VEC_ELT (*get_loops (cfun), i, loop) if (loop && loop->header == NULL) { -#ifdef ENABLE_CHECKING if (dump_file && ((unsigned) loop->former_header->index < basic_block_info_for_fn (cfun)->length ())) @@ -306,7 +303,6 @@ fix_loop_structure (bitmap changed_bbs) former_header->loop_father->header->index); } } -#endif (*get_loops (cfun))[i] = NULL; flow_loop_free (loop); } Index: gcc/tree-inline.c =================================================================== --- gcc/tree-inline.c (revision 215008) +++ gcc/tree-inline.c (working copy) @@ -2376,11 +2376,8 @@ copy_loops (copy_body_data *id, /* Assign the new loop its header and latch and associate those with the new loop. */ - if (src_loop->header != NULL) - { - dest_loop->header = (basic_block)src_loop->header->aux; - dest_loop->header->loop_father = dest_loop; - } + dest_loop->header = (basic_block)src_loop->header->aux; + dest_loop->header->loop_father = dest_loop; if (src_loop->latch != NULL) { dest_loop->latch = (basic_block)src_loop->latch->aux; @@ -5536,6 +5533,11 @@ tree_function_versioning (tree old_decl, delete_unreachable_blocks_update_callgraph (&id); if (id.dst_node->definition) cgraph_edge::rebuild_references (); + if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) + { + calculate_dominance_info (CDI_DOMINATORS); + fix_loop_structure (NULL); + } update_ssa (TODO_update_ssa); /* After partial cloning we need to rescale frequencies, so they are