https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88593
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Alexander Monakov from comment #4) > It seems to avoid this sort of gotchas cleanup_cfg should > > gcc_checking_assert (!dom_info_available_p (CDI_DOMINATORS)); > gcc_checking_assert (!dom_info_available_p (CDI_POST_DOMINATORS)); > > but maybe there's a deeper reason it's not done already — I cannot be sure. It already does it in a not always executed path: /* ??? We probably do this way too often. */ if (current_loops && (changed || (mode & CLEANUP_CFG_CHANGED))) { timevar_push (TV_REPAIR_LOOPS); /* The above doesn't preserve dominance info if available. */ gcc_assert (!dom_info_available_p (CDI_DOMINATORS)); calculate_dominance_info (CDI_DOMINATORS); hardening this contract might be a good idea but expect some fallout. I think the correct mode-switching local fix is to do diff --git a/gcc/mode-switching.c b/gcc/mode-switching.c index ef6f6e1984c..2ff21a40081 100644 --- a/gcc/mode-switching.c +++ b/gcc/mode-switching.c @@ -856,7 +856,10 @@ optimize_mode_switching (void) commit_edge_insertions (); if (targetm.mode_switching.entry && targetm.mode_switching.exit) - cleanup_cfg (CLEANUP_NO_INSN_DEL); + { + free_dominance_info (CDI_DOMINATORS); + cleanup_cfg (CLEANUP_NO_INSN_DEL); + } else if (!need_commit && !emitted) return 0;