https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68625
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- So the copyprop iteration figures out half of the function is unreachable and thus registers a copy from a value defined in a region that is also dead (but we figure that out only during substitution and folding via a match.pd pattern looking at defs). Then cfgcleanup comes along and processes BBs in random order, removing the wrong unreachable region (with the def we propagated) first and then another unreachable region part where a basic-block merging opportunity then causes the propagated but removed def being a source for propagating out a PHI ... One fix is to _not_ do remove_edge_and_dominated_blocks in CFG cleanup but only remove edges and remove unreachable blocks later (which causes more work of course). Or trying to paper over the issue by checking for released SSA names (propagating them out anyway) or delaying SSA name release via registering them for SSA update. CFG cleanup ordering patch: Index: gcc/tree-cfgcleanup.c =================================================================== --- gcc/tree-cfgcleanup.c (revision 231101) +++ gcc/tree-cfgcleanup.c (working copy) @@ -67,7 +67,7 @@ remove_fallthru_edge (vec<edge, va_gc> * if (e->flags & EDGE_COMPLEX) e->flags &= ~EDGE_FALLTHRU; else - remove_edge_and_dominated_blocks (e); + remove_edge (e); return true; } return false; @@ -134,7 +134,7 @@ cleanup_control_expr_graph (basic_block taken_edge->probability += e->probability; taken_edge->count += e->count; - remove_edge_and_dominated_blocks (e); + remove_edge (e); retval = true; } else @@ -218,7 +218,7 @@ cleanup_control_flow_bb (basic_block bb) for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); ) { if (e->dest != target_block) - remove_edge_and_dominated_blocks (e); + remove_edge (e); else { /* Turn off the EDGE_ABNORMAL flag. */ @@ -717,7 +717,13 @@ cleanup_tree_cfg_noloop (void) changed = false; } - changed |= cleanup_tree_cfg_1 (); + if (cleanup_tree_cfg_1 ()) + { + changed = true; + delete_unreachable_blocks (); + free_dominance_info (CDI_DOMINATORS); + calculate_dominance_info (CDI_DOMINATORS); + } gcc_assert (dom_info_available_p (CDI_DOMINATORS)); compact_blocks (); "Hack" to detect the situation and not ICE (could also be applied to may_propagate_copy) Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c (revision 231101) +++ gcc/tree-cfg.c (working copy) @@ -1865,6 +1865,8 @@ gimple_merge_blocks (basic_block a, basi tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0); gimple *copy; bool may_replace_uses = (virtual_operand_p (def) + || (TREE_CODE (use) == SSA_NAME + && SSA_NAME_IN_FREE_LIST (use)) || may_propagate_copy (def, use)); /* In case we maintain loop closed ssa form, do not propagate arguments