On Thu, 30 Jul 2026, Jakub Jelinek wrote:
> On Wed, Jul 29, 2026 at 05:09:43PM -0700, Andrea Pinski wrote:
> > > --- gcc/match.pd.jj 2026-07-29 17:21:33.893285488 +0200
> > > +++ gcc/match.pd 2026-07-29 17:17:59.855012063 +0200
> > > @@ -5293,7 +5293,11 @@ (define_operator_list SYNC_FETCH_AND_AND
> > > (cmp (bit_and (lshift integer_pow2p@1 @0) integer_pow2p@2)
> > > integer_zerop)
> > > (with { int c1 = wi::clz (wi::to_wide (@1));
> > > int c2 = wi::clz (wi::to_wide (@2)); }
> > > - (if (c1 < c2)
> > > + (if (c1 < c2
> > > + /* If c1 - c2 isn't representable in TREE_TYPE (@0), it is also
> > > + never true, because for any valid x C << x will be smaller
> > > + than D. See PR126476. */
> > > + || c1 - c2 > wi::to_widest (TYPE_MAX_VALUE (TREE_TYPE (@0))))
> >
> > I was worried that TYPE_MAX_VALUE might not be constant but we depend
> > on it being constant in other places.
>
> On a second thought, I think comparison with TYPE_MAX_VALUE is not what
> we want, even for limited range type build_int_cst will happily create
> larger constants.
>
> So, I think we should go with the following instead.
> wi::shwi (c1 - c2, HOST_BITS_PER_INT) will always fit and fits_to_tree_p
> will then check if build_int_cst will work or not.
LGTM.
> 2026-07-30 Jakub Jelinek <[email protected]>
>
> PR tree-optimization/126476
> * match.pd (((C << A) & D) != 0 -> A == 0,
> ((C << A) & D) == 0 -> A != 0): Fold to false/true if
> c1 - c2 resp. c2 - c1 doesn't fit into TREE_TYPE (@0).
>
> * gcc.dg/torture/bitint-103.c: New test.
>
> --- gcc/match.pd.jj 2026-07-30 09:55:49.767353123 +0200
> +++ gcc/match.pd 2026-07-30 10:30:26.284706405 +0200
> @@ -5265,7 +5265,12 @@ (define_operator_list SYNC_FETCH_AND_AND
> (cmp (bit_and (lshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
> (with { int c1 = wi::clz (wi::to_wide (@1));
> int c2 = wi::clz (wi::to_wide (@2)); }
> - (if (c1 < c2)
> + (if (c1 < c2
> + /* If c1 - c2 isn't representable in TREE_TYPE (@0), it is also
> + never true, because for any valid x C << x will be smaller
> + than D. See PR126476. */
> + || !wi::fits_to_tree_p (wi::shwi (c1 - c2, HOST_BITS_PER_INT),
> + TREE_TYPE (@0)))
> { constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
> (icmp @0 { build_int_cst (TREE_TYPE (@0), c1 - c2); }))))
> (simplify
> @@ -5273,7 +5278,9 @@ (define_operator_list SYNC_FETCH_AND_AND
> (if (tree_int_cst_sgn (@1) > 0)
> (with { int c1 = wi::clz (wi::to_wide (@1));
> int c2 = wi::clz (wi::to_wide (@2)); }
> - (if (c1 > c2)
> + (if (c1 > c2
> + || !wi::fits_to_tree_p (wi::shwi (c2 - c1, HOST_BITS_PER_INT),
> + TREE_TYPE (@0)))
> { constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
> (icmp @0 { build_int_cst (TREE_TYPE (@0), c2 - c1); }))))))
>
> --- gcc/testsuite/gcc.dg/torture/bitint-103.c.jj 2026-07-30
> 10:28:31.349777715 +0200
> +++ gcc/testsuite/gcc.dg/torture/bitint-103.c 2026-07-30 10:28:31.349777715
> +0200
> @@ -0,0 +1,22 @@
> +/* PR tree-optimization/126476 */
> +/* { dg-do run { target bitint } } */
> +
> +[[gnu::noipa]] int
> +foo (unsigned _BitInt(4) n)
> +{
> + return ((1ULL << n) & (1ULL << 20)) != 0;
> +}
> +
> +[[gnu::noipa]] int
> +bar (unsigned _BitInt(4) n)
> +{
> + return (((1ULL << 40) >> n) & (1ULL << 20)) != 0;
> +}
> +
> +int
> +main ()
> +{
> + for (unsigned i = 0; i < 16; i++)
> + if (foo (i) != 0 || bar (i) != 0)
> + __builtin_abort ();
> +}
>
>
> Jakub
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)