https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87468
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Slightly cleaned up testcase: int a; int bar (void); void baz (void); void foo (void) { for (int c = 1; c <= 3;) { int d = bar () && !0; switch (c) case 1: if (d) case 2: case 3: baz (); if (a) c++; } } The problem is that EDGE_IGNORE is not being cleared when it should anymore. It is set during vr_values::simplify_switch_using_ranges, then checked in inside of thread_outgoing_edges, but later on thread_through_all_blocks eventually calls create_block_for_threading -> duplicate_block and that creates new edges using the flags of the old succs edges. While the original edges that had EDGE_IGNORE set are in to_remove_edges vector and thus don't leak into the IL afterwards, the copies of them created by duplicate_block are not and leak into the IL, violating /* An edge we should ignore. It should be entirely local to passes. ie, it is never set on any edge upon the completion of any pass. */ DEF_EDGE_FLAG(IGNORE, 17) requirement. So, either we need some vr-values.c method that will clear EDGE_IGNORE flags on to_remove_edge edges and call it before we start duplicating any blocks, or something else went wrong (maybe we shouldn't duplicate_blocks that have such edges?).