On Sat, May 16, 2026 at 1:30 AM Jakub Jelinek <[email protected]> wrote:
>
> Hi!
>
> The committed __builtin_bitreverse* patch mishandled the
> bitwise CCP handling, it is true that BUILT_IN_BITREVERSE* can be
> handled there similarly to BUILT_IN_BSWAP*, but not exactly, for
> the latter we need (and do) bswap the value and mask constants,
> while for the former we obviously need to bitreverse them instead.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

>
> 2026-05-16  Jakub Jelinek  <[email protected]>
>
>         PR target/50481
>         * tree-ssa-ccp.cc (evaluate_stmt): Fix up
>         BUILT_IN_BITREVERSE{8,16,32,64} handling.
>
>         * gcc.dg/builtin-bitreverse-3.c: New test.
>
> --- gcc/tree-ssa-ccp.cc.jj      2026-05-15 22:26:46.621857908 +0200
> +++ gcc/tree-ssa-ccp.cc 2026-05-16 10:21:46.786421477 +0200
> @@ -2435,10 +2435,6 @@ evaluate_stmt (gimple *stmt)
>             case BUILT_IN_BSWAP32:
>             case BUILT_IN_BSWAP64:
>             case BUILT_IN_BSWAP128:
> -           case BUILT_IN_BITREVERSE8:
> -           case BUILT_IN_BITREVERSE16:
> -           case BUILT_IN_BITREVERSE32:
> -           case BUILT_IN_BITREVERSE64:
>               val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
>               if (val.lattice_val == UNDEFINED)
>                 break;
> @@ -2461,6 +2457,33 @@ evaluate_stmt (gimple *stmt)
>                   if (wi::sext (val.mask, prec) != -1)
>                     break;
>                 }
> +             val.lattice_val = VARYING;
> +             val.value = NULL_TREE;
> +             val.mask = -1;
> +             break;
> +
> +           case BUILT_IN_BITREVERSE8:
> +           case BUILT_IN_BITREVERSE16:
> +           case BUILT_IN_BITREVERSE32:
> +           case BUILT_IN_BITREVERSE64:
> +             val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
> +             if (val.lattice_val == UNDEFINED)
> +               break;
> +             else if (val.lattice_val == CONSTANT
> +                      && val.value
> +                      && TREE_CODE (val.value) == INTEGER_CST)
> +               {
> +                 tree type = TREE_TYPE (gimple_call_lhs (stmt));
> +                 int prec = TYPE_PRECISION (type);
> +                 wide_int wval = wi::to_wide (val.value);
> +                 wval = wide_int::from (wval, prec, UNSIGNED);
> +                 wide_int wmask = wide_int::from (val.mask, prec, UNSIGNED);
> +                 val.value = wide_int_to_tree (type, wi::bitreverse (wval));
> +                 val.mask = widest_int::from (wi::bitreverse (wmask),
> +                                              UNSIGNED);
> +                 if (wi::sext (val.mask, prec) != -1)
> +                   break;
> +               }
>               val.lattice_val = VARYING;
>               val.value = NULL_TREE;
>               val.mask = -1;
> --- gcc/testsuite/gcc.dg/builtin-bitreverse-3.c.jj      2026-03-27 
> 08:35:17.031535967 +0100
> +++ gcc/testsuite/gcc.dg/builtin-bitreverse-3.c 2026-05-16 10:18:41.063664634 
> +0200
> @@ -0,0 +1,31 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2" } */
> +
> +#if __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8
> +[[gnu::noipa]] bool
> +foo (unsigned x)
> +{
> +  x &= 0x499a750a;
> +  x |= 0x5a7c04f;
> +  x = __builtin_bitreverse32 (x);
> +  return (x & ~0x351848) == 0x4fc0a705;
> +}
> +
> +[[gnu::noipa]] bool
> +bar (unsigned x)
> +{
> +  x &= 0x499a750a;
> +  x |= 0x5a7c04f;
> +  x = __builtin_bitreverse32 (x);
> +  return (x & ~0xac1812) == 0xf203e5a0;
> +}
> +#endif
> +
> +int
> +main ()
> +{
> +#if __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8
> +  if (foo (~0) || !bar (~0))
> +    __builtin_abort ();
> +#endif
> +}
>
>         Jakub
>

Reply via email to