https://gcc.gnu.org/g:43356828d897ad96c5359e03f8f4aad2c283b81f

commit r17-1683-g43356828d897ad96c5359e03f8f4aad2c283b81f
Author: Kael Andrew Franco <[email protected]>
Date:   Thu Jun 18 21:00:44 2026 -0600

    [PATCH] match: Optimize bit_ior/bit_and {bit_not} rshift to min/max 
[PR125641]
    
    Fold x | (x >> (TYPE_PRECISION (type) - 1)) to max (x, -1)
    Fold x | (~ (x >> (TYPE_PRECISION (type) - 1))) to min (x, -1)
    Fold x & (x >> (TYPE_PRECISION (type) - 1)) to min (x, 0)
    Fold x & (~ (x >> (TYPE_PRECISION (type) - 1))) to max (x, 0)
    
    Bootstrapped and tested on x86_64-pc-linux-gnu
    
            PR tree-optimization/125641
    
    gcc/ChangeLog:
    
            PR tree-optimization/125641
            * match.pd: Add bit_ior/bit_and {bit_not} rshift to min/max.
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/125641
            * gcc.dg/pr125641.c: New test.

Diff:
---
 gcc/match.pd                    | 23 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr125641.c | 42 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+)

diff --git a/gcc/match.pd b/gcc/match.pd
index fdc2cf88e906..8c410c2f3b34 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5091,6 +5091,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         (op @0 { build_int_cst (TREE_TYPE (@1), prec - 1); })))
       (op @0 { build_int_cst (TREE_TYPE (@1), low); })))))))
 
+/* Fold x | (x >> (TYPE_PRECISION (type) - 1)) to max (x, -1)
+   Fold x | (~ (x >> (TYPE_PRECISION (type) - 1))) to min (x, -1)
+   Fold x & (x >> (TYPE_PRECISION (type) - 1)) to min (x, 0)
+   Fold x & (~ (x >> (TYPE_PRECISION (type) - 1))) to max (x, 0)
+*/
+#ifdef GIMPLE
+(for bitop (bit_ior bit_and)
+     result (max min)
+     rresult (min max)
+ (simplify
+  (bitop:c @0 (rshift @0 INTEGER_CST@1))
+  (if (INTEGRAL_TYPE_P (type)
+       && !TYPE_UNSIGNED (type)
+       && wi::eq_p (wi::to_wide (@1), TYPE_PRECISION (type) - 1))
+   (result @0 { build_int_cst (type, bitop == BIT_IOR_EXPR ? -1 : 0); })))
+ (simplify
+  (bitop:c @0 (bit_not (rshift @0 INTEGER_CST@1)))
+  (if (INTEGRAL_TYPE_P (type)
+       && !TYPE_UNSIGNED (type)
+       && wi::eq_p (wi::to_wide (@1), TYPE_PRECISION (type) - 1))
+   (rresult @0 { build_int_cst (type, bitop == BIT_IOR_EXPR ? -1 : 0); }))))
+#endif
+
 /* Fold `1 >> a` into `a == 0` for scalar integral types. */
 (simplify
  (rshift integer_onep @2)
diff --git a/gcc/testsuite/gcc.dg/pr125641.c b/gcc/testsuite/gcc.dg/pr125641.c
new file mode 100644
index 000000000000..4a1e240e8e1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr125641.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+static int int_prec = sizeof (int) * __CHAR_BIT__ - 1;
+
+int
+max_i32 (int x, int k)
+{
+  return x < k ? k : x;
+}
+
+int
+min_i32 (int x, int k)
+{
+  return x > k ? k : x;
+}
+
+_Bool
+x_bit_ior_rshift_x (int x)
+{
+  return (x | (x >> int_prec)) == max_i32 (x, -1);
+}
+
+_Bool
+x_bit_ior_bit_not_rshift_x (int x)
+{
+  return (x | ~(x >> int_prec)) == min_i32 (x, -1);
+}
+
+_Bool
+x_bit_and_rshift_x (int x)
+{
+  return (x & (x >> int_prec)) == min_i32 (x, 0);
+}
+
+_Bool
+x_bit_and_bit_not_rshift_x (int x)
+{
+  return (x & ~(x >> int_prec)) == max_i32 (x, 0);
+}
+
+/* { dg-final { scan-tree-dump-times "return 1;" 4 "optimized" } } */

Reply via email to