Skip to content

Commit 19e722e

Browse files
committed
Manually implement popcount when not available
1 parent 0bbe26d commit 19e722e

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

include/swift/Basic/MathUtils.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#ifndef SWIFT_BASIC_MATH_UTILS_H
1818
#define SWIFT_BASIC_MATH_UTILS_H
1919

20+
#include "Compiler.h"
2021
#include <cstddef>
22+
#include <cstdint>
2123

2224
#if SWIFT_COMPILER_IS_MSVC
2325
#include <intrin.h>
@@ -38,11 +40,17 @@ static inline size_t roundUpToAlignMask(size_t size, size_t alignMask) {
3840
}
3941

4042
static inline unsigned popcount(unsigned value) {
41-
#if SWIFT_COMPILER_IS_MSVC
43+
#if SWIFT_COMPILER_IS_MSVC && (defined(_M_IX86) || defined(_M_X64))
44+
// The __popcnt intrinsic is only available when targetting x86{_64} with MSVC.
4245
return __popcnt(value);
43-
#else
44-
// Assume we have a compiler with this intrinsic.
46+
#elif __has_builtin(__builtin_popcount)
4547
return __builtin_popcount(value);
48+
#else
49+
// From llvm/ADT/bit.h which the runtime doesn't have access to (yet?)
50+
uint32_t v = value;
51+
v = v - ((v >> 1) & 0x55555555);
52+
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
53+
return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
4654
#endif
4755
}
4856

0 commit comments

Comments
 (0)