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" } } */
