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
>
>

Reply via email to