My fix for PR51513 modified group_case_labels_stmt() to remove unreachable case statements labels. Being a middle-end newbie, I incorrectly thought group_case_labels_stmt() was only called very early, before we have a cfg. With -O3, we can generate extra copies of the switch statement, well after the cfg exists, and we end up calling group_case_labels_stmt() to optimize them. In those cases, we need to remove their edges from the cfg.
This passes my bootstrap and regtesting on powerpc64le-linux and x86_64-linux with no regressions. In addition, both David and HJ confirm this fixes the bootstrap issues they ran into. Is this ok for trunk? Peter gcc/ PR middle-end/80707 * tree-cfg.c: Remove cfg edges of unreachable case statements. gcc/testsuite/ * g++.dg/pr80707.C: New test. Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c (revision 247845) +++ gcc/tree-cfg.c (working copy) @@ -1684,6 +1684,10 @@ group_case_labels_stmt (gswitch *stmt) || (EDGE_COUNT (base_bb->succs) == 0 && gimple_seq_unreachable_p (bb_seq (base_bb)))) { + edge e; + if (base_bb != default_bb + && (e = find_edge (gimple_bb (stmt), base_bb)) != NULL) + remove_edge_and_dominated_blocks (e); gimple_switch_set_label (stmt, i, NULL_TREE); i++; new_size--; Index: gcc/testsuite/g++.dg/pr80707.C =================================================================== --- gcc/testsuite/g++.dg/pr80707.C (nonexistent) +++ gcc/testsuite/g++.dg/pr80707.C (working copy) @@ -0,0 +1,29 @@ +// PR middle-end/80707 ICE: extra outgoing edge causes verify_flow_info error. +// { dg-do compile } +// { dg-options "-O3" } */ + +struct A { + int m_fn1(int &) const; +}; +int A::m_fn1(int &p1) const { + int a[6]; + int b = 0; + for (int i;; i++) { + if (a[i]) + break; + b++; + } + while (b) { + int c; + switch (b) { + case 1: + c = 0; + break; + case 5: + c = a[0]; + } + if (c) + p1 = 0; + b--; + } +}