From 8c66d338fc20b2d206c261426a6aed3bcbc6eba2 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Wed, 26 Aug 2020 16:25:57 +0100 Subject: [PATCH] Fixes to ctz on Windows Clang. --- src/ds/bits.h | 30 +++++++++++++++----------- src/test/func/bits/bits.cc | 43 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 src/test/func/bits/bits.cc diff --git a/src/ds/bits.h b/src/ds/bits.h index 50967fd37..a32513aaf 100644 --- a/src/ds/bits.h +++ b/src/ds/bits.h @@ -12,9 +12,6 @@ #include #include #include -#if defined(_WIN32) && defined(__GNUC__) -# define USE_CLZLL -#endif #ifdef pause # undef pause #endif @@ -76,10 +73,15 @@ namespace snmalloc return BITS - index - 1; # endif -#elif defined(USE_CLZLL) - return static_cast(__builtin_clzll(x)); -#else - return static_cast(__builtin_clzl(x)); +#else + if constexpr (std::is_same_v) + { + return __builtin_clzl(x); + } + else if constexpr (std::is_same_v) + { + return __builtin_clzll(x); + } #endif } @@ -142,17 +144,21 @@ namespace snmalloc inline size_t ctz(size_t x) { -#if __has_builtin(__builtin_ctzl) - return static_cast(__builtin_ctzl(x)); -#elif defined(_MSC_VER) +#if defined(_MSC_VER) # ifdef SNMALLOC_VA_BITS_64 return _tzcnt_u64(x); # else return _tzcnt_u32((uint32_t)x); # endif #else - // Probably GCC at this point. - return static_cast(__builtin_ctzl(x)); + if constexpr (std::is_same_v) + { + return __builtin_ctzl(x); + } + else if constexpr (std::is_same_v) + { + return __builtin_ctzll(x); + } #endif } diff --git a/src/test/func/bits/bits.cc b/src/test/func/bits/bits.cc new file mode 100644 index 000000000..c521264df --- /dev/null +++ b/src/test/func/bits/bits.cc @@ -0,0 +1,43 @@ +/** + * Unit tests for operations in bits.h + */ + +#include +#include +#include + +void +test_ctz() +{ + for (size_t i = 0; i < sizeof(size_t) * 8; i++) + if (snmalloc::bits::ctz(snmalloc::bits::one_at_bit(i)) != i) + { + std::cout << "Failed with ctz(one_at_bit(i)) != i for i=" << i << std::endl; + abort(); + } +} + + +void +test_clz() +{ + const size_t PTRSIZE_LOG = sizeof(size_t) * 8; + + for (size_t i = 0; i < sizeof(size_t) * 8; i++) + if (snmalloc::bits::clz(snmalloc::bits::one_at_bit(i)) != (PTRSIZE_LOG - i - 1)) + { + std::cout << "Failed with clz(one_at_bit(i)) != (PTRSIZE_LOG - i - 1) for i=" << i << std::endl; + abort(); + } +} + +int main(int argc, char** argv) +{ + UNUSED(argc); + UNUSED(argv); + + setup(); + + test_clz(); + test_ctz(); +} \ No newline at end of file