Index: llvm/include/llvm/Support/MathExtras.h =================================================================== --- llvm/include/llvm/Support/MathExtras.h +++ llvm/include/llvm/Support/MathExtras.h @@ -88,7 +88,7 @@ namespace detail { template struct TrailingZerosCounter { - static unsigned count(T Val, ZeroBehavior) { + static constexpr unsigned count(T Val, ZeroBehavior) { if (!Val) return std::numeric_limits::digits; if (Val & 0x1) @@ -110,31 +110,45 @@ } }; -#if defined(__GNUC__) || defined(_MSC_VER) +#if defined(_MSC_VER) || __has_builtin(__builtin_ctz) || defined(__GNUC__) + +#if __has_builtin(__builtin_ctz) || defined(__GNUC__) +template struct TrailingZerosCounter { + static constexpr unsigned count(T Val, ZeroBehavior ZB) { +#else //_MSC_VER template struct TrailingZerosCounter { static unsigned count(T Val, ZeroBehavior ZB) { +#endif if (ZB != ZB_Undefined && Val == 0) return 32; #if __has_builtin(__builtin_ctz) || defined(__GNUC__) return __builtin_ctz(Val); -#elif defined(_MSC_VER) +#else //_MSC_VER unsigned long Index; _BitScanForward(&Index, Val); return Index; #endif } }; +#endif + +#if (defined(_MSC_VER) && defined(_M_X64)) || __has_builtin(__builtin_ctz) || \ + defined(__GNUC__) -#if !defined(_MSC_VER) || defined(_M_X64) +#if __has_builtin(__builtin_ctzll) || defined(__GNUC__) +template struct TrailingZerosCounter { + static constexpr unsigned count(T Val, ZeroBehavior ZB) { +#else // defined(_MSC_VER) && defined(_M_X64) template struct TrailingZerosCounter { static unsigned count(T Val, ZeroBehavior ZB) { +#endif if (ZB != ZB_Undefined && Val == 0) return 64; #if __has_builtin(__builtin_ctzll) || defined(__GNUC__) return __builtin_ctzll(Val); -#elif defined(_MSC_VER) +#else // defined(_MSC_VER) && defined(_M_X64) unsigned long Index; _BitScanForward64(&Index, Val); return Index; @@ -142,7 +156,7 @@ } }; #endif -#endif + } // namespace detail /// Count number of 0's from the least significant bit to the most @@ -153,7 +167,7 @@ /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template -unsigned countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { +constexpr unsigned countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); @@ -162,7 +176,7 @@ namespace detail { template struct LeadingZerosCounter { - static unsigned count(T Val, ZeroBehavior) { + static constexpr unsigned count(T Val, ZeroBehavior) { if (!Val) return std::numeric_limits::digits; @@ -179,31 +193,45 @@ } }; -#if defined(__GNUC__) || defined(_MSC_VER) +#if defined(_MSC_VER) || __has_builtin(__builtin_clz) || defined(__GNUC__) + +#if __has_builtin(__builtin_clz) || defined(__GNUC__) +template struct LeadingZerosCounter { + static constexpr unsigned count(T Val, ZeroBehavior ZB) { +#else // defined(_MSC_VER) template struct LeadingZerosCounter { static unsigned count(T Val, ZeroBehavior ZB) { +#endif if (ZB != ZB_Undefined && Val == 0) return 32; #if __has_builtin(__builtin_clz) || defined(__GNUC__) return __builtin_clz(Val); -#elif defined(_MSC_VER) +#else // defined(_MSC_VER) unsigned long Index; _BitScanReverse(&Index, Val); return Index ^ 31; #endif } }; +#endif -#if !defined(_MSC_VER) || defined(_M_X64) +#if (defined(_MSC_VER) && defined(_M_X64)) || \ + __has_builtin(__builtin_clzll) || defined(__GNUC__) + +#if __has_builtin(__builtin_clzll) || defined(__GNUC__) +template struct LeadingZerosCounter { + static constexpr unsigned count(T Val, ZeroBehavior ZB) { +#else // defined(_MSC_VER) && defined(_M_X64) template struct LeadingZerosCounter { static unsigned count(T Val, ZeroBehavior ZB) { +#endif if (ZB != ZB_Undefined && Val == 0) return 64; #if __has_builtin(__builtin_clzll) || defined(__GNUC__) return __builtin_clzll(Val); -#elif defined(_MSC_VER) +#else // defined(_MSC_VER) && defined(_M_X64) unsigned long Index; _BitScanReverse64(&Index, Val); return Index ^ 63; @@ -211,7 +239,6 @@ } }; #endif -#endif } // namespace detail /// Count number of 0's from the most significant bit to the least @@ -222,7 +249,7 @@ /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template -unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { +constexpr unsigned countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); @@ -236,7 +263,8 @@ /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { +template +constexpr T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits::max(); @@ -277,7 +305,7 @@ /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { +template constexpr T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits::max(); @@ -294,15 +322,14 @@ #define R2(n) n, n + 2 * 64, n + 1 * 64, n + 3 * 64 #define R4(n) R2(n), R2(n + 2 * 16), R2(n + 1 * 16), R2(n + 3 * 16) #define R6(n) R4(n), R4(n + 2 * 4), R4(n + 1 * 4), R4(n + 3 * 4) - R6(0), R6(2), R6(1), R6(3) + R6(0), R6(2), R6(1), R6(3) #undef R2 #undef R4 #undef R6 }; /// Reverse the bits in \p Val. -template -T reverseBits(T Val) { +template T reverseBits(T Val) { unsigned char in[sizeof(Val)]; unsigned char out[sizeof(Val)]; std::memcpy(in, &Val, sizeof(Val)); @@ -313,29 +340,25 @@ } #if __has_builtin(__builtin_bitreverse8) -template<> -inline uint8_t reverseBits(uint8_t Val) { +template <> inline uint8_t reverseBits(uint8_t Val) { return __builtin_bitreverse8(Val); } #endif #if __has_builtin(__builtin_bitreverse16) -template<> -inline uint16_t reverseBits(uint16_t Val) { +template <> inline uint16_t reverseBits(uint16_t Val) { return __builtin_bitreverse16(Val); } #endif #if __has_builtin(__builtin_bitreverse32) -template<> -inline uint32_t reverseBits(uint32_t Val) { +template <> inline uint32_t reverseBits(uint32_t Val) { return __builtin_bitreverse32(Val); } #endif #if __has_builtin(__builtin_bitreverse64) -template<> -inline uint64_t reverseBits(uint64_t Val) { +template <> inline uint64_t reverseBits(uint64_t Val) { return __builtin_bitreverse64(Val); } #endif @@ -356,12 +379,13 @@ /// Make a 64-bit integer from a high / low pair of 32-bit integers. constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { - return ((uint64_t)High << 32) | (uint64_t)Low; + return (static_cast(High) << 32) | static_cast(Low); } /// Checks if an integer fits into the given bit width. template constexpr inline bool isInt(int64_t x) { - return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); + return N >= 64 || + (-(INT64_C(1) << (N - 1)) <= x && x < (INT64_C(1) << (N - 1))); } // Template specializations to get better code for common cases. template <> constexpr inline bool isInt<8>(int64_t x) { @@ -506,7 +530,7 @@ /// \param ZB the behavior on an input of all ones. Only ZB_Width and /// ZB_Undefined are valid arguments. template -unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { +constexpr unsigned countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); @@ -522,7 +546,7 @@ /// \param ZB the behavior on an input of all ones. Only ZB_Width and /// ZB_Undefined are valid arguments. template -unsigned countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { +constexpr unsigned countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); @@ -531,7 +555,7 @@ namespace detail { template struct PopulationCounter { - static unsigned count(T Value) { + static constexpr unsigned count(T Value) { // Generic version, forward to 32 bits. static_assert(SizeOfT <= 4, "Not implemented!"); #if defined(__GNUC__) @@ -546,7 +570,7 @@ }; template struct PopulationCounter { - static unsigned count(T Value) { + static constexpr unsigned count(T Value) { #if defined(__GNUC__) return __builtin_popcountll(Value); #else @@ -554,7 +578,7 @@ v = v - ((v >> 1) & 0x5555555555555555ULL); v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; - return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); + return unsigned(static_cast(v * 0x0101010101010101ULL) >> 56); #endif } }; @@ -563,8 +587,7 @@ /// Count the number of set bits in a value. /// Ex. countPopulation(0xF000F000) = 8 /// Returns 0 if the word is zero. -template -inline unsigned countPopulation(T Value) { +template constexpr inline unsigned countPopulation(T Value) { static_assert(std::numeric_limits::is_integer && !std::numeric_limits::is_signed, "Only unsigned integral types are allowed."); @@ -593,32 +616,31 @@ /// Return the floor log base 2 of the specified value, -1 if the value is zero. /// (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) { +constexpr inline unsigned Log2_32(uint32_t Value) { return 31 - countLeadingZeros(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) { +constexpr inline unsigned Log2_64(uint64_t Value) { return 63 - countLeadingZeros(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) { +constexpr inline unsigned Log2_32_Ceil(uint32_t Value) { return 32 - countLeadingZeros(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) { +constexpr inline unsigned Log2_64_Ceil(uint64_t Value) { return 64 - countLeadingZeros(Value - 1); } /// Return the greatest common divisor of the values using Euclid's algorithm. -template -inline T greatestCommonDivisor(T A, T B) { +template constexpr inline T greatestCommonDivisor(T A, T B) { while (B) { T Tmp = B; B = A % B; @@ -627,7 +649,7 @@ return A; } -inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { +constexpr inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { return greatestCommonDivisor(A, B); } @@ -680,7 +702,7 @@ /// Returns the next power of two (in 64-bits) that is strictly greater than A. /// Returns zero on overflow. -inline uint64_t NextPowerOf2(uint64_t A) { +constexpr inline uint64_t NextPowerOf2(uint64_t A) { A |= (A >> 1); A |= (A >> 2); A |= (A >> 4); @@ -692,14 +714,15 @@ /// 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) { - if (!A) return 0; +constexpr inline uint64_t PowerOf2Floor(uint64_t A) { + if (!A) + return 0; return 1ull << (63 - countLeadingZeros(A, ZB_Undefined)); } /// Returns the power of two which is greater than or equal to the given value. /// Essentially, it is a ceil operation across the domain of powers of two. -inline uint64_t PowerOf2Ceil(uint64_t A) { +constexpr inline uint64_t PowerOf2Ceil(uint64_t A) { if (!A) return 0; return NextPowerOf2(A - 1); @@ -744,7 +767,8 @@ } /// Returns the integer nearest(Numerator / Denominator). -inline uint64_t divideNearest(uint64_t Numerator, uint64_t Denominator) { +constexpr inline uint64_t divideNearest(uint64_t Numerator, + uint64_t Denominator) { return (Numerator + (Denominator / 2)) / Denominator; } @@ -791,7 +815,8 @@ /// Subtract two unsigned integers, X and Y, of type T and return the absolute /// value of the result. template -std::enable_if_t::value, T> AbsoluteDifference(T X, T Y) { +constexpr std::enable_if_t::value, T> +AbsoluteDifference(T X, T Y) { return X > Y ? (X - Y) : (Y - X); } @@ -877,7 +902,6 @@ /// Use this rather than HUGE_VALF; the latter causes warnings on MSVC. extern const float huge_valf; - /// Add two signed integers, computing the two's complement truncated result, /// returning true if overflow occured. template @@ -957,6 +981,6 @@ return UX > (static_cast(std::numeric_limits::max())) / UY; } -} // End llvm namespace +} // namespace llvm #endif Index: llvm/lib/Support/MathExtras.cpp =================================================================== --- llvm/lib/Support/MathExtras.cpp +++ llvm/lib/Support/MathExtras.cpp @@ -15,17 +15,17 @@ #ifdef _MSC_VER #include #else -#include +#include #endif namespace llvm { -#if defined(_MSC_VER) - // Visual Studio defines the HUGE_VAL class of macros using purposeful - // constant arithmetic overflow, which it then warns on when encountered. - const float huge_valf = std::numeric_limits::infinity(); +#ifdef _MSC_VER +// Visual Studio defines the HUGE_VAL class of macros using purposeful +// constant arithmetic overflow, which it then warns on when encountered. +const float huge_valf = std::numeric_limits::infinity(); #else - const float huge_valf = HUGE_VALF; +constexpr float huge_valf = HUGE_VALF; #endif } // namespace llvm