https://gcc.gnu.org/g:365e5618bc6fcb62560450677e0fe4f5ba96345e

commit r17-705-g365e5618bc6fcb62560450677e0fe4f5ba96345e
Author: Raven Hallsby <[email protected]>
Date:   Sat May 23 21:09:16 2026 -0500

    match: Optimize `(~y & x) ^ y` into (y | x) [PR125104]
    
    Despite a similar rule existing earlier in match.pd, this simplify
    rule is needed because the front-end (before pass 006.original)
    performs trivial constant optimizations, such as ~1 -> -2 on
    integers (at least those defined as `int`).
    
            PR tree-optimization/125104
    
    gcc/ChangeLog:
    
            * match.pd (`(~y & x) ^ y`): New Pattern.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/pr125104.c: New test.

Diff:
---
 gcc/match.pd                             | 21 +++++++++++++--------
 gcc/testsuite/gcc.dg/tree-ssa/pr125104.c | 13 +++++++++++++
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index b3ddd5158287..d7704e78851d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2358,14 +2358,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
  (simplify
   (bitop:c (rbitop:c @0 @1) @0)
   @0)
- /* (~x | y) & x -> x & y */
- /* (~x & y) | x -> x | y */
- (simplify
-  (bitop:c (rbitop:c @2 @1) @0)
-  (with { bool wascmp; }
-   (if (bitwise_inverted_equal_p (@0, @2, wascmp)
-       && (!wascmp || element_precision (type) == 1))
-    (bitop @0 @1))))
   /* (x | y) & (x & z) -> (x & z) */
   /* (x & y) | (x | z) -> (x | z) */
  (simplify
@@ -2384,6 +2376,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    { build_zero_cst (type); }
    { build_minus_one_cst (type); })))
 
+/* (~x | y) & x -> x & y
+   (~x & y) | x -> x | y
+   (~x & y) ^ x -> x | y */
+(for bitop (bit_and bit_ior bit_xor)
+     rbitop (bit_ior bit_and bit_and)
+     resbitop (bit_and bit_ior bit_ior)
+ (simplify
+  (bitop:c (rbitop:c @2 @1) @0)
+  (with { bool wascmp; }
+   (if (bitwise_inverted_equal_p (@0, @2, wascmp)
+       && (!wascmp || element_precision (type) == 1))
+    (resbitop @0 @1)))))
+
 /* ((x | y) & z) | x -> (z & y) | x
    ((x ^ y) & z) | x -> (z & y) | x  */
 (for op (bit_ior bit_xor)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125104.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr125104.c
new file mode 100644
index 000000000000..7c400dfcce3d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125104.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-gimple-raw -fdump-tree-forwprop1-raw" } */
+/* PR tree-optimization/125104 */
+
+int f(int a, int b)
+{
+  a &= ~1;
+  a ^= 1;
+  return a; // a | 1
+}
+
+/* { dg-final { scan-tree-dump "bit_xor_expr" "gimple" } } */
+/* { dg-final { scan-tree-dump "bit_ior_expr" "forwprop1" } } */

Reply via email to