https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61607
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- With the propagation limitation removed we get Registering jump thread: (2, 4) incoming edge; (4, 5) joiner; (5, 7) normal; Cancelling jump thread: (2, 4) incoming edge; (4, 5) joiner; (5, 7) normal; Jump threading proved probability of edge 7->9 too small (it is 3900, should be 5000). Threaded jump 5 --> 7 to 10 fix_loop_structure: removing loop 1 flow_loops_find: discovered new loop 2 with header 4 <bb 5>: # inter0p_13 = PHI <inter0p_2(4)> # inter1p_14 = PHI <inter0p_2(4)> if (inter0p_2 != 0) goto <bb 6>; else goto <bb 10>; <bb 6>: inter[0] = 1; <bb 7>: if (inter0p_2 != 0) goto <bb 8>; else goto <bb 9>; <bb 8>: inter[1] = 1; <bb 9>: foo (&inter); inter ={v} {CLOBBER}; return; <bb 10>: goto <bb 9>; that still misses the threading of the true path. And it still destroys loop info from: static bool thread_block_1 (basic_block bb, bool noloop_only, bool joiners) { ... /* If we thread the latch of the loop to its exit, the loop ceases to exist. Make sure we do not restrict ourselves in order to preserve this loop. */ if (loop->header == bb) { e = loop_latch_edge (loop); vec<jump_thread_edge *> *path = THREAD_PATH (e); if (path && (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && joiners) || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && !joiners))) { for (unsigned int i = 1; i < path->length (); i++) { edge e2 = (*path)[i]->e; if (loop_exit_edge_p (loop, e2)) { loop->header = NULL; loop->latch = NULL; loops_state_set (LOOPS_NEED_FIXUP); but it seems we cancel the threading later... (gdb) 913 delete_jump_thread_path (path); so it would be better if we destroyed the loop only if necessary (I would have expected the actual edge redirection code takes care of that). Cancelling loops unnecessarily is very bad.