| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Tyler Veness <calcmogul@gmail.com> |
| Date: Tue, 11 Jul 2023 22:56:09 -0700 |
| Subject: [PATCH 29/31] Use C++20 <bit> header |
| |
| --- |
| llvm/include/llvm/ADT/DenseMap.h | 3 +- |
| llvm/include/llvm/ADT/Hashing.h | 35 +-- |
| llvm/include/llvm/ADT/bit.h | 287 ------------------------- |
| llvm/include/llvm/Support/MathExtras.h | 21 +- |
| 4 files changed, 31 insertions(+), 315 deletions(-) |
| |
| diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h |
| index e9bd3bfa4a6fe0fa26ff20069bbadc816c8baa65..93b50c9e53af4ea3af5fd0329a8a03bdce659e9d 100644 |
| --- a/llvm/include/llvm/ADT/DenseMap.h |
| +++ b/llvm/include/llvm/ADT/DenseMap.h |
| @@ -23,6 +23,7 @@ |
| #include "llvm/Support/ReverseIteration.h" |
| #include "llvm/Support/type_traits.h" |
| #include <algorithm> |
| +#include <bit> |
| #include <cassert> |
| #include <cstddef> |
| #include <cstring> |
| @@ -933,7 +934,7 @@ class SmallDenseMap |
| public: |
| explicit SmallDenseMap(unsigned NumInitBuckets = 0) { |
| if (NumInitBuckets > InlineBuckets) |
| - NumInitBuckets = llvm::bit_ceil(NumInitBuckets); |
| + NumInitBuckets = std::bit_ceil(NumInitBuckets); |
| init(NumInitBuckets); |
| } |
| |
| diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h |
| index 781bdb7416392e3f60a1ac3a38fbcf5324b5395f..28934add722f518ae1e9cb9c4a23d2212a47cbdf 100644 |
| --- a/llvm/include/llvm/ADT/Hashing.h |
| +++ b/llvm/include/llvm/ADT/Hashing.h |
| @@ -49,6 +49,7 @@ |
| #include "llvm/Support/SwapByteOrder.h" |
| #include "llvm/Support/type_traits.h" |
| #include <algorithm> |
| +#include <bit> |
| #include <cassert> |
| #include <cstring> |
| #include <optional> |
| @@ -224,30 +225,30 @@ inline uint64_t hash_17to32_bytes(const char *s, size_t len, uint64_t seed) { |
| uint64_t b = fetch64(s + 8); |
| uint64_t c = fetch64(s + len - 8) * k2; |
| uint64_t d = fetch64(s + len - 16) * k0; |
| - return hash_16_bytes(llvm::rotr<uint64_t>(a - b, 43) + |
| - llvm::rotr<uint64_t>(c ^ seed, 30) + d, |
| - a + llvm::rotr<uint64_t>(b ^ k3, 20) - c + len + seed); |
| + return hash_16_bytes(std::rotr<uint64_t>(a - b, 43) + |
| + std::rotr<uint64_t>(c ^ seed, 30) + d, |
| + a + std::rotr<uint64_t>(b ^ k3, 20) - c + len + seed); |
| } |
| |
| inline uint64_t hash_33to64_bytes(const char *s, size_t len, uint64_t seed) { |
| uint64_t z = fetch64(s + 24); |
| uint64_t a = fetch64(s) + (len + fetch64(s + len - 16)) * k0; |
| - uint64_t b = llvm::rotr<uint64_t>(a + z, 52); |
| - uint64_t c = llvm::rotr<uint64_t>(a, 37); |
| + uint64_t b = std::rotr<uint64_t>(a + z, 52); |
| + uint64_t c = std::rotr<uint64_t>(a, 37); |
| a += fetch64(s + 8); |
| - c += llvm::rotr<uint64_t>(a, 7); |
| + c += std::rotr<uint64_t>(a, 7); |
| a += fetch64(s + 16); |
| uint64_t vf = a + z; |
| - uint64_t vs = b + llvm::rotr<uint64_t>(a, 31) + c; |
| + uint64_t vs = b + std::rotr<uint64_t>(a, 31) + c; |
| a = fetch64(s + 16) + fetch64(s + len - 32); |
| z = fetch64(s + len - 8); |
| - b = llvm::rotr<uint64_t>(a + z, 52); |
| - c = llvm::rotr<uint64_t>(a, 37); |
| + b = std::rotr<uint64_t>(a + z, 52); |
| + c = std::rotr<uint64_t>(a, 37); |
| a += fetch64(s + len - 24); |
| - c += llvm::rotr<uint64_t>(a, 7); |
| + c += std::rotr<uint64_t>(a, 7); |
| a += fetch64(s + len - 16); |
| uint64_t wf = a + z; |
| - uint64_t ws = b + llvm::rotr<uint64_t>(a, 31) + c; |
| + uint64_t ws = b + std::rotr<uint64_t>(a, 31) + c; |
| uint64_t r = shift_mix((vf + ws) * k2 + (wf + vs) * k0); |
| return shift_mix((seed ^ (r * k0)) + vs) * k2; |
| } |
| @@ -280,7 +281,7 @@ struct hash_state { |
| hash_state state = {0, |
| seed, |
| hash_16_bytes(seed, k1), |
| - llvm::rotr<uint64_t>(seed ^ k1, 49), |
| + std::rotr<uint64_t>(seed ^ k1, 49), |
| seed * k1, |
| shift_mix(seed), |
| 0}; |
| @@ -294,10 +295,10 @@ struct hash_state { |
| static void mix_32_bytes(const char *s, uint64_t &a, uint64_t &b) { |
| a += fetch64(s); |
| uint64_t c = fetch64(s + 24); |
| - b = llvm::rotr<uint64_t>(b + a + c, 21); |
| + b = std::rotr<uint64_t>(b + a + c, 21); |
| uint64_t d = a; |
| a += fetch64(s + 8) + fetch64(s + 16); |
| - b += llvm::rotr<uint64_t>(a, 44) + d; |
| + b += std::rotr<uint64_t>(a, 44) + d; |
| a += c; |
| } |
| |
| @@ -305,11 +306,11 @@ struct hash_state { |
| /// We mix all 64 bytes even when the chunk length is smaller, but we |
| /// record the actual length. |
| void mix(const char *s) { |
| - h0 = llvm::rotr<uint64_t>(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; |
| - h1 = llvm::rotr<uint64_t>(h1 + h4 + fetch64(s + 48), 42) * k1; |
| + h0 = std::rotr<uint64_t>(h0 + h1 + h3 + fetch64(s + 8), 37) * k1; |
| + h1 = std::rotr<uint64_t>(h1 + h4 + fetch64(s + 48), 42) * k1; |
| h0 ^= h6; |
| h1 += h3 + fetch64(s + 40); |
| - h2 = llvm::rotr<uint64_t>(h2 + h5, 33) * k1; |
| + h2 = std::rotr<uint64_t>(h2 + h5, 33) * k1; |
| h3 = h4 * k1; |
| h4 = h0 + h5; |
| mix_32_bytes(s, h3, h4); |
| diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h |
| index 2840c5f608d3ea896e1867dd4710685da9572f2d..0a4a3634820efbc0a8ca675e3ad7c98469260d0b 100644 |
| --- a/llvm/include/llvm/ADT/bit.h |
| +++ b/llvm/include/llvm/ADT/bit.h |
| @@ -27,18 +27,6 @@ |
| #include <cstdlib> // for _byteswap_{ushort,ulong,uint64} |
| #endif |
| |
| -#ifdef _MSC_VER |
| -// Declare these intrinsics manually rather including intrin.h. It's very |
| -// expensive, and bit.h is popular via MathExtras.h. |
| -// #include <intrin.h> |
| -extern "C" { |
| -unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask); |
| -unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask); |
| -unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask); |
| -unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask); |
| -} |
| -#endif |
| - |
| namespace llvm { |
| |
| // This implementation of bit_cast is different from the C++20 one in two ways: |
| @@ -106,281 +94,6 @@ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>> |
| } |
| } |
| |
| -template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> |
| -[[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept { |
| - return (Value != 0) && ((Value & (Value - 1)) == 0); |
| -} |
| - |
| -namespace detail { |
| -template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { |
| - static unsigned count(T Val) { |
| - if (!Val) |
| - return std::numeric_limits<T>::digits; |
| - if (Val & 0x1) |
| - return 0; |
| - |
| - // Bisection method. |
| - unsigned ZeroBits = 0; |
| - T Shift = std::numeric_limits<T>::digits >> 1; |
| - T Mask = std::numeric_limits<T>::max() >> Shift; |
| - while (Shift) { |
| - if ((Val & Mask) == 0) { |
| - Val >>= Shift; |
| - ZeroBits |= Shift; |
| - } |
| - Shift >>= 1; |
| - Mask >>= Shift; |
| - } |
| - return ZeroBits; |
| - } |
| -}; |
| - |
| -#if defined(__GNUC__) || defined(_MSC_VER) |
| -template <typename T> struct TrailingZerosCounter<T, 4> { |
| - static unsigned count(T Val) { |
| - if (Val == 0) |
| - return 32; |
| - |
| -#if __has_builtin(__builtin_ctz) || defined(__GNUC__) |
| - return __builtin_ctz(Val); |
| -#elif defined(_MSC_VER) |
| - unsigned long Index; |
| - _BitScanForward(&Index, Val); |
| - return Index; |
| -#endif |
| - } |
| -}; |
| - |
| -#if !defined(_MSC_VER) || defined(_M_X64) |
| -template <typename T> struct TrailingZerosCounter<T, 8> { |
| - static unsigned count(T Val) { |
| - if (Val == 0) |
| - return 64; |
| - |
| -#if __has_builtin(__builtin_ctzll) || defined(__GNUC__) |
| - return __builtin_ctzll(Val); |
| -#elif defined(_MSC_VER) |
| - unsigned long Index; |
| - _BitScanForward64(&Index, Val); |
| - return Index; |
| -#endif |
| - } |
| -}; |
| -#endif |
| -#endif |
| -} // namespace detail |
| - |
| -/// Count number of 0's from the least significant bit to the most |
| -/// stopping at the first 1. |
| -/// |
| -/// Only unsigned integral types are allowed. |
| -/// |
| -/// Returns std::numeric_limits<T>::digits on an input of 0. |
| -template <typename T> [[nodiscard]] int countr_zero(T Val) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - return llvm::detail::TrailingZerosCounter<T, sizeof(T)>::count(Val); |
| -} |
| - |
| -namespace detail { |
| -template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { |
| - static unsigned count(T Val) { |
| - if (!Val) |
| - return std::numeric_limits<T>::digits; |
| - |
| - // Bisection method. |
| - unsigned ZeroBits = 0; |
| - for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { |
| - T Tmp = Val >> Shift; |
| - if (Tmp) |
| - Val = Tmp; |
| - else |
| - ZeroBits |= Shift; |
| - } |
| - return ZeroBits; |
| - } |
| -}; |
| - |
| -#if defined(__GNUC__) || defined(_MSC_VER) |
| -template <typename T> struct LeadingZerosCounter<T, 4> { |
| - static unsigned count(T Val) { |
| - if (Val == 0) |
| - return 32; |
| - |
| -#if __has_builtin(__builtin_clz) || defined(__GNUC__) |
| - return __builtin_clz(Val); |
| -#elif defined(_MSC_VER) |
| - unsigned long Index; |
| - _BitScanReverse(&Index, Val); |
| - return Index ^ 31; |
| -#endif |
| - } |
| -}; |
| - |
| -#if !defined(_MSC_VER) || defined(_M_X64) |
| -template <typename T> struct LeadingZerosCounter<T, 8> { |
| - static unsigned count(T Val) { |
| - if (Val == 0) |
| - return 64; |
| - |
| -#if __has_builtin(__builtin_clzll) || defined(__GNUC__) |
| - return __builtin_clzll(Val); |
| -#elif defined(_MSC_VER) |
| - unsigned long Index; |
| - _BitScanReverse64(&Index, Val); |
| - return Index ^ 63; |
| -#endif |
| - } |
| -}; |
| -#endif |
| -#endif |
| -} // namespace detail |
| - |
| -/// Count number of 0's from the most significant bit to the least |
| -/// stopping at the first 1. |
| -/// |
| -/// Only unsigned integral types are allowed. |
| -/// |
| -/// Returns std::numeric_limits<T>::digits on an input of 0. |
| -template <typename T> [[nodiscard]] int countl_zero(T Val) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - return llvm::detail::LeadingZerosCounter<T, sizeof(T)>::count(Val); |
| -} |
| - |
| -/// Count the number of ones from the most significant bit to the first |
| -/// zero bit. |
| -/// |
| -/// Ex. countl_one(0xFF0FFF00) == 8. |
| -/// Only unsigned integral types are allowed. |
| -/// |
| -/// Returns std::numeric_limits<T>::digits on an input of all ones. |
| -template <typename T> [[nodiscard]] int countl_one(T Value) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - return llvm::countl_zero<T>(~Value); |
| -} |
| - |
| -/// Count the number of ones from the least significant bit to the first |
| -/// zero bit. |
| -/// |
| -/// Ex. countr_one(0x00FF00FF) == 8. |
| -/// Only unsigned integral types are allowed. |
| -/// |
| -/// Returns std::numeric_limits<T>::digits on an input of all ones. |
| -template <typename T> [[nodiscard]] int countr_one(T Value) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - return llvm::countr_zero<T>(~Value); |
| -} |
| - |
| -/// Returns the number of bits needed to represent Value if Value is nonzero. |
| -/// Returns 0 otherwise. |
| -/// |
| -/// Ex. bit_width(5) == 3. |
| -template <typename T> [[nodiscard]] int bit_width(T Value) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - return std::numeric_limits<T>::digits - llvm::countl_zero(Value); |
| -} |
| - |
| -/// Returns the largest integral power of two no greater than Value if Value is |
| -/// nonzero. Returns 0 otherwise. |
| -/// |
| -/// Ex. bit_floor(5) == 4. |
| -template <typename T> [[nodiscard]] T bit_floor(T Value) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - if (!Value) |
| - return 0; |
| - return T(1) << (llvm::bit_width(Value) - 1); |
| -} |
| - |
| -/// Returns the smallest integral power of two no smaller than Value if Value is |
| -/// nonzero. Returns 1 otherwise. |
| -/// |
| -/// Ex. bit_ceil(5) == 8. |
| -/// |
| -/// The return value is undefined if the input is larger than the largest power |
| -/// of two representable in T. |
| -template <typename T> [[nodiscard]] T bit_ceil(T Value) { |
| - static_assert(std::is_unsigned_v<T>, |
| - "Only unsigned integral types are allowed."); |
| - if (Value < 2) |
| - return 1; |
| - return T(1) << llvm::bit_width<T>(Value - 1u); |
| -} |
| - |
| -namespace detail { |
| -template <typename T, std::size_t SizeOfT> struct PopulationCounter { |
| - static int count(T Value) { |
| - // Generic version, forward to 32 bits. |
| - static_assert(SizeOfT <= 4, "Not implemented!"); |
| -#if defined(__GNUC__) |
| - return (int)__builtin_popcount(Value); |
| -#else |
| - uint32_t v = Value; |
| - v = v - ((v >> 1) & 0x55555555); |
| - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); |
| - return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24); |
| -#endif |
| - } |
| -}; |
| - |
| -template <typename T> struct PopulationCounter<T, 8> { |
| - static int count(T Value) { |
| -#if defined(__GNUC__) |
| - return (int)__builtin_popcountll(Value); |
| -#else |
| - uint64_t v = Value; |
| - v = v - ((v >> 1) & 0x5555555555555555ULL); |
| - v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); |
| - v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; |
| - return int((uint64_t)(v * 0x0101010101010101ULL) >> 56); |
| -#endif |
| - } |
| -}; |
| -} // namespace detail |
| - |
| -/// Count the number of set bits in a value. |
| -/// Ex. popcount(0xF000F000) = 8 |
| -/// Returns 0 if the word is zero. |
| -template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> |
| -[[nodiscard]] inline int popcount(T Value) noexcept { |
| - return detail::PopulationCounter<T, sizeof(T)>::count(Value); |
| -} |
| - |
| -// Forward-declare rotr so that rotl can use it. |
| -template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> |
| -[[nodiscard]] constexpr T rotr(T V, int R); |
| - |
| -template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>> |
| -[[nodiscard]] constexpr T rotl(T V, int R) { |
| - unsigned N = std::numeric_limits<T>::digits; |
| - |
| - R = R % N; |
| - if (!R) |
| - return V; |
| - |
| - if (R < 0) |
| - return llvm::rotr(V, -R); |
| - |
| - return (V << R) | (V >> (N - R)); |
| -} |
| - |
| -template <typename T, typename> [[nodiscard]] constexpr T rotr(T V, int R) { |
| - unsigned N = std::numeric_limits<T>::digits; |
| - |
| - R = R % N; |
| - if (!R) |
| - return V; |
| - |
| - if (R < 0) |
| - return llvm::rotl(V, -R); |
| - |
| - return (V >> R) | (V << (N - R)); |
| -} |
| - |
| } // namespace llvm |
| |
| #endif |
| diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h |
| index b82d9883c41008dcbbd933709c6e854ad74c5b58..5f034b694989d8ef24e0b249abd12a5c20146b97 100644 |
| --- a/llvm/include/llvm/Support/MathExtras.h |
| +++ b/llvm/include/llvm/Support/MathExtras.h |
| @@ -15,6 +15,7 @@ |
| |
| #include "llvm/ADT/bit.h" |
| #include "llvm/Support/Compiler.h" |
| +#include <bit> |
| #include <cassert> |
| #include <climits> |
| #include <cstdint> |
| @@ -235,12 +236,12 @@ constexpr inline bool isShiftedMask_64(uint64_t Value) { |
| /// Return true if the argument is a power of two > 0. |
| /// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) |
| constexpr inline bool isPowerOf2_32(uint32_t Value) { |
| - return llvm::has_single_bit(Value); |
| + return std::has_single_bit(Value); |
| } |
| |
| /// Return true if the argument is a power of two > 0 (64 bit edition.) |
| constexpr inline bool isPowerOf2_64(uint64_t Value) { |
| - return llvm::has_single_bit(Value); |
| + return std::has_single_bit(Value); |
| } |
| |
| /// Return true if the argument contains a non-empty sequence of ones with the |
| @@ -252,8 +253,8 @@ inline bool isShiftedMask_32(uint32_t Value, unsigned &MaskIdx, |
| unsigned &MaskLen) { |
| if (!isShiftedMask_32(Value)) |
| return false; |
| - MaskIdx = llvm::countr_zero(Value); |
| - MaskLen = llvm::popcount(Value); |
| + MaskIdx = std::countr_zero(Value); |
| + MaskLen = std::popcount(Value); |
| return true; |
| } |
| |
| @@ -265,8 +266,8 @@ inline bool isShiftedMask_64(uint64_t Value, unsigned &MaskIdx, |
| unsigned &MaskLen) { |
| if (!isShiftedMask_64(Value)) |
| return false; |
| - MaskIdx = llvm::countr_zero(Value); |
| - MaskLen = llvm::popcount(Value); |
| + MaskIdx = std::countr_zero(Value); |
| + MaskLen = std::popcount(Value); |
| return true; |
| } |
| |
| @@ -284,26 +285,26 @@ template <> constexpr inline size_t CTLog2<1>() { return 0; } |
| /// (32 bit edition.) |
| /// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 |
| inline unsigned Log2_32(uint32_t Value) { |
| - return static_cast<unsigned>(31 - llvm::countl_zero(Value)); |
| + return static_cast<unsigned>(31 - std::countl_zero(Value)); |
| } |
| |
| /// Return the floor log base 2 of the specified value, -1 if the value is zero. |
| /// (64 bit edition.) |
| inline unsigned Log2_64(uint64_t Value) { |
| - return static_cast<unsigned>(63 - llvm::countl_zero(Value)); |
| + return static_cast<unsigned>(63 - std::countl_zero(Value)); |
| } |
| |
| /// Return the ceil log base 2 of the specified value, 32 if the value is zero. |
| /// (32 bit edition). |
| /// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 |
| inline unsigned Log2_32_Ceil(uint32_t Value) { |
| - return static_cast<unsigned>(32 - llvm::countl_zero(Value - 1)); |
| + return static_cast<unsigned>(32 - std::countl_zero(Value - 1)); |
| } |
| |
| /// Return the ceil log base 2 of the specified value, 64 if the value is zero. |
| /// (64 bit edition.) |
| inline unsigned Log2_64_Ceil(uint64_t Value) { |
| - return static_cast<unsigned>(64 - llvm::countl_zero(Value - 1)); |
| + return static_cast<unsigned>(64 - std::countl_zero(Value - 1)); |
| } |
| |
| /// A and B are either alignments or offsets. Return the minimum alignment that |