https://gcc.gnu.org/g:7ca53f9d86ef5f4c6a49f414f3cdd88d2b8a0bad
commit r17-549-g7ca53f9d86ef5f4c6a49f414f3cdd88d2b8a0bad Author: Jakub Jelinek <[email protected]> Date: Sat May 16 10:50:00 2026 +0200 tree-ssa-ccp: Fix up __builtin_bitreverse* handling [PR50481] 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. 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. Reviewed-by: Andrew Pinski <[email protected]> Diff: --- gcc/testsuite/gcc.dg/builtin-bitreverse-3.c | 31 +++++++++++++++++++++++++++++ gcc/tree-ssa-ccp.cc | 31 +++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/gcc/testsuite/gcc.dg/builtin-bitreverse-3.c b/gcc/testsuite/gcc.dg/builtin-bitreverse-3.c new file mode 100644 index 000000000000..bd5601292b6c --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-bitreverse-3.c @@ -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 +} diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc index 974bef17832f..891fcc12cafc 100644 --- a/gcc/tree-ssa-ccp.cc +++ b/gcc/tree-ssa-ccp.cc @@ -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; @@ -2466,6 +2462,33 @@ evaluate_stmt (gimple *stmt) 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; + break; + default:; } }
