Files
allwpilib/upstream_utils/llvm_patches/0030-Use-C-20-bit-header.patch
2023-07-12 22:50:13 -07:00

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.