http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51737
--- Comment #11 from Martin Jambor <jamborm at gcc dot gnu.org> 2012-01-09 22:42:00 UTC --- The problem is much more fundamental than just a clone removal while also walking the clones of the same function although that is the reason why we segfault. But that would be almost easy to solve. The bigger problem is indeed materialization of recursive loads itself: We have a function that calls itself twice and some of these calls and their calls are scheduled to be recursively inlined. When the decisions are to be carried out, we recognize we need to save a copy of the body to copy from somewhere and so we call save_inline_function_body. That function elects a clone to "own" the body copy and calls tree_function_versioning to copy it. And tree_function_versioning calls the problematic delete_unreachable_blocks_update_callgraph which analyzes CFG and finds some BBs unreachable - I'm not quite sure what made them so suddenly unreachable, but it almost certainly has something to do with EH BBs that somehow are stale at that point. And so the function begins to nuke respective call graph edges and also call graph nodes of respective inlined callees and their inlined callees and... and sure enough it decides to delete the node that save_inline_function_body chose to hold the new body, in other words it intends to delete id->dst_node of currently running tree_function_versioning. Thus even if we taught delete_unreachable_blocks_update_callgraph to be more careful about deleted nodes, tree_function_versioning would fail nevertheless. I'm wondering whether we could just skip delete_unreachable_blocks_update_callgraph when tree_function_versioning is called from within save_inline_function_body, though I can imagine the verifier could complain about something. I have to run now, will experiment more tomorrow.