From 09a7daad01b02482a58fb2ad6972e80871040c84 Mon Sep 17 00:00:00 2001 From: Nathan Slingerland Date: Wed, 9 Dec 2015 17:11:28 +0000 Subject: [PATCH] [Support] Change SaturatingAdd()/SaturatingMultiply() to use pointer for returning overflow state Summary: Improve SaturatingAdd()/SaturatingMultiply() to use bool * to optionally return overflow result. This should make it clearer that the value is returned at callsites and reduces the size of the implementation. Reviewers: davidxl, silvas Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D15219 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255128 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ProfileData/InstrProf.h | 2 +- include/llvm/Support/MathExtras.h | 37 +++++++++------------------- unittests/Support/MathExtrasTest.cpp | 34 ++++++++++++------------- 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index 3e711bb60cf..2730cc167f7 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -435,7 +435,7 @@ instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) { for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) { bool ResultOverflowed; - Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], ResultOverflowed); + Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], &ResultOverflowed); if (ResultOverflowed) Result = instrprof_error::counter_overflow; } diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 0d0a2efa7ad..8111aeebe6e 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -659,38 +659,34 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) { /// representable value of type T. template typename std::enable_if::value, T>::type -SaturatingAdd(T X, T Y, bool &ResultOverflowed) { +SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { + bool Dummy; + bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; // Hacker's Delight, p. 29 T Z = X + Y; - ResultOverflowed = (Z < X || Z < Y); - if (ResultOverflowed) + Overflowed = (Z < X || Z < Y); + if (Overflowed) return std::numeric_limits::max(); else return Z; } -/// \brief Add two unsigned integers, X and Y, of type T. -/// Clamp the result to the maximum representable value of T on overflow. -template -typename std::enable_if::value, T>::type -SaturatingAdd(T X, T Y) { - bool ResultOverflowed; - return SaturatingAdd(X, Y, ResultOverflowed); -} - /// \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) { +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. - ResultOverflowed = false; + 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 @@ -702,7 +698,7 @@ SaturatingMultiply(T X, T Y, bool &ResultOverflowed) { return X * Y; } if (Log2Z > Log2Max) { - ResultOverflowed = true; + Overflowed = true; return Max; } @@ -711,7 +707,7 @@ SaturatingMultiply(T X, T Y, bool &ResultOverflowed) { // that on at the end. T Z = (X >> 1) * Y; if (Z & ~(Max >> 1)) { - ResultOverflowed = true; + Overflowed = true; return Max; } Z <<= 1; @@ -721,15 +717,6 @@ SaturatingMultiply(T X, T Y, bool &ResultOverflowed) { 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. -template -typename std::enable_if::value, T>::type -SaturatingMultiply(T X, T Y) { - bool ResultOverflowed; - return SaturatingMultiply(X, Y, ResultOverflowed); -} - extern const float huge_valf; } // End llvm namespace diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp index ee2fc1b9034..945d8322b25 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -197,23 +197,23 @@ void SaturatingAddTestHelper() bool ResultOverflowed; EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2))); - EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2), ResultOverflowed)); + EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(Max, SaturatingAdd(Max, T(1))); - EXPECT_EQ(Max, SaturatingAdd(Max, T(1), ResultOverflowed)); + EXPECT_EQ(Max, SaturatingAdd(Max, T(1), &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1))); - EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1), ResultOverflowed)); + EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(Max, SaturatingAdd(T(1), Max)); - EXPECT_EQ(Max, SaturatingAdd(T(1), Max, ResultOverflowed)); + EXPECT_EQ(Max, SaturatingAdd(T(1), Max, &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); EXPECT_EQ(Max, SaturatingAdd(Max, Max)); - EXPECT_EQ(Max, SaturatingAdd(Max, Max, ResultOverflowed)); + EXPECT_EQ(Max, SaturatingAdd(Max, Max, &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); } @@ -232,45 +232,45 @@ void SaturatingMultiplyTestHelper() // Test basic multiplication. EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3))); - EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3), ResultOverflowed)); + EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2))); - EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2), ResultOverflowed)); + EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); // Test multiplication by zero. EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0))); - EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0), ResultOverflowed)); + EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0))); - EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0), ResultOverflowed)); + EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1))); - EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1), ResultOverflowed)); + EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0))); - EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0), ResultOverflowed)); + EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0), &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max)); - EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max, ResultOverflowed)); + EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max, &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); // Test multiplication by maximum value. EXPECT_EQ(Max, SaturatingMultiply(Max, T(2))); - EXPECT_EQ(Max, SaturatingMultiply(Max, T(2), ResultOverflowed)); + EXPECT_EQ(Max, SaturatingMultiply(Max, T(2), &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); EXPECT_EQ(Max, SaturatingMultiply(T(2), Max)); - EXPECT_EQ(Max, SaturatingMultiply(T(2), Max, ResultOverflowed)); + EXPECT_EQ(Max, SaturatingMultiply(T(2), Max, &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); EXPECT_EQ(Max, SaturatingMultiply(Max, Max)); - EXPECT_EQ(Max, SaturatingMultiply(Max, Max, ResultOverflowed)); + EXPECT_EQ(Max, SaturatingMultiply(Max, Max, &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); // Test interesting boundary conditions for algorithm - @@ -286,11 +286,11 @@ void SaturatingMultiplyTestHelper() if(OverflowExpected) { EXPECT_EQ(Max, SaturatingMultiply(X, Y)); - EXPECT_EQ(Max, SaturatingMultiply(X, Y, ResultOverflowed)); + EXPECT_EQ(Max, SaturatingMultiply(X, Y, &ResultOverflowed)); EXPECT_TRUE(ResultOverflowed); } else { EXPECT_EQ(X * Y, SaturatingMultiply(X, Y)); - EXPECT_EQ(X * Y, SaturatingMultiply(X, Y, ResultOverflowed)); + EXPECT_EQ(X * Y, SaturatingMultiply(X, Y, &ResultOverflowed)); EXPECT_FALSE(ResultOverflowed); } } -- 2.34.1