mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
437 lines
15 KiB
Diff
437 lines
15 KiB
Diff
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 30/30] Use C++20 <bit> header
|
|
|
|
---
|
|
llvm/include/llvm/ADT/bit.h | 256 -------------------------
|
|
llvm/include/llvm/Support/MathExtras.h | 37 ++--
|
|
2 files changed, 19 insertions(+), 274 deletions(-)
|
|
|
|
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
|
|
index d93023d88b4efe962f425d0b8fe98fc25394f1fe..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,250 +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 0 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);
|
|
-}
|
|
-
|
|
} // namespace llvm
|
|
|
|
#endif
|
|
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
|
|
index fe9c5136f9f2f687577a0b1ecce69262568a9c3c..c269839c309e92d92ff8835127dcd2dfc0dd2c23 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>
|
|
@@ -41,7 +42,7 @@ enum ZeroBehavior {
|
|
template <typename T> unsigned countTrailingZeros(T Val) {
|
|
static_assert(std::is_unsigned_v<T>,
|
|
"Only unsigned integral types are allowed.");
|
|
- return llvm::countr_zero(Val);
|
|
+ return std::countr_zero(Val);
|
|
}
|
|
|
|
/// Count number of 0's from the most significant bit to the least
|
|
@@ -53,7 +54,7 @@ template <typename T> unsigned countTrailingZeros(T Val) {
|
|
template <typename T> unsigned countLeadingZeros(T Val) {
|
|
static_assert(std::is_unsigned_v<T>,
|
|
"Only unsigned integral types are allowed.");
|
|
- return llvm::countl_zero(Val);
|
|
+ return std::countl_zero(Val);
|
|
}
|
|
|
|
/// Get the index of the first set bit starting from the least
|
|
@@ -66,7 +67,7 @@ template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
|
if (ZB == ZB_Max && Val == 0)
|
|
return (std::numeric_limits<T>::max)();
|
|
|
|
- return llvm::countr_zero(Val);
|
|
+ return std::countr_zero(Val);
|
|
}
|
|
|
|
/// Create a bitmask with the N right-most bits set to 1, and all other
|
|
@@ -108,7 +109,7 @@ template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
|
|
|
// Use ^ instead of - because both gcc and llvm can remove the associated ^
|
|
// in the __builtin_clz intrinsic on x86.
|
|
- return llvm::countl_zero(Val) ^ (std::numeric_limits<T>::digits - 1);
|
|
+ return std::countl_zero(Val) ^ (std::numeric_limits<T>::digits - 1);
|
|
}
|
|
|
|
/// Macro compressed bit reversal table for 256 bits.
|
|
@@ -295,12 +296,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);
|
|
}
|
|
|
|
/// Count the number of ones from the most significant bit to the first
|
|
@@ -313,7 +314,7 @@ constexpr inline bool isPowerOf2_64(uint64_t Value) {
|
|
template <typename T> unsigned countLeadingOnes(T Value) {
|
|
static_assert(std::is_unsigned_v<T>,
|
|
"Only unsigned integral types are allowed.");
|
|
- return llvm::countl_one<T>(Value);
|
|
+ return std::countl_one<T>(Value);
|
|
}
|
|
|
|
/// Count the number of ones from the least significant bit to the first
|
|
@@ -326,7 +327,7 @@ template <typename T> unsigned countLeadingOnes(T Value) {
|
|
template <typename T> unsigned countTrailingOnes(T Value) {
|
|
static_assert(std::is_unsigned_v<T>,
|
|
"Only unsigned integral types are allowed.");
|
|
- return llvm::countr_one<T>(Value);
|
|
+ return std::countr_one<T>(Value);
|
|
}
|
|
|
|
/// Count the number of set bits in a value.
|
|
@@ -336,7 +337,7 @@ template <typename T>
|
|
inline unsigned countPopulation(T Value) {
|
|
static_assert(std::is_unsigned_v<T>,
|
|
"Only unsigned integral types are allowed.");
|
|
- return (unsigned)llvm::popcount(Value);
|
|
+ return (unsigned)std::popcount(Value);
|
|
}
|
|
|
|
/// Return true if the argument contains a non-empty sequence of ones with the
|
|
@@ -348,8 +349,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;
|
|
}
|
|
|
|
@@ -361,8 +362,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;
|
|
}
|
|
|
|
@@ -380,26 +381,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));
|
|
}
|
|
|
|
/// This function takes a 64-bit integer and returns the bit equivalent double.
|
|
@@ -456,7 +457,7 @@ constexpr inline uint64_t NextPowerOf2(uint64_t A) {
|
|
/// Returns the power of two which is less than or equal to the given value.
|
|
/// Essentially, it is a floor operation across the domain of powers of two.
|
|
inline uint64_t PowerOf2Floor(uint64_t A) {
|
|
- return llvm::bit_floor(A);
|
|
+ return std::bit_floor(A);
|
|
}
|
|
|
|
/// Returns the power of two which is greater than or equal to the given value.
|