https://gcc.gnu.org/g:5193b9d250a8ecec669a87708a1a98abae94130f

commit r16-4219-g5193b9d250a8ecec669a87708a1a98abae94130f
Author: Matteo Nicoli <[email protected]>
Date:   Sat Oct 4 09:22:54 2025 -0600

    [PATCH][PR tree-optimization/117760] `a != b` implies that a or b is also 
non-zero
    
    Implements a match.pd pattern to optimize the cases found in PR 117760.
    
            PR tree-optimization/117760
    gcc/
            * match.pd: Add simplifications that exploit implied values after
            logical tests.
    
    gcc/testsuite
            * gcc.dg/int-bwise-opt-1.c: New test.
            * gcc.dg/int-bwise-opt-2.c: New test.

Diff:
---
 gcc/match.pd                           | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/int-bwise-opt-1.c | 31 +++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/int-bwise-opt-2.c | 15 +++++++++++++++
 3 files changed, 74 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index b3fd26e18ddd..6f896aa7961c 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6808,6 +6808,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    @2))
 )
 
+#if GIMPLE
+/* Given two integers a and b:
+   (a != b) & ((a|b) != 0) -> (a != b)
+   (a != b) | ((a|b) != 0) -> ((a|b) != 0)
+   (a == b) & ((a|b) == 0) -> ((a|b) == 0)
+   (a == b) | ((a|b) == 0) -> (a == b)
+   (a != b) & ((a|b) == 0) -> false
+   (a == b) | ((a|b) != 0) -> true  */
+(simplify
+ (bit_and:c (ne:c @0 @1) (ne (bit_ior @0 @1) integer_zerop))
+ (ne @0 @1))
+(simplify
+ (bit_ior:c (ne:c @0 @1) (ne (bit_ior @0 @1) integer_zerop))
+ (ne (bit_ior @0 @1) { integer_zero_node; }))
+(simplify
+ (bit_and:c (eq:c @0 @1) (eq (bit_ior @0 @1) integer_zerop))
+ (eq (bit_ior @0 @1) { integer_zero_node; }))
+(simplify
+ (bit_ior:c (eq:c @0 @1) (eq (bit_ior @0 @1) integer_zerop))
+ (eq @0 @1))
+(simplify
+ (bit_and:c (ne:c @0 @1) (eq (bit_ior @0 @1) integer_zerop))
+ { build_zero_cst (type); })
+(simplify
+ (bit_ior:c (eq:c @0 @1) (ne (bit_ior @0 @1) integer_zerop))
+ { build_one_cst (type); })
+#endif
+
 /* These was part of minmax phiopt.  */
 /* Optimize (a CMP b) ? minmax<a, c> : minmax<b, c>
    to minmax<min/max<a, b>, c> */
diff --git a/gcc/testsuite/gcc.dg/int-bwise-opt-1.c 
b/gcc/testsuite/gcc.dg/int-bwise-opt-1.c
new file mode 100644
index 000000000000..11ea9acb3fc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/int-bwise-opt-1.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int f1(int a, int b)
+{
+  return (a != b) & ((a | b) != 0);
+}
+
+int f2(int a, int b)
+{
+  return (a == b) | ((a | b) == 0);
+}
+
+int f3(int a, int b)
+{
+  return (a != b) & ((a | b) == 0);
+}
+
+int f4(int a, int b)
+{
+  return (a == b) | ((a | b) != 0);
+}
+
+/* { dg-final { scan-tree-dump-times "\\\|" 0 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\&" 0 "optimized" } } */
+
+/* f3 should fold to `1` (true).  */
+/* { dg-final { scan-tree-dump-times "return 1;" 1 "optimized" } } */
+
+/* f4 should fold to `0` (false).  */
+/* { dg-final { scan-tree-dump-times "return 0;" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/int-bwise-opt-2.c 
b/gcc/testsuite/gcc.dg/int-bwise-opt-2.c
new file mode 100644
index 000000000000..cc1a48b061a2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/int-bwise-opt-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int f1(int a, int b)
+{
+  return (a != b) | ((a | b) != 0);
+}
+
+int f2(int a, int b)
+{
+  return (a == b) & ((a | b) == 0);
+}
+
+ /* { dg-final { scan-tree-dump-times "a == b" 0 "optimized" } } */
+ /* { dg-final { scan-tree-dump-times "a != b" 0 "optimized" } } */

Reply via email to