http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52756
--- Comment #4 from Richard Guenther <rguenth at gcc dot gnu.org> 2012-03-30 13:26:57 UTC --- (In reply to comment #3) > DOM jump threading threads the loop latch edge: > > if (latch->aux) > { > /* First handle the case latch edge is redirected. */ > loop->latch = thread_single_edge (latch); > gcc_assert (single_succ (loop->latch) == tgt_bb); > loop->header = tgt_bb; At this point everything is still ok, but > /* Thread the remaining edges through the former header. */ > thread_block (header, false); this creates a multiple entry loop (with the old entry being an unreachable block after threading - sth cfgcleaup exposes, which in turn would turn that into a valid loop, albeit with bogus header/latch, again). Now, thread_through_loop_header ensures (fingers crossing) that we never create a multiple entry loop. Thus the following fix would work. Index: gcc/tree-ssa-threadupdate.c =================================================================== --- gcc/tree-ssa-threadupdate.c (revision 186007) +++ gcc/tree-ssa-threadupdate.c (working copy) @@ -649,6 +649,17 @@ thread_block (basic_block bb, bool noloo || THREAD_TARGET2 (e)))) continue; + /* thread_through_loop_header made sure we are not creating + a multiple entry loop. If we are creating a new loop + entry the destination will become the new header of the + loop and the old entry will become unreachable. */ + if (e->src->loop_father != e2->dest->loop_father) + { + e2->dest->loop_father->header = e2->dest; + /* Discard knowledge about the latch. */ + e2->dest->loop_father->latch = NULL; + } + if (e->dest == e2->src) update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e), e->count, THREAD_TARGET (e));