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=d853e8a21e4d0c59cf2be94dbf86ed081dbb9b00;hb=09a7daad01b02482a58fb2ad6972e80871040c84;hpb=f2bc179203d0e17bfcfa28bd5b9c1ba1d04cd6fe diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index d853e8a21e4..8111aeebe6e 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -655,12 +655,17 @@ inline int64_t SignExtend64(uint64_t X, unsigned 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) { +SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; // Hacker's Delight, p. 29 T Z = X + Y; - if (Z < X || Z < Y) + Overflowed = (Z < X || Z < Y); + if (Overflowed) return std::numeric_limits::max(); else return Z; @@ -668,33 +673,48 @@ SaturatingAdd(T X, T Y) { /// \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) { +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) + if (Log2Z < Log2Max) { return X * Y; - if (Log2Z > Log2Max) + } + 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)) + if (Z & ~(Max >> 1)) { + Overflowed = true; return Max; + } Z <<= 1; - return (X & 1) ? SaturatingAdd(Z, Y) : Z; + if (X & 1) + return SaturatingAdd(Z, Y, ResultOverflowed); + + return Z; } extern const float huge_valf;