https://gcc.gnu.org/g:7b2e9d01d325f091ab7615985f413dda78415fec

commit r16-7367-g7b2e9d01d325f091ab7615985f413dda78415fec
Author: Daniel Barboza <[email protected]>
Date:   Fri Jan 23 13:10:30 2026 -0300

    match.pd: (A | (convert?)(A != 0)) EQ|NE 0 -> A EQ|NE 0 [PR114969]
    
    The NE variant is a gimple pattern that comes from the following C++
    code:
    
    bool result = (std::max(
                      (unsigned long long) 0, (unsigned long long) var_0))
                   | ( var_0 ?  1 : 0);
    
            PR tree-optimization/114969
    
    gcc/ChangeLog:
    
            * match.pd (`(A | (convert?)(A != 0)) EQ|NE 0`): New pattern.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/pr114969.C: New test.

Diff:
---
 gcc/match.pd                    | 10 ++++++++++
 gcc/testsuite/g++.dg/pr114969.C | 16 ++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index f4732d39c517..8910591a04b3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -8368,6 +8368,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        sign extension followed by AND with C will achieve the effect.  */
     (bit_and (convert @0) @1)))))
 
+/* (A | (convert?)(A != 0)) EQ|NE 0 -> A EQ|NE 0 (PR114969)
+
+   The NE variant of this pattern is produced by the C++ code:
+
+   (bool)(std::max (ulong_A, 0) | (ulong_A ? 1 : 0)).  */
+(for cmp (eq ne)
+ (simplify
+  (cmp (bit_ior:c @0 (convert? (ne @0 integer_zerop))) integer_zerop)
+  (cmp @0 { build_zero_cst (TREE_TYPE (@0)); })))
+
 /* When the addresses are not directly of decls compare base and offset.
    This implements some remaining parts of fold_comparison address
    comparisons but still no complete part of it.  Still it is good
diff --git a/gcc/testsuite/g++.dg/pr114969.C b/gcc/testsuite/g++.dg/pr114969.C
new file mode 100644
index 000000000000..4eca335ee426
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr114969.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-O3 -fdump-tree-optimized" }
+
+#include <algorithm>
+
+bool result;
+
+void func (unsigned long long var_0) {
+    result = (std::max ((unsigned long long) 0, (unsigned long long) var_0)) | 
( var_0 ?  1 : 0);
+}
+
+void func2 (unsigned long long var_0) {
+    result = !((std::max ((unsigned long long) 0, (unsigned long long) var_0)) 
| ( var_0 ?  1 : 0));
+}
+
+/* { dg-final { scan-tree-dump-times " \\\| " 0 "optimized" } } */
\ No newline at end of file

Reply via email to