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 >
