[Base] Add faster `bit_count` variants
- Use C++20 `popcount()` when available - Else use compiler specific built-ins
This commit is contained in:
parent
806a33d625
commit
4800194f0d
|
@ -17,6 +17,16 @@
|
|||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
|
||||
#if defined __has_include
|
||||
#if __has_include(<version>)
|
||||
#include <version>
|
||||
#endif
|
||||
#endif
|
||||
#if __cpp_lib_bitops
|
||||
#include <bit>
|
||||
#endif
|
||||
|
||||
#include "xenia/base/platform.h"
|
||||
|
||||
#if XE_ARCH_AMD64
|
||||
|
@ -101,6 +111,23 @@ constexpr uint32_t select_bits(uint32_t value, uint32_t a, uint32_t b) {
|
|||
return (value & make_bitmask(a, b)) >> a;
|
||||
}
|
||||
|
||||
#if __cpp_lib_bitops
|
||||
template <class T>
|
||||
constexpr inline uint32_t bit_count(T v) {
|
||||
return static_cast<uint32_t>(std::popcount(v));
|
||||
}
|
||||
#else
|
||||
#if XE_COMPILER_MSVC || XE_COMPILER_INTEL
|
||||
inline uint32_t bit_count(uint32_t v) { return __popcnt(v); }
|
||||
inline uint32_t bit_count(uint64_t v) {
|
||||
return static_cast<uint32_t>(__popcnt64(v));
|
||||
}
|
||||
#elif XE_COMPILER_GCC || XE_COMPILER_CLANG
|
||||
static_assert(sizeof(unsigned int) == sizeof(uint32_t));
|
||||
static_assert(sizeof(unsigned long long) == sizeof(uint64_t));
|
||||
inline uint32_t bit_count(uint32_t v) { return __builtin_popcount(v); }
|
||||
inline uint32_t bit_count(uint64_t v) { return __builtin_popcountll(v); }
|
||||
#else
|
||||
inline uint32_t bit_count(uint32_t v) {
|
||||
v = v - ((v >> 1) & 0x55555555);
|
||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||
|
@ -116,6 +143,8 @@ inline uint32_t bit_count(uint64_t v) {
|
|||
v = v + (v >> 32) & 0x0000007F;
|
||||
return static_cast<uint32_t>(v);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lzcnt instruction, typed for integers of all sizes.
|
||||
// The number of leading zero bits in the value parameter. If value is zero, the
|
||||
|
|
Loading…
Reference in New Issue