X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FMathExtras.h;h=8111aeebe6ee228b989c45de86a3437361e6a1c3;hp=71b22b0f2fcf2b67adf10aab6eb38d060195ffa9;hb=09a7daad01b02482a58fb2ad6972e80871040c84;hpb=3b3752c898d041fcab9455581136ebc6de921610 diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 71b22b0f2fc..8111aeebe6e 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -63,7 +63,7 @@ template struct TrailingZerosCounter { } }; -#if __GNUC__ >= 4 || _MSC_VER +#if __GNUC__ >= 4 || defined(_MSC_VER) template struct TrailingZerosCounter { static std::size_t count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) @@ -71,7 +71,7 @@ template struct TrailingZerosCounter { #if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_ctz(Val); -#elif _MSC_VER +#elif defined(_MSC_VER) unsigned long Index; _BitScanForward(&Index, Val); return Index; @@ -87,7 +87,7 @@ template struct TrailingZerosCounter { #if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_ctzll(Val); -#elif _MSC_VER +#elif defined(_MSC_VER) unsigned long Index; _BitScanForward64(&Index, Val); return Index; @@ -132,7 +132,7 @@ template struct LeadingZerosCounter { } }; -#if __GNUC__ >= 4 || _MSC_VER +#if __GNUC__ >= 4 || defined(_MSC_VER) template struct LeadingZerosCounter { static std::size_t count(T Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) @@ -140,7 +140,7 @@ template struct LeadingZerosCounter { #if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_clz(Val); -#elif _MSC_VER +#elif defined(_MSC_VER) unsigned long Index; _BitScanReverse(&Index, Val); return Index ^ 31; @@ -156,7 +156,7 @@ template struct LeadingZerosCounter { #if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) return __builtin_clzll(Val); -#elif _MSC_VER +#elif defined(_MSC_VER) unsigned long Index; _BitScanReverse64(&Index, Val); return Index ^ 63; @@ -313,7 +313,7 @@ inline bool isShiftedUInt(uint64_t x) { /// isUIntN - Checks if an unsigned integer fits into the given (dynamic) /// bit width. inline bool isUIntN(unsigned N, uint64_t x) { - return x == (x & (~0ULL >> (64 - N))); + return N >= 64 || x < (UINT64_C(1)<<(N)); } /// isIntN - Checks if an signed integer fits into the given (dynamic) @@ -653,6 +653,70 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) { return int64_t(X << (64 - B)) >> (64 - B); } +/// \brief Add two unsigned integers, X and Y, of type T. +/// Clamp the result to the maximum representable value of T on overflow. +/// ResultOverflowed indicates if the result is larger than the maximum +/// representable value of type T. +template +typename std::enable_if::value, T>::type +SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + // Hacker's Delight, p. 29 + T Z = X + Y; + Overflowed = (Z < X || Z < Y); + if (Overflowed) + return std::numeric_limits::max(); + else + return Z; +} + +/// \brief Multiply two unsigned integers, X and Y, of type T. +/// Clamp the result to the maximum representable value of T on overflow. +/// ResultOverflowed indicates if the result is larger than the maximum +/// representable value of type T. +template +typename std::enable_if::value, T>::type +SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; + + // Hacker's Delight, p. 30 has a different algorithm, but we don't use that + // because it fails for uint16_t (where multiplication can have undefined + // behavior due to promotion to int), and requires a division in addition + // to the multiplication. + + Overflowed = false; + + // Log2(Z) would be either Log2Z or Log2Z + 1. + // Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z + // will necessarily be less than Log2Max as desired. + int Log2Z = Log2_64(X) + Log2_64(Y); + const T Max = std::numeric_limits::max(); + int Log2Max = Log2_64(Max); + if (Log2Z < Log2Max) { + return X * Y; + } + if (Log2Z > Log2Max) { + Overflowed = true; + return Max; + } + + // We're going to use the top bit, and maybe overflow one + // bit past it. Multiply all but the bottom bit then add + // that on at the end. + T Z = (X >> 1) * Y; + if (Z & ~(Max >> 1)) { + Overflowed = true; + return Max; + } + Z <<= 1; + if (X & 1) + return SaturatingAdd(Z, Y, ResultOverflowed); + + return Z; +} + extern const float huge_valf; } // End llvm namespace