On Wed, May 13, 2026 at 1:46 AM Andrew Pinski <[email protected]> wrote: > > So the problem here is that group_case_labels_stmt can remove all > cases if they all go directly to a BB just containing > __builtin_unreachable. So we left with a switch which has one label > left; the default case. Code in ifcvt (which is the pass right after > this cleanup happens) is not ready for that case because well it is just > an fallthrough at this point and it should not have to worry about it. > > I have not figured out why this only started to show up recently but > it is definitely a latent bug since group_case_labels_stmt started removing > case labels that go to a BB that contains __builtin_unreachable; > r8-546-gca4d2851687875.
Huh, I didn't expect end_recording_case_labels to affect the CFG. Which is why I'm also worried about this patch ... IMO this belongs to CFG cleanup. I see we're recording case labels only from two places, critical edge splitting, CFG cleanup itself and uninit analysis. Only CFG cleanup should have exposed the need for r8-546, right? So ... can we somehow move this all there? > What this does is if group_case_labels_stmt returns true and we only > have a default case left; remove the switch and change the flow into > a fallthrough. > > There is some slight cleanups in end_recording_case_labels done > with just using continue instead f indention to make it easier > to read on what is going on. > > Bootstrapped and tested on x86_64-linux-gnu. > > PR tree-optimization/125290 > > gcc/ChangeLog: > > * tree-cfg.cc (end_recording_case_labels): Fixup > case for only switch with default case left. > > gcc/testsuite/ChangeLog: > > * gcc.dg/torture/pr125290-1.c: New test. > > Signed-off-by: Andrew Pinski <[email protected]> > --- > gcc/testsuite/gcc.dg/torture/pr125290-1.c | 40 +++++++++++++++++++++++ > gcc/tree-cfg.cc | 20 +++++++++--- > 2 files changed, 56 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/torture/pr125290-1.c > > diff --git a/gcc/testsuite/gcc.dg/torture/pr125290-1.c > b/gcc/testsuite/gcc.dg/torture/pr125290-1.c > new file mode 100644 > index 00000000000..6183cbd2681 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/torture/pr125290-1.c > @@ -0,0 +1,40 @@ > +/* PR tree-optimization/125290 */ > +/* { dg-do compile } */ > + > +int g21; > +int g31, f14f16_c12; > +void f14f16() > +{ > + short v7; > + long v9; > + long v13; > + if (g31) > + { > + g21 = 0; > + switch (v7) > + { > + case 4: > + case 66: break; > + default: __builtin_unreachable(); > + } > + } > + else > + { > + lbl_bf2: > + v9 = g21; > + } > + v13 = v9; > + switch (v13) > + { > + case 55: > + case 2: goto lbl_sw12; > + default: > + if (f14f16_c12) > + goto lbl_bf2; > + else > + return; > + } > +lbl_sw12: > + __builtin_unreachable(); > +} > + > diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc > index b2968c412ed..da6d6b34da8 100644 > --- a/gcc/tree-cfg.cc > +++ b/gcc/tree-cfg.cc > @@ -1271,10 +1271,22 @@ end_recording_case_labels (void) > EXECUTE_IF_SET_IN_BITMAP (touched_switch_bbs, 0, i, bi) > { > basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i); > - if (bb) > - { > - if (gswitch *stmt = safe_dyn_cast <gswitch *> (*gsi_last_bb (bb))) > - group_case_labels_stmt (stmt); > + if (!bb) > + continue; > + gswitch *stmt = safe_dyn_cast <gswitch *> (*gsi_last_bb (bb)); > + if (!stmt) > + continue; > + if (group_case_labels_stmt (stmt) > + && gimple_switch_num_labels (stmt) == 1) > + { > + /* group_case_labels_stmt can remove all > + cases except for the default (via __builtin_unreachable()) > + so fixup that case. */ > + edge taken_edge = single_succ_edge (bb); > + auto gsi = gsi_last_bb (bb); > + gsi_remove (&gsi, true); > + taken_edge->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE); > + taken_edge->flags |= EDGE_FALLTHRU; > } > } > BITMAP_FREE (touched_switch_bbs); > -- > 2.43.0 >
