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
@@ -24,10 +27,50 @@ _LIBCPP_PUSH_MACROS
2427
2528_LIBCPP_BEGIN_NAMESPACE_STD
2629
30+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount (unsigned __x) _NOEXCEPT {
31+ return __builtin_popcount (__x);
32+ }
33+
34+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount (unsigned long __x) _NOEXCEPT {
35+ return __builtin_popcountl (__x);
36+ }
37+
38+ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount (unsigned long long __x) _NOEXCEPT {
39+ return __builtin_popcountll (__x);
40+ }
41+
42+ template <class _Tp >
43+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount_impl (_Tp __t ) _NOEXCEPT {
44+ if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned int )) {
45+ return std::__libcpp_popcount (static_cast <unsigned int >(__t ));
46+ } else if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned long )) {
47+ return std::__libcpp_popcount (static_cast <unsigned long >(__t ));
48+ } else if _LIBCPP_CONSTEXPR (sizeof (_Tp) <= sizeof (unsigned long long )) {
49+ return std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
50+ } else {
51+ #if _LIBCPP_STD_VER == 11
52+ return __t != 0 ? std::__libcpp_popcount (static_cast <unsigned long long >(__t )) +
53+ std::__popcount_impl<_Tp>(__t >> numeric_limits<unsigned long long >::digits)
54+ : 0 ;
55+ #else
56+ int __ret = 0 ;
57+ while (__t != 0 ) {
58+ __ret += std::__libcpp_popcount (static_cast <unsigned long long >(__t ));
59+ __t >>= std::numeric_limits<unsigned long long >::digits;
60+ }
61+ return __ret;
62+ #endif
63+ }
64+ }
65+
2766template <class _Tp >
2867[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) _NOEXCEPT {
2968 static_assert (is_unsigned<_Tp>::value, " __popcount only works with unsigned types" );
69+ #if __has_builtin(__builtin_popcountg) // TODO (LLVM 21): This can be dropped once we only support Clang >= 19.
3070 return __builtin_popcountg (__t );
71+ #else
72+ return std::__popcount_impl (__t );
73+ #endif
3174}
3275
3376#if _LIBCPP_STD_VER >= 20
0 commit comments