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.