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
>

Reply via email to