https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118855
Bug ID: 118855
Summary: Simplify <bit> when __builtin_*g builtins are
available
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: jakub at gcc dot gnu.org
Target Milestone: ---
I think various <bit> implementations could be simplified when compiling with
GCC >= 14.
E.g.
if (__x == 0)
return _Nd;
constexpr auto _Nd_ull = __int_traits<unsigned long long>::__digits;
constexpr auto _Nd_ul = __int_traits<unsigned long>::__digits;
constexpr auto _Nd_u = __int_traits<unsigned>::__digits;
if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u)
return __builtin_ctz(__x);
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul)
return __builtin_ctzl(__x);
else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull)
return __builtin_ctzll(__x);
else // (_Nd > _Nd_ull)
{
static_assert(_Nd <= (2 * _Nd_ull),
"Maximum supported integer size is 128-bit");
constexpr auto __max_ull = __int_traits<unsigned long long>::__max;
unsigned long long __low = __x & __max_ull;
if (__low != 0)
return __builtin_ctzll(__low);
unsigned long long __high = __x >> _Nd_ull;
return __builtin_ctzll(__high) + _Nd_ull;
}
could be
#if __has_builtin(__builtin_ctzg)
return __builtin_ctzg(__x, _Nd);
#else
// The current implementation.
#endif
Similarly __builtin_clzg, __builtin_popcountg.
Those builtins were added mainly with <stdbit.h> in mind, but later on the C FE
also got __builtin_stdc_* builtins which the C++ FE doesn't have, because with
just __builtin_*g the type-generic macros might need to expand arguments
multiple times.
That is not the problem in C++ with templates. The advantage of __builtin_*g
is that it will be shorter to parse, fewer ops in constexpr evaluation.