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