On Sat, May 16, 2026 at 1:35 AM Jakub Jelinek <[email protected]> wrote: > > Hi! > > We already have __builtin_bswap{16,32,64,128}, the last one has been > added ~6 years ago. So, I think we should have also > __builtin_bitreverse128. > > The following patch does that. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > Note, we don't have __builtin_bswapg and I don't think we should, one can > only byteswap something which has number of bits divisible by CHAR_BIT.
clang added __builtin_bswapg. They added it for types which 2*CHAR_BIT (16bits). See https://github.com/llvm/llvm-project/issues/160266 and https://github.com/llvm/llvm-project/pull/162433 which added it. I had filed https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122731 for the compatibility there. > For __builtin_bitreverseg that isn't a problem, but am not sure I want to > spend time handling it on say unsigned _BitInt(357). Perhaps only if there > is some real-world use-case. > > 2026-05-16 Jakub Jelinek <[email protected]> > > PR target/50481 > * doc/extend.texi (__builtin_bitreverse32, __builtin_bitreverse64): > Tweak wording for consistency with __builtin_bswap*. > (__builtin_bitreverse128): Document. > * builtins.def (BUILT_IN_BITREVERSE128): New. > * builtins.cc (expand_builtin): Handle also BUILT_IN_BITREVERSE128. > (is_inexpensive_builtin): Likewise. > * fold-const-call.cc (fold_const_call_ss): Handle also > CFN_BUILT_IN_BITREVERSE128. > * fold-const.cc (tree_call_nonnegative_warnv_p): Likewise. > * tree-ssa-ccp.cc (evaluate_stmt): Handle also BUILT_IN_BITREVERSE128. > * tree-ssa-phiopt.cc (empty_bb_or_one_feeding_into_p): Handle also > CFN_BUILT_IN_BITREVERSE128. > (cond_removal_in_builtin_zero_pattern): Likewise. > > * gcc.dg/builtin-bitreverse-1.c: Add __builtin_bitreverse128 tests. > * gcc.dg/builtin-bitreverse-2.c: Likewise. Ok. > > --- gcc/doc/extend.texi.jj 2026-05-15 09:31:18.380852668 +0200 > +++ gcc/doc/extend.texi 2026-05-15 11:41:31.441911030 +0200 > @@ -16032,15 +16032,20 @@ are 16-bit. > @enddefbuiltin > > @defbuiltin{uint32_t __builtin_bitreverse32 (uint32_t @var{x})} > -Similar to @code{__builtin_bitreverse8}, except the argument and return types > +Similar to @code{__builtin_bitreverse16}, except the argument and return > types > are 32-bit. > @enddefbuiltin > > @defbuiltin{uint64_t __builtin_bitreverse64 (uint64_t @var{x})} > -Similar to @code{__builtin_bitreverse8}, except the argument and return types > +Similar to @code{__builtin_bitreverse32}, except the argument and return > types > are 64-bit. > @enddefbuiltin > > +@defbuiltin{uint128_t __builtin_bitreverse128 (uint128_t @var{x})} > +Similar to @code{__builtin_bitreverse64}, except the argument and return > types > +are 128-bit. Only supported on targets when 128-bit types are supported. > +@enddefbuiltin > + > @node CRC Builtins > @subsection CRC Builtins > @cindex CRC builtins > --- gcc/builtins.def.jj 2026-05-15 09:31:18.379183958 +0200 > +++ gcc/builtins.def 2026-05-15 11:00:08.850492644 +0200 > @@ -1028,6 +1028,7 @@ DEF_GCC_BUILTIN (BUILT_IN_BITREVE > DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE16, "bitreverse16", > BT_FN_UINT16_UINT16, ATTR_CONST_NOTHROW_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE32, "bitreverse32", > BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST) > DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE64, "bitreverse64", > BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST) > +DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE128, "bitreverse128", > BT_FN_UINT128_UINT128, ATTR_CONST_NOTHROW_LEAF_LIST) > > DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", > BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST) > /* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */ > --- gcc/builtins.cc.jj 2026-05-15 09:31:18.378534258 +0200 > +++ gcc/builtins.cc 2026-05-15 11:01:20.014275990 +0200 > @@ -8188,6 +8188,7 @@ expand_builtin (tree exp, rtx target, rt > case BUILT_IN_BITREVERSE16: > case BUILT_IN_BITREVERSE32: > case BUILT_IN_BITREVERSE64: > + case BUILT_IN_BITREVERSE128: > target = expand_builtin_unop (target_mode, exp, target, subtarget, > bitreverse_optab); > if (target) > @@ -12357,6 +12358,7 @@ is_inexpensive_builtin (tree decl) > case BUILT_IN_BITREVERSE16: > case BUILT_IN_BITREVERSE32: > case BUILT_IN_BITREVERSE64: > + case BUILT_IN_BITREVERSE128: > case BUILT_IN_CLZ: > case BUILT_IN_CLZIMAX: > case BUILT_IN_CLZL: > --- gcc/fold-const-call.cc.jj 2026-05-15 09:31:18.381940011 +0200 > +++ gcc/fold-const-call.cc 2026-05-15 11:01:35.660008503 +0200 > @@ -1106,6 +1106,7 @@ fold_const_call_ss (wide_int *result, co > case CFN_BUILT_IN_BITREVERSE16: > case CFN_BUILT_IN_BITREVERSE32: > case CFN_BUILT_IN_BITREVERSE64: > + case CFN_BUILT_IN_BITREVERSE128: > *result = wi::bitreverse (wide_int::from (arg, precision, > TYPE_SIGN (arg_type))); > return true; > --- gcc/fold-const.cc.jj 2026-05-15 09:31:18.382677943 +0200 > +++ gcc/fold-const.cc 2026-05-15 11:01:51.075744951 +0200 > @@ -14988,6 +14988,7 @@ tree_call_nonnegative_warnv_p (tree type > case CFN_BUILT_IN_BITREVERSE16: > case CFN_BUILT_IN_BITREVERSE32: > case CFN_BUILT_IN_BITREVERSE64: > + case CFN_BUILT_IN_BITREVERSE128: > /* Always true. */ > return true; > > --- gcc/tree-ssa-ccp.cc.jj 2026-05-15 09:31:18.384503870 +0200 > +++ gcc/tree-ssa-ccp.cc 2026-05-15 22:27:05.533474689 +0200 > @@ -2466,6 +2466,7 @@ evaluate_stmt (gimple *stmt) > case BUILT_IN_BITREVERSE16: > case BUILT_IN_BITREVERSE32: > case BUILT_IN_BITREVERSE64: > + case BUILT_IN_BITREVERSE128: > val = get_value_for_expr (gimple_call_arg (stmt, 0), true); > if (val.lattice_val == UNDEFINED) > break; > --- gcc/tree-ssa-phiopt.cc.jj 2026-05-15 09:31:18.384795813 +0200 > +++ gcc/tree-ssa-phiopt.cc 2026-05-15 11:08:28.023938328 +0200 > @@ -823,6 +823,7 @@ empty_bb_or_one_feeding_into_p (basic_bl > case CFN_BUILT_IN_BITREVERSE16: > case CFN_BUILT_IN_BITREVERSE32: > case CFN_BUILT_IN_BITREVERSE64: > + case CFN_BUILT_IN_BITREVERSE128: > CASE_CFN_FFS: > CASE_CFN_PARITY: > CASE_CFN_POPCOUNT: > @@ -2586,6 +2587,7 @@ cond_removal_in_builtin_zero_pattern (ba > case CFN_BUILT_IN_BITREVERSE16: > case CFN_BUILT_IN_BITREVERSE32: > case CFN_BUILT_IN_BITREVERSE64: > + case CFN_BUILT_IN_BITREVERSE128: > CASE_CFN_FFS: > CASE_CFN_PARITY: > CASE_CFN_POPCOUNT: > --- gcc/testsuite/gcc.dg/builtin-bitreverse-1.c.jj 2026-05-15 > 09:47:01.332664414 +0200 > +++ gcc/testsuite/gcc.dg/builtin-bitreverse-1.c 2026-05-15 11:46:42.888574660 > +0200 > @@ -25,6 +25,14 @@ br64 (unsigned long long x) > return __builtin_bitreverse64 (x); > } > > +#if __SIZEOF_INT128__ == 16 > +[[gnu::noipa]] static unsigned __int128 > +br128 (unsigned __int128 x) > +{ > + return __builtin_bitreverse128 (x); > +} > +#endif > + > int > main () > { > @@ -67,5 +75,18 @@ main () > if (br64 (0xffffffffffffffffull) != 0xffffffffffffffffull) > __builtin_abort (); > #endif > +#if __SIZEOF_INT128__ == 16 > + if (br128 (0) != 0) > + __builtin_abort (); > + if (br128 (1) != (unsigned __int128) 1 << 127) > + __builtin_abort (); > + if (br128 (((unsigned __int128) 0x0123456789abcdefull << 64) > + | 0x2468ace013579bdfull) > + != (((unsigned __int128) 0xfbd9eac807351624ull << 64) > + | 0xf7b3d591e6a2c480ull)) > + __builtin_abort (); > + if (br128 (~(unsigned __int128) 0) != ~(unsigned __int128) 0) > + __builtin_abort (); > +#endif > #endif > } > --- gcc/testsuite/gcc.dg/builtin-bitreverse-2.c.jj 2026-05-15 > 09:36:13.907780008 +0200 > +++ gcc/testsuite/gcc.dg/builtin-bitreverse-2.c 2026-05-15 11:46:55.306361889 > +0200 > @@ -12,6 +12,13 @@ _Static_assert (__builtin_bitreverse32 ( > #endif > #if __SIZEOF_LONG_LONG__ == 8 > _Static_assert (__builtin_bitreverse64 (0x0123456789abcdefull) > - == 0xf7b3d591e6a2c480ull, "bitreverse64"); > + == 0xf7b3d591e6a2c480ull, "bitreverse64"); > +#endif > +#if __SIZEOF_INT128__ == 16 > +_Static_assert (__builtin_bitreverse128 (((unsigned __int128) > + 0x0123456789abcdefull << 64) > + | 0x2468ace013579bdfull) > + == (((unsigned __int128) 0xfbd9eac807351624ull << 64) > + | 0xf7b3d591e6a2c480ull), "bitreverse128"); > #endif > #endif > > Jakub >
