On Tue, May 12, 2026 at 11:38 PM Richard Biener
<[email protected]> wrote:
>
> 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?

Yes I agree it belongs in a different place from the current
placement. In fact I think it should not happen until after vrp1.
I will look into moving it tomorrow as the first step. Though since
this is a regression so the big question is what do we do for GCC 16
branch?

Thanks,
Andrew

>
> > 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
> >

Reply via email to