https://gcc.gnu.org/g:2f7edefc54e6967168c3cce3a4347cc0bc6a8155

commit r16-4669-g2f7edefc54e6967168c3cce3a4347cc0bc6a8155
Author: Andrew Pinski <[email protected]>
Date:   Sun Oct 5 22:39:35 2025 -0700

    [PATCH] match: simplify `VCE<bool>({0,1}) ==/!= 0` to `{0,1} ==/!= 0` 
[PR105749]
    
    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 and when it
    is known not to have any undefined behavior since the ranges of a is known
    to be 0/1.
    
    This implements similar was done for PR 80635 but without VRP's help; ccp
    provides enough on the range/non-zeroness to implement this in match.
    
    This will fix many of the std::optional reported warnings at -O1 too.
    pr80635-[34].C are the same as pr80635-[12].C but compiled at -O1 rather
    than just -O2.
    
            PR tree-optimization/105749
            PR tree-optimization/80635
    
    gcc/ChangeLog:
    
            * match.pd (`VCE<bool>(zero_one_valued_p) ==\!= 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 <[email protected]>

Diff:
---
 gcc/match.pd                          | 11 +++++++++
 gcc/testsuite/g++.dg/warn/pr80635-3.C | 46 +++++++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/warn/pr80635-4.C | 31 +++++++++++++++++++++++
 3 files changed, 88 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index b37a43713360..eff70ad9bb4f 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2429,6 +2429,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
          || TYPE_PRECISION (type) > 1)
       && wi::leu_p (tree_nonzero_bits (@1), 1))))
 
+/* VCE<bool>(zero_one) ==/!= false -> zero_one ==/!= 0.
+   This is done as SRA likes to create VCE for boolean accesses
+   and it helps code gneration and uninitialized variable warnings.  */
+(for neeq (ne eq)
+ (simplify
+  (neeq (view_convert@0 zero_one_valued_p@1) integer_zerop)
+  (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE
+       && TYPE_PRECISION (TREE_TYPE (@0)) == 1
+       && TYPE_UNSIGNED (TREE_TYPE (@0)))
+   (neeq @1 { build_zero_cst (TREE_TYPE (@1)); } ))))
+
 /* Transform { 0 or 1 } * { 0 or 1 } into { 0 or 1 } & { 0 or 1 }.  */
 (simplify
  (mult zero_one_valued_p@0 zero_one_valued_p@1)
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 000000000000..09fd6ee33920
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr80635-3.C
@@ -0,0 +1,46 @@
+// PR tree-optimization/80635
+// { dg-do compile { target c++11 } }
+// { dg-options "-O1 -Wmaybe-uninitialized" }
+
+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 000000000000..7b3bf8876e00
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr80635-4.C
@@ -0,0 +1,31 @@
+// PR tree-optimization/80635
+// { dg-do compile { target c++17 } }
+// { dg-options "-O1 -Wmaybe-uninitialized" }
+
+#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 ();
+}

Reply via email to