mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-21 18:24:23 +00:00
MathExtras: Parametrize count(Trailing|Leading)Zeros on the type size.
Otherwise we will always select the generic version for e.g. unsigned long if uint64_t is typedef'd to 'unsigned long long'. Also remove enable_if hacks in favor of static_assert. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228921 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -35,6 +35,65 @@ enum ZeroBehavior {
|
|||||||
ZB_Width
|
ZB_Width
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
|
||||||
|
static std::size_t count(T Val, ZeroBehavior) {
|
||||||
|
if (!Val)
|
||||||
|
return std::numeric_limits<T>::digits;
|
||||||
|
if (Val & 0x1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Bisection method.
|
||||||
|
std::size_t 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 __GNUC__ >= 4 || _MSC_VER
|
||||||
|
template <typename T> struct TrailingZerosCounter<T, 4> {
|
||||||
|
static std::size_t count(T Val, ZeroBehavior ZB) {
|
||||||
|
if (ZB != ZB_Undefined && Val == 0)
|
||||||
|
return 32;
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||||
|
return __builtin_ctz(Val);
|
||||||
|
#elif _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 std::size_t count(T Val, ZeroBehavior ZB) {
|
||||||
|
if (ZB != ZB_Undefined && Val == 0)
|
||||||
|
return 64;
|
||||||
|
|
||||||
|
#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||||
|
return __builtin_ctzll(Val);
|
||||||
|
#elif _MSC_VER
|
||||||
|
unsigned long Index;
|
||||||
|
_BitScanForward64(&Index, Val);
|
||||||
|
return Index;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
/// \brief Count number of 0's from the least significant bit to the most
|
/// \brief Count number of 0's from the least significant bit to the most
|
||||||
/// stopping at the first 1.
|
/// stopping at the first 1.
|
||||||
///
|
///
|
||||||
@ -43,68 +102,66 @@ enum ZeroBehavior {
|
|||||||
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
||||||
/// valid arguments.
|
/// valid arguments.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
||||||
!std::numeric_limits<T>::is_signed, std::size_t>::type
|
static_assert(std::numeric_limits<T>::is_integer &&
|
||||||
countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
!std::numeric_limits<T>::is_signed,
|
||||||
(void)ZB;
|
"Only unsigned integral types are allowed.");
|
||||||
|
return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
|
||||||
if (!Val)
|
|
||||||
return std::numeric_limits<T>::digits;
|
|
||||||
if (Val & 0x1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Bisection method.
|
|
||||||
std::size_t 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable signed.
|
namespace detail {
|
||||||
template <typename T>
|
template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
static std::size_t count(T Val, ZeroBehavior) {
|
||||||
std::numeric_limits<T>::is_signed, std::size_t>::type
|
if (!Val)
|
||||||
countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
|
return std::numeric_limits<T>::digits;
|
||||||
|
|
||||||
|
// Bisection method.
|
||||||
|
std::size_t 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 __GNUC__ >= 4 || _MSC_VER
|
#if __GNUC__ >= 4 || _MSC_VER
|
||||||
template <>
|
template <typename T> struct LeadingZerosCounter<T, 4> {
|
||||||
inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
|
static std::size_t count(T Val, ZeroBehavior ZB) {
|
||||||
if (ZB != ZB_Undefined && Val == 0)
|
if (ZB != ZB_Undefined && Val == 0)
|
||||||
return 32;
|
return 32;
|
||||||
|
|
||||||
#if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0)
|
#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||||
return __builtin_ctz(Val);
|
return __builtin_clz(Val);
|
||||||
#elif _MSC_VER
|
#elif _MSC_VER
|
||||||
unsigned long Index;
|
unsigned long Index;
|
||||||
_BitScanForward(&Index, Val);
|
_BitScanReverse(&Index, Val);
|
||||||
return Index;
|
return Index ^ 31;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || defined(_M_X64)
|
#if !defined(_MSC_VER) || defined(_M_X64)
|
||||||
template <>
|
template <typename T> struct LeadingZerosCounter<T, 8> {
|
||||||
inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
|
static std::size_t count(T Val, ZeroBehavior ZB) {
|
||||||
if (ZB != ZB_Undefined && Val == 0)
|
if (ZB != ZB_Undefined && Val == 0)
|
||||||
return 64;
|
return 64;
|
||||||
|
|
||||||
#if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0)
|
#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
|
||||||
return __builtin_ctzll(Val);
|
return __builtin_clzll(Val);
|
||||||
#elif _MSC_VER
|
#elif _MSC_VER
|
||||||
unsigned long Index;
|
unsigned long Index;
|
||||||
_BitScanForward64(&Index, Val);
|
_BitScanReverse64(&Index, Val);
|
||||||
return Index;
|
return Index ^ 63;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
/// \brief Count number of 0's from the most significant bit to the least
|
/// \brief Count number of 0's from the most significant bit to the least
|
||||||
/// stopping at the first 1.
|
/// stopping at the first 1.
|
||||||
@ -114,64 +171,13 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
|
|||||||
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
||||||
/// valid arguments.
|
/// valid arguments.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
||||||
!std::numeric_limits<T>::is_signed, std::size_t>::type
|
static_assert(std::numeric_limits<T>::is_integer &&
|
||||||
countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
!std::numeric_limits<T>::is_signed,
|
||||||
(void)ZB;
|
"Only unsigned integral types are allowed.");
|
||||||
|
return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
|
||||||
if (!Val)
|
|
||||||
return std::numeric_limits<T>::digits;
|
|
||||||
|
|
||||||
// Bisection method.
|
|
||||||
std::size_t 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable signed.
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
|
||||||
std::numeric_limits<T>::is_signed, std::size_t>::type
|
|
||||||
countLeadingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
|
|
||||||
|
|
||||||
#if __GNUC__ >= 4 || _MSC_VER
|
|
||||||
template <>
|
|
||||||
inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
|
|
||||||
if (ZB != ZB_Undefined && Val == 0)
|
|
||||||
return 32;
|
|
||||||
|
|
||||||
#if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0)
|
|
||||||
return __builtin_clz(Val);
|
|
||||||
#elif _MSC_VER
|
|
||||||
unsigned long Index;
|
|
||||||
_BitScanReverse(&Index, Val);
|
|
||||||
return Index ^ 31;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || defined(_M_X64)
|
|
||||||
template <>
|
|
||||||
inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
|
|
||||||
if (ZB != ZB_Undefined && Val == 0)
|
|
||||||
return 64;
|
|
||||||
|
|
||||||
#if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0)
|
|
||||||
return __builtin_clzll(Val);
|
|
||||||
#elif _MSC_VER
|
|
||||||
unsigned long Index;
|
|
||||||
_BitScanReverse64(&Index, Val);
|
|
||||||
return Index ^ 63;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// \brief Get the index of the first set bit starting from the least
|
/// \brief Get the index of the first set bit starting from the least
|
||||||
/// significant bit.
|
/// significant bit.
|
||||||
///
|
///
|
||||||
@ -179,22 +185,13 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
|
|||||||
///
|
///
|
||||||
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
|
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
|
||||||
/// valid arguments.
|
/// valid arguments.
|
||||||
template <typename T>
|
template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
|
||||||
!std::numeric_limits<T>::is_signed, T>::type
|
|
||||||
findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
|
||||||
if (ZB == ZB_Max && Val == 0)
|
if (ZB == ZB_Max && Val == 0)
|
||||||
return std::numeric_limits<T>::max();
|
return std::numeric_limits<T>::max();
|
||||||
|
|
||||||
return countTrailingZeros(Val, ZB_Undefined);
|
return countTrailingZeros(Val, ZB_Undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable signed.
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
|
||||||
std::numeric_limits<T>::is_signed, T>::type
|
|
||||||
findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
|
|
||||||
|
|
||||||
/// \brief Get the index of the last set bit starting from the least
|
/// \brief Get the index of the last set bit starting from the least
|
||||||
/// significant bit.
|
/// significant bit.
|
||||||
///
|
///
|
||||||
@ -202,10 +199,7 @@ findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
|
|||||||
///
|
///
|
||||||
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
|
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
|
||||||
/// valid arguments.
|
/// valid arguments.
|
||||||
template <typename T>
|
template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
|
||||||
!std::numeric_limits<T>::is_signed, T>::type
|
|
||||||
findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
|
||||||
if (ZB == ZB_Max && Val == 0)
|
if (ZB == ZB_Max && Val == 0)
|
||||||
return std::numeric_limits<T>::max();
|
return std::numeric_limits<T>::max();
|
||||||
|
|
||||||
@ -215,12 +209,6 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
|
|||||||
(std::numeric_limits<T>::digits - 1);
|
(std::numeric_limits<T>::digits - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable signed.
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
|
||||||
std::numeric_limits<T>::is_signed, T>::type
|
|
||||||
findLastSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION;
|
|
||||||
|
|
||||||
/// \brief Macro compressed bit reversal table for 256 bits.
|
/// \brief Macro compressed bit reversal table for 256 bits.
|
||||||
///
|
///
|
||||||
/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
|
/// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable
|
||||||
|
Reference in New Issue
Block a user