https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64284
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Sth like Index: tree-ssa-threadupdate.c =================================================================== --- tree-ssa-threadupdate.c (revision 218621) +++ tree-ssa-threadupdate.c (working copy) @@ -2364,7 +2364,7 @@ duplicate_seme_region (edge entry, edge basic_block *region_copy) { unsigned i; - bool free_region_copy = false, copying_header = false; + bool free_region_copy = false; struct loop *loop = entry->dest->loop_father; edge exit_copy; edge redirected; @@ -2388,10 +2388,7 @@ duplicate_seme_region (edge entry, edge initialize_original_copy_tables (); - if (copying_header) - set_loop_copy (loop, loop_outer (loop)); - else - set_loop_copy (loop, loop); + set_loop_copy (loop, loop); if (!region_copy) { @@ -2453,6 +2450,8 @@ duplicate_seme_region (edge entry, edge } /* Redirect the entry and add the phi node arguments. */ + if (entry->dest == loop->header) + mark_loop_for_removal (loop); redirected = redirect_edge_and_branch (entry, get_bb_copy (entry->dest)); gcc_assert (redirected != NULL); flush_pending_stmts (entry); "works" but results in the less than optimal fix_loop_structure: fixing up loops for function fix_loop_structure: removing loop 1 flow_loops_find: discovered new loop 2 with header 5 in the testcase the loop header will be entry->src it seems - not sure how reliably that is in the full generality of duplicate_seme_region. We know that all blocks are contained in the same loop, so it must be possible to compute where the header goes. Ideally we'd simply set loop->header and loop->latch to the correct values, marking loops for fixup (to recompute BB ownership - or do even that ourselves). The testcase has two latches later, thus loop->latch would be NULL, but both VRP and DOM init loops without LOOPS_MAY_HAVE_MULTIPLE_LATCHES so we'd have to disambiguate the loops. That said - the above patch works.