[PATCH] libstdc++: implement bit_reverse from P3104R6 for C++29
Jakub Jelinek
jakub@redhat.com
Mon Aug 31 11:01:22 GMT 2026
On Sun, Aug 30, 2026 at 09:09:57PM +0800, Yuao Ma wrote:
> --- a/libstdc++-v3/include/std/bit
> +++ b/libstdc++-v3/include/std/bit
> @@ -503,6 +503,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> };
> #endif // __cpp_lib_endian
>
> +#if __cplusplus > 202603L
> +
> + template<__unsigned_integer _Tp>
> + constexpr _Tp
> + bit_reverse(_Tp __x) noexcept
> + { return __builtin_bitreverseg(__x); }
> +#endif
This needs to be guarded on __has_builtin(__builtin_bitreverseg)
Though, given that it has an easy fallback, I think it should be actually
in the <bit> style
#if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_bitreverseg)
{ return __builtin_bitreverseg(__x); }
#else
fallback implementation
#endif
I also wonder if it wouldn't be better to start with P3793R2
and only when that is implemented continue on with the whole
P3104R6, not just part of it.
For P3793R2 I think we want a plain code with multiple conditionals,
so
constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits;
if (__s >= 0)
return __s < _Nd ? __x << __s : 0;
else
return __s > -_Nd ? __x >> -__s : 0;
or so, and for the rest of P3104R6, it can use
__builtin_elementwise_{pext,pdep} for the sake of clang++ and have a
fallback implementation. At some point gcc should add builtins for
the bitcompress/bitexpand cases, but I'd prefer not to use the clang
name, that is too ugly and x86 dependent.
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.permutation/bit_reverse.cc
> @@ -0,0 +1,41 @@
> +// { dg-do run { target c++29 } }
> +
> +#include <testsuite_hooks.h>
> +
> +#include <bit>
> +
> +constexpr void test01() {
I think the formatting of this test is just weird, look at other libstdc++
tests. I think { should go on next line,
> +#if __CHAR_BIT__ == 8
> +#if __SIZEOF_INT__ == 4
> + static_assert(std::bit_reverse(0x2fa889a7U) == 0xe59115f4U, "");
> +#endif
> +#if __SIZEOF_LONG_LONG__ == 8
> + static_assert(
> + std::bit_reverse(0xd7632f428bdccb94ULL) == 0x29d33bd142f4c6ebULL, "");
here you can wrap before == and put the == below std::bit_reverse which
would be on the same line as static_assert.
Why , "" ?
> +#endif
> + static_assert(std::bit_reverse((unsigned char)0xac) == (unsigned char)0x35,
> + "");
> +#if __SIZEOF_SHORT__ == 2
> + static_assert(
> + std::bit_reverse((unsigned short)0xc4f0) == (unsigned short)0x0f23, "");
> +#endif
> +#if __SIZEOF_INT128__ == 16
> + static_assert(
> + std::bit_reverse((((unsigned __int128)0x398773ddb9250c54ULL) << 64) |
| shouldn't be at the end of line, neither ==
Jakub
More information about the Libstdc++
mailing list