On 6/9/2026 11:08 AM, Kael Andrew Franco wrote:
>  From 712dd974acd5a972d74e62e8eec902de9c557a26 Mon Sep 17 00:00:00 2001
> From: Kael Andrew Alonzo Franco <[email protected]>
> Date: Tue, 9 Jun 2026 05:59:57 -0400
> Subject: [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.
>
> Signed-off-by: Kael Franco <[email protected]>
> ---
>   gcc/match.pd                    | 23 +++++++++++++++++++
>   gcc/testsuite/gcc.dg/pr125641.c | 40 +++++++++++++++++++++++++++++++++
>   2 files changed, 63 insertions(+)
>   create mode 100644 gcc/testsuite/gcc.dg/pr125641.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index e0d7ef80e14..015a12c6055 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -5043,6 +5043,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 00000000000..690d1c70d1f
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr125641.c
> @@ -0,0 +1,40 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
So the test assumes 32bit integers (via the " >> 31").  It seems like

(sizeof (int) * 8) - 1

Would be better.

Otherwise it looks sensible to me.  I'll ack/push one the testsuite is 
cleaned up.

Jeff

Reply via email to