mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-22 10:24:26 +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,19 +35,9 @@ enum ZeroBehavior {
|
|||||||
ZB_Width
|
ZB_Width
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Count number of 0's from the least significant bit to the most
|
namespace detail {
|
||||||
/// stopping at the first 1.
|
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
|
||||||
///
|
static std::size_t count(T Val, ZeroBehavior) {
|
||||||
/// Only unsigned integral types are allowed.
|
|
||||||
///
|
|
||||||
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
|
||||||
/// valid arguments.
|
|
||||||
template <typename T>
|
|
||||||
typename std::enable_if<std::numeric_limits<T>::is_integer &&
|
|
||||||
!std::numeric_limits<T>::is_signed, std::size_t>::type
|
|
||||||
countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
|
||||||
(void)ZB;
|
|
||||||
|
|
||||||
if (!Val)
|
if (!Val)
|
||||||
return std::numeric_limits<T>::digits;
|
return std::numeric_limits<T>::digits;
|
||||||
if (Val & 0x1)
|
if (Val & 0x1)
|
||||||
@ -66,17 +56,12 @@ countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
|||||||
Mask >>= Shift;
|
Mask >>= Shift;
|
||||||
}
|
}
|
||||||
return ZeroBits;
|
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
|
|
||||||
countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION;
|
|
||||||
|
|
||||||
#if __GNUC__ >= 4 || _MSC_VER
|
#if __GNUC__ >= 4 || _MSC_VER
|
||||||
template <>
|
template <typename T> struct TrailingZerosCounter<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;
|
||||||
|
|
||||||
@ -87,11 +72,12 @@ inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
|
|||||||
_BitScanForward(&Index, Val);
|
_BitScanForward(&Index, Val);
|
||||||
return Index;
|
return Index;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || defined(_M_X64)
|
#if !defined(_MSC_VER) || defined(_M_X64)
|
||||||
template <>
|
template <typename T> struct TrailingZerosCounter<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;
|
||||||
|
|
||||||
@ -102,11 +88,13 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
|
|||||||
_BitScanForward64(&Index, Val);
|
_BitScanForward64(&Index, Val);
|
||||||
return Index;
|
return Index;
|
||||||
#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 least significant bit to the most
|
||||||
/// stopping at the first 1.
|
/// stopping at the first 1.
|
||||||
///
|
///
|
||||||
/// Only unsigned integral types are allowed.
|
/// Only unsigned integral types are allowed.
|
||||||
@ -114,11 +102,16 @@ 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 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 &&
|
||||||
countLeadingZeros(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
|
||||||
|
static std::size_t count(T Val, ZeroBehavior) {
|
||||||
if (!Val)
|
if (!Val)
|
||||||
return std::numeric_limits<T>::digits;
|
return std::numeric_limits<T>::digits;
|
||||||
|
|
||||||
@ -132,17 +125,12 @@ countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
|||||||
ZeroBits |= Shift;
|
ZeroBits |= Shift;
|
||||||
}
|
}
|
||||||
return ZeroBits;
|
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
|
#if __GNUC__ >= 4 || _MSC_VER
|
||||||
template <>
|
template <typename T> struct LeadingZerosCounter<T, 4> {
|
||||||
inline std::size_t countLeadingZeros<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;
|
||||||
|
|
||||||
@ -153,11 +141,12 @@ inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) {
|
|||||||
_BitScanReverse(&Index, Val);
|
_BitScanReverse(&Index, Val);
|
||||||
return Index ^ 31;
|
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 countLeadingZeros<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;
|
||||||
|
|
||||||
@ -168,9 +157,26 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) {
|
|||||||
_BitScanReverse64(&Index, Val);
|
_BitScanReverse64(&Index, Val);
|
||||||
return Index ^ 63;
|
return Index ^ 63;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/// \brief Count number of 0's from the most significant bit to the least
|
||||||
|
/// stopping at the first 1.
|
||||||
|
///
|
||||||
|
/// Only unsigned integral types are allowed.
|
||||||
|
///
|
||||||
|
/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are
|
||||||
|
/// valid arguments.
|
||||||
|
template <typename T>
|
||||||
|
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
|
||||||
|
static_assert(std::numeric_limits<T>::is_integer &&
|
||||||
|
!std::numeric_limits<T>::is_signed,
|
||||||
|
"Only unsigned integral types are allowed.");
|
||||||
|
return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
|
||||||
}
|
}
|
||||||
#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