6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
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
+
9
12
#ifndef _LIBCPP___BIT_POPCOUNT_H
10
13
#define _LIBCPP___BIT_POPCOUNT_H
11
14
@@ -24,10 +27,50 @@ _LIBCPP_PUSH_MACROS
24
27
25
28
_LIBCPP_BEGIN_NAMESPACE_STD
26
29
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 {
10000
td>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
+
27
66
template <class _Tp >
28
67
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount (_Tp __t ) _NOEXCEPT {
29
68
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.
30
70
return __builtin_popcountg (__t );
71
+ #else
72
+ return std::__popcount_impl (__t );
73
+ #endif
31
74
}
32
75
33
76
#if _LIBCPP_STD_VER >= 20
0 commit comments