66//
77// ===----------------------------------------------------------------------===//
88
9+ // TODO: __builtin_popcountg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can
10+ // refactor this code to exclusively use __builtin_popcountg.
11+
912#ifndef _LIBCPP___BIT_POPCOUNT_H
1013#define _LIBCPP___BIT_POPCOUNT_H
1114
@@ -21,10 +24,50 @@ _LIBCPP_PUSH_MACROS
2124
2225_LIBCPP_BEGIN_NAMESPACE_STD
2326
27+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount (unsigned __x) _NOEXCEPT {
28+ return __builtin_popcount (__x);
29+ }
30+
31+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount (unsigned long __x) _NOEXCEPT {
32+ return __builtin_popcountl (__x);
33+ }
34+
35+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount (unsigned long long __x) _NOEXCEPT {
36+ return __builtin_popcountll (__x);
37+ }
38+
39+ template <class _Tp >
40+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount_impl (_Tp __t ) _NOEXCEPT {
41+ if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned int )) {
42+ return std::__libcpp_popcount (static_cast <unsigned int >(__t ));
43+ } else if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned long )) {
44+ return std::__libcpp_popcount (static_cast <unsigned long >(__t ));
45+ } else if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned long long )) {
46+ return std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
47+ } else {
48+ #if _LIBCPP_STD_VER == 11
49+ return __t != 0 ? std::__libcpp_popcount (static_cast <unsigned long long >(__t )) +
50+ std::__popcount_impl<_Tp>(__t >> numeric_limits<unsigned long long >::digits)
51+ : 0 ;
52+ #else
53+ int __ret = 0 ;
54+ while (__t != 0 ) {
55+ __ret += std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
56+ __t >>= std::numeric_limits<unsigned long long >::digits;
57+ }
58+ return __ret;
59+ #endif
60+ }
61+ }
62+
2463template <class _Tp >
2564[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) _NOEXCEPT {
26- static_assert (__is_unsigned_integer_v<_Tp>, " __popcount only works with unsigned types" );
65+ static_assert (is_unsigned<_Tp>::value, " __popcount only works with unsigned types" );
66+ #if __has_builtin(__builtin_popcountg) // TODO (LLVM 21): This can be dropped once we only support Clang >= 19.
2767 return __builtin_popcountg (__t );
68+ #else
69+ return std::__popcount_impl (__t );
70+ #endif
2871}
2972
3073#if _LIBCPP_STD_VER >= 20
0 commit comments