This patch does just $subject, leaving the sanity checking under ENABLE_CHECKING for 2/2.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2014-09-05 Richard Biener <rguent...@suse.de> * cfgloop.c (mark_loop_for_removal): New function. * cfgloop.h (mark_loop_for_removal): Declare. * cfghooks.c (delete_basic_block): Use mark_loop_for_removal. (merge_blocks): Likewise. (duplicate_block): Likewise. * except.c (sjlj_emit_dispatch_table): Likewise. * tree-eh.c (cleanup_empty_eh_merge_phis): Likewise. * tree-ssa-threadupdate.c (ssa_redirect_edges): Likewise. (thread_through_loop_header): Likewise. Index: trunk/gcc/cfghooks.c =================================================================== *** trunk.orig/gcc/cfghooks.c 2014-09-05 10:13:28.713737197 +0200 --- trunk/gcc/cfghooks.c 2014-09-05 10:14:27.537733147 +0200 *************** delete_basic_block (basic_block bb) *** 569,582 **** struct loop *loop = bb->loop_father; /* If we remove the header or the latch of a loop, mark the loop for ! removal by setting its header and latch to NULL. */ if (loop->latch == bb || loop->header == bb) ! { ! loop->header = NULL; ! loop->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP); ! } remove_bb_from_loops (bb); } --- 569,578 ---- struct loop *loop = bb->loop_father; /* If we remove the header or the latch of a loop, mark the loop for ! removal. */ if (loop->latch == bb || loop->header == bb) ! mark_loop_for_removal (loop); remove_bb_from_loops (bb); } *************** merge_blocks (basic_block a, basic_block *** 760,770 **** /* ... we merge two loop headers, in which case we kill the inner loop. */ if (b->loop_father->header == b) ! { ! b->loop_father->header = NULL; ! b->loop_father->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP); ! } } /* If we merge a loop header into its predecessor, update the loop structure. */ --- 756,762 ---- /* ... we merge two loop headers, in which case we kill the inner loop. */ if (b->loop_father->header == b) ! mark_loop_for_removal (b->loop_father); } /* If we merge a loop header into its predecessor, update the loop structure. */ *************** duplicate_block (basic_block bb, edge e, *** 1099,1107 **** && cloop->header == bb) { add_bb_to_loop (new_bb, loop_outer (cloop)); ! cloop->header = NULL; ! cloop->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP); } else { --- 1091,1097 ---- && cloop->header == bb) { add_bb_to_loop (new_bb, loop_outer (cloop)); ! mark_loop_for_removal (cloop); } else { Index: trunk/gcc/cfgloop.c =================================================================== *** trunk.orig/gcc/cfgloop.c 2014-09-05 10:13:28.713737197 +0200 --- trunk/gcc/cfgloop.c 2014-09-05 10:14:35.787732579 +0200 *************** bb_loop_depth (const_basic_block bb) *** 1931,1933 **** --- 1931,1943 ---- { return bb->loop_father ? loop_depth (bb->loop_father) : 0; } + + /* Marks LOOP for removal and sets LOOPS_NEED_FIXUP. */ + + void + mark_loop_for_removal (loop_p loop) + { + loop->header = NULL; + loop->latch = NULL; + loops_state_set (LOOPS_NEED_FIXUP); + } Index: trunk/gcc/cfgloop.h =================================================================== *** trunk.orig/gcc/cfgloop.h 2014-09-05 10:13:28.713737197 +0200 --- trunk/gcc/cfgloop.h 2014-09-05 10:14:27.537733147 +0200 *************** struct loop * loop_version (struct loop *** 336,341 **** --- 336,343 ---- extern bool remove_path (edge); extern void unloop (struct loop *, bool *, bitmap); extern void scale_loop_frequencies (struct loop *, int, int); + void mark_loop_for_removal (loop_p); + /* Induction variable analysis. */ Index: trunk/gcc/except.c =================================================================== *** trunk.orig/gcc/except.c 2014-09-05 10:13:28.713737197 +0200 --- trunk/gcc/except.c 2014-09-05 10:14:27.538733147 +0200 *************** sjlj_emit_dispatch_table (rtx_code_label *** 1375,1384 **** { for (loop = bb->loop_father; loop_outer (loop); loop = loop_outer (loop)) ! { ! loop->header = NULL; ! loop->latch = NULL; ! } } } --- 1375,1381 ---- { for (loop = bb->loop_father; loop_outer (loop); loop = loop_outer (loop)) ! mark_loop_for_removal (loop); } } Index: trunk/gcc/tree-eh.c =================================================================== *** trunk.orig/gcc/tree-eh.c 2014-09-05 10:13:28.713737197 +0200 --- trunk/gcc/tree-eh.c 2014-09-05 10:14:27.539733147 +0200 *************** cleanup_empty_eh_merge_phis (basic_block *** 4171,4180 **** and mark the other loop as possibly having multiple latches. */ if (e->dest == e->dest->loop_father->header) { ! e->dest->loop_father->header = NULL; ! e->dest->loop_father->latch = NULL; new_bb->loop_father->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP|LOOPS_MAY_HAVE_MULTIPLE_LATCHES); } redirect_eh_edge_1 (e, new_bb, change_region); redirect_edge_succ (e, new_bb); --- 4171,4179 ---- and mark the other loop as possibly having multiple latches. */ if (e->dest == e->dest->loop_father->header) { ! mark_loop_for_removal (e->dest->loop_father); new_bb->loop_father->latch = NULL; ! loops_state_set (LOOPS_MAY_HAVE_MULTIPLE_LATCHES); } redirect_eh_edge_1 (e, new_bb, change_region); redirect_edge_succ (e, new_bb); Index: trunk/gcc/tree-ssa-threadupdate.c =================================================================== *** trunk.orig/gcc/tree-ssa-threadupdate.c 2014-09-05 10:13:28.713737197 +0200 --- trunk/gcc/tree-ssa-threadupdate.c 2014-09-05 10:14:27.540733147 +0200 *************** ssa_redirect_edges (struct redirection_d *** 766,776 **** /* If we redirect a loop latch edge cancel its loop. */ if (e->src == e->src->loop_father->latch) ! { ! e->src->loop_father->header = NULL; ! e->src->loop_father->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP); ! } /* Redirect the incoming edge (possibly to the joiner block) to the appropriate duplicate block. */ --- 766,772 ---- /* If we redirect a loop latch edge cancel its loop. */ if (e->src == e->src->loop_father->latch) ! mark_loop_for_removal (e->src->loop_father); /* Redirect the incoming edge (possibly to the joiner block) to the appropriate duplicate block. */ *************** thread_through_loop_header (struct loop *** 1304,1312 **** { /* If the loop ceased to exist, mark it as such, and thread through its original header. */ ! loop->header = NULL; ! loop->latch = NULL; ! loops_state_set (LOOPS_NEED_FIXUP); return thread_block (header, false); } --- 1300,1306 ---- { /* If the loop ceased to exist, mark it as such, and thread through its original header. */ ! mark_loop_for_removal (loop); return thread_block (header, false); }