On Wed, Jul 1, 2026 at 10:22 AM Kael Andrew Franco
<[email protected]> wrote:
>
> From 05879b4239bcb970acfb5c5afe22ef7ebd5cf084 Mon Sep 17 00:00:00 2001
> From: Kael Andrew Alonzo Franco <[email protected]>
> Date: Wed, 1 Jul 2026 07:10:38 -0400
> Subject: [PATCH] match: If a in (0,1), `1 << a` to `a + 1` and `2 >> a` to `2
> - a`. [PR126029]
>
> a + 1 is more common than 1 << a.
> 2 - a allows more reassoc optimizations like (2 >> a) - 1 to a == 0.
>
> Bootstrapped and tested on x86_64-pc-linux-gnu.
>
> PR tree-optimization/126029
>
> gcc/ChangeLog:
>
> PR tree-optimization/126029
> * match.pd: If a in (0,1), `1 << a` to `a + 1` and `2 >> a` to `2 - a`.
>
> gcc/testsuite/ChangeLog:
>
> PR tree-optimization/126029
> * gcc.dg/pr126029-1.c: New test.
>
> Signed-off-by: Kael Franco <[email protected]>
> ---
> gcc/match.pd | 13 +++++++++++++
> gcc/testsuite/gcc.dg/pr126029-1.c | 16 ++++++++++++++++
> 2 files changed, 29 insertions(+)
> create mode 100644 gcc/testsuite/gcc.dg/pr126029-1.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index ddf3b61638c..4e8b3044594 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -5137,12 +5137,25 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (rresult @0 { build_int_cst (type, bitop == BIT_IOR_EXPR ? -1 : 0); }))))
> #endif
>
> +/* Fold `2 >> a` into 2 - a for scalar integral types if a is in (0,1). */
> +(simplify
> + (rshift INTEGER_CST@1 zero_one_valued_p@0)
> + (if (INTEGRAL_TYPE_P (type)
> + && wi::eq_p (wi::to_wide (@1), 2))
&& wi::to_wide (@1) == 2
> + (minus { build_int_cst (type, 2); } (convert:type @0))))
Just reuse @1 here.
> +
> /* Fold `1 >> a` into `a == 0` for scalar integral types. */
> (simplify
> (rshift integer_onep @2)
> (if (INTEGRAL_TYPE_P (type))
> (convert (eq:boolean_type_node @2 { build_zero_cst (TREE_TYPE (@2)); }))))
>
> +/* Fold `1 << a` into `a + 1` for scalar integral types if a is in (0,1). */
> +(simplify
> + (lshift integer_onep zero_one_valued_p@2)
> + (if (INTEGRAL_TYPE_P (type))
> + (plus (convert:type @2) { build_one_cst (type); })))
If you capture integer_onep (via @0) you can reuse that instead of
calling build_one_cst.
Also @2 really should be @1. I don't remember why I did @2 in the
pattern above this :).
Thanks,
Andrea
> +
> /* Simplify (CST << x) & 1 to 0 if CST is even or to x == 0 if it is odd. */
> (simplify
> (bit_and (lshift INTEGER_CST@1 @0) integer_onep)
> diff --git a/gcc/testsuite/gcc.dg/pr126029-1.c
> b/gcc/testsuite/gcc.dg/pr126029-1.c
> new file mode 100644
> index 00000000000..354220adebc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr126029-1.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +int
> +one_lshift_a (_Bool a)
> +{
> + return (1 << a) == (a + 1);
> +}
> +
> +int
> +two_rshift_a (_Bool a)
> +{
> + return (2 >> a) == (2 - a);
> +}
> +
> +/* { dg-final { scan-tree-dump-times "return 1;" 2 "optimized" } } */
> --
> 2.54.0
>
>