On Fri, Sep 5, 2025 at 1:50 AM Andrew Pinski <andrew.pin...@oss.qualcomm.com> wrote: > > SRA likes to create VCE<bool>(a) when it comes to bool. This confuses > a few different passes including jump threading and uninitialization > warning. This removes the VCE in one case where it will help. > Values outside of 0/1 with the VCE will produce undefined code so > removing the VCE is always fine as we go from undefined to well defined > and not introduce new undefined code. > > This fix is like what was done for PR 80635 but not depending on the VRP to > do the work so it is fixed at -O1 too. > > Bootstrapped and tested on x86_64-linux-gnu. > > PR tree-optimization/105749 > PR tree-optimization/80635 > > gcc/ChangeLog: > > * match.pd (`VCE<bool>(a) ==\!= 0`): New pattern. > > gcc/testsuite/ChangeLog: > > * g++.dg/warn/pr80635-3.C: New test. > * g++.dg/warn/pr80635-4.C: New test. > > Signed-off-by: Andrew Pinski <andrew.pin...@oss.qualcomm.com> > --- > gcc/match.pd | 10 ++++++ > gcc/testsuite/g++.dg/warn/pr80635-3.C | 47 +++++++++++++++++++++++++++ > gcc/testsuite/g++.dg/warn/pr80635-4.C | 32 ++++++++++++++++++ > 3 files changed, 89 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/warn/pr80635-3.C > create mode 100644 gcc/testsuite/g++.dg/warn/pr80635-4.C > > diff --git a/gcc/match.pd b/gcc/match.pd > index b1d7a3a1b73..954e52d9562 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -2359,6 +2359,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (bit_not (bit_not @0)) > (non_lvalue @0)) > > +/* VCE<bool>(a) ==/!= false -> a ==/!= 0. > + This is done as SRA likes to create VCE for boolean accesses > + and it helps code gneration and uninitialized variable warnings. */
But it loses information? The reverse, VCE<int>(a) with a bool 'a' would gain. So I don't quite understand the idea behind this pattern. Isn't the problem in uninit/jump threading instead? Richard. > +(for neeq (ne eq) > + (simplify > + (neeq (view_convert@0 @1) integer_zerop) > + (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE > + && INTEGRAL_TYPE_P (TREE_TYPE (@1))) > + (neeq @1 { build_zero_cst (TREE_TYPE (@1)); } )))) > + > /* zero_one_valued_p will match when a value is known to be either > 0 or 1 including constants 0 or 1. > Signed 1-bits includes -1 so they cannot match here. */ > diff --git a/gcc/testsuite/g++.dg/warn/pr80635-3.C > b/gcc/testsuite/g++.dg/warn/pr80635-3.C > new file mode 100644 > index 00000000000..64fd78bac5a > --- /dev/null > +++ b/gcc/testsuite/g++.dg/warn/pr80635-3.C > @@ -0,0 +1,47 @@ > +// PR tree-optimization/80635 > +// { dg-do compile { target c++11 } } > +// { dg-options "-O1 -Wmaybe-uninitialized" } > +// This is the same as pr80635-1.C but at -O1 instead of -O2. > + > +using size_t = decltype (sizeof (1)); > +inline void *operator new (size_t, void *p) { return p; } > +template<typename T> > +struct optional > +{ > + optional () : m_dummy (), live (false) {} > + void emplace () { new (&m_item) T (); live = true; } > + ~optional () { if (live) m_item.~T (); } > + > + union > + { > + struct {} m_dummy; > + T m_item; > + }; > + bool live; > +}; > + > +extern int get (); > +extern void set (int); > + > +struct A > +{ > + A () : m (get ()) {} > + ~A () { set (m); } // { dg-bogus "may be used uninitialized in this > function" } > + > + int m; > +}; > + > +struct B > +{ > + B (); > + ~B (); > +}; > + > +void func () > +{ > + optional<A> maybe_a; > + optional<B> maybe_b; > + > + maybe_a.emplace (); > + maybe_b.emplace (); > +} > diff --git a/gcc/testsuite/g++.dg/warn/pr80635-4.C > b/gcc/testsuite/g++.dg/warn/pr80635-4.C > new file mode 100644 > index 00000000000..1f32b9ae034 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/warn/pr80635-4.C > @@ -0,0 +1,32 @@ > +// PR tree-optimization/80635 > +// { dg-do compile { target c++17 } } > +// { dg-options "-O1 -Wmaybe-uninitialized" } > +// This is the same as pr80635-2.C but at -O1 instead of -O2. > + > +#include <optional> > + > +extern int get (); > +extern void set (int); > + > +struct A > +{ > + A () : m (get ()) {} > + ~A () { set (m); } // { dg-bogus "may be used uninitialized in this > function" } > + > + int m; > +}; > + > +struct B > +{ > + B (); > + ~B (); > +}; > + > +void func () > +{ > + std::optional<A> maybe_a; > + std::optional<B> maybe_b; > + > + maybe_a.emplace (); > + maybe_b.emplace (); > +} > -- > 2.43.0 >