On Fri, Nov 7, 2025 at 1:32 AM Andrew Pinski <[email protected]> wrote: > > When optimize_unreachable was moved from fab to forwprop, I missed that due to > the integrated copy prop, we might end up with an already true branch leading > to a __builtin_unreachable block. optimize_unreachable would switch around > the if and things go down hill from there since the other edge was already > marked as non-executable, forwprop didn't process those blocks and didn't > do copy prop into that block and the original assignment statement was > removed. > > This fixes the problem by having optimize_unreachable not touch the if > statement was already changed to true/false. > > Note I placed the testcase in gcc.c-torture/compile as gcc.dg/torture > is NOT currently testing -Og (see PR 122450 for that). > > Changes since v1: > * v2: Add gimple testcase. > > Bootstrapped and tested on x86_64-linux-gnu.
OK. > PR tree-optimization/122588 > > gcc/ChangeLog: > > * tree-ssa-forwprop.cc (optimize_unreachable): Don't touch > if the condition was already true or false. > > gcc/testsuite/ChangeLog: > > * gcc.c-torture/compile/pr122588-1.c: New test. > * gcc.dg/tree-ssa/pr122588-1.c: New test. > > Signed-off-by: Andrew Pinski <[email protected]> > --- > .../gcc.c-torture/compile/pr122588-1.c | 25 ++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c | 30 +++++++++++++++++++ > gcc/tree-ssa-forwprop.cc | 7 ++++- > 3 files changed, 61 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr122588-1.c > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c > > diff --git a/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c > b/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c > new file mode 100644 > index 00000000000..43ec621512c > --- /dev/null > +++ b/gcc/testsuite/gcc.c-torture/compile/pr122588-1.c > @@ -0,0 +1,25 @@ > +/* Disable warnings about __sync_nand_and_fetch. */ > +/* { dg-options "-w" } */ > +/* PR tree-optimization/122588 */ > + > +int i; > +char c; > + > +static inline __attribute__((__always_inline__)) > +void foo0 (int a) > +{ > +l5: > + __sync_nand_and_fetch (&i, 0); > + int x = __builtin_memcmp_eq (&a, 0, 4); > + if (__builtin_iseqsig (x, 0.)) > + goto l5; > + if (a) > + __builtin_unreachable (); > + c = a; > +} > + > +int > +main () > +{ > + foo0 (1); > +} > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c > new file mode 100644 > index 00000000000..2c214c90576 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr122588-1.c > @@ -0,0 +1,30 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O1 -fgimple" } */ > +/* PR tree-optimization/122588 */ > + > +/* The removal of unreachable blocks should not > + change blocks which have already become true/false. > + The function below was is an example of that. And > + forwprop does not go into non-executable blocks > + so the statement `t = _1;` was still holding the > + old reference. */ > + > +int t; > + > +__GIMPLE(ssa,startwith("forwprop4")) void g(void) > +{ > + int _1; > + __BB(2): > + _1 = 1; > + if (_1 != 0) > + goto __BB3; > + else > + goto __BB4; > + > + __BB(3): > + __builtin_unreachable (); > + > + __BB(4): > + t = _1; > + return; > +} > diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc > index ae7f0e770ba..9f8d4ad3b44 100644 > --- a/gcc/tree-ssa-forwprop.cc > +++ b/gcc/tree-ssa-forwprop.cc > @@ -5080,7 +5080,12 @@ optimize_unreachable (basic_block bb) > stmt = gsi_stmt (gsi); > if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) > { > - if (e->flags & EDGE_TRUE_VALUE) > + /* If the condition is already true/false > + ignore it. This can happen during copy prop of forwprop. */ > + if (gimple_cond_true_p (cond_stmt) > + || gimple_cond_false_p (cond_stmt)) > + continue; > + else if (e->flags & EDGE_TRUE_VALUE) > gimple_cond_make_false (cond_stmt); > else if (e->flags & EDGE_FALSE_VALUE) > gimple_cond_make_true (cond_stmt); > -- > 2.43.0 >
