1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[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

llvm-svn: 255128
This commit is contained in:
Nathan Slingerland 2015-12-09 17:11:28 +00:00
parent de04fa6b68
commit 3b35892e68
3 changed files with 30 additions and 43 deletions

View File

@ -435,7 +435,7 @@ instrprof_error InstrProfRecord::merge(InstrProfRecord &Other) {
for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) { for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
bool ResultOverflowed; bool ResultOverflowed;
Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], ResultOverflowed); Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], &ResultOverflowed);
if (ResultOverflowed) if (ResultOverflowed)
Result = instrprof_error::counter_overflow; Result = instrprof_error::counter_overflow;
} }

View File

@ -659,38 +659,34 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
/// representable value of type T. /// representable value of type T.
template <typename T> template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type typename std::enable_if<std::is_unsigned<T>::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 // Hacker's Delight, p. 29
T Z = X + Y; T Z = X + Y;
ResultOverflowed = (Z < X || Z < Y); Overflowed = (Z < X || Z < Y);
if (ResultOverflowed) if (Overflowed)
return std::numeric_limits<T>::max(); return std::numeric_limits<T>::max();
else else
return Z; 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 T>
typename std::enable_if<std::is_unsigned<T>::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. /// \brief Multiply two unsigned integers, X and Y, of type T.
/// Clamp the result to the maximum representable value of T on overflow. /// Clamp the result to the maximum representable value of T on overflow.
/// ResultOverflowed indicates if the result is larger than the maximum /// ResultOverflowed indicates if the result is larger than the maximum
/// representable value of type T. /// representable value of type T.
template <typename T> template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type typename std::enable_if<std::is_unsigned<T>::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 // 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 // because it fails for uint16_t (where multiplication can have undefined
// behavior due to promotion to int), and requires a division in addition // behavior due to promotion to int), and requires a division in addition
// to the multiplication. // to the multiplication.
ResultOverflowed = false; Overflowed = false;
// Log2(Z) would be either Log2Z or Log2Z + 1. // Log2(Z) would be either Log2Z or Log2Z + 1.
// Special case: if X or Y is 0, Log2_64 gives -1, and Log2Z // 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; return X * Y;
} }
if (Log2Z > Log2Max) { if (Log2Z > Log2Max) {
ResultOverflowed = true; Overflowed = true;
return Max; return Max;
} }
@ -711,7 +707,7 @@ SaturatingMultiply(T X, T Y, bool &ResultOverflowed) {
// that on at the end. // that on at the end.
T Z = (X >> 1) * Y; T Z = (X >> 1) * Y;
if (Z & ~(Max >> 1)) { if (Z & ~(Max >> 1)) {
ResultOverflowed = true; Overflowed = true;
return Max; return Max;
} }
Z <<= 1; Z <<= 1;
@ -721,15 +717,6 @@ SaturatingMultiply(T X, T Y, bool &ResultOverflowed) {
return Z; 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 T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingMultiply(T X, T Y) {
bool ResultOverflowed;
return SaturatingMultiply(X, Y, ResultOverflowed);
}
extern const float huge_valf; extern const float huge_valf;
} // End llvm namespace } // End llvm namespace

View File

@ -197,23 +197,23 @@ void SaturatingAddTestHelper()
bool ResultOverflowed; bool ResultOverflowed;
EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(Max, T(1))); 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_TRUE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(T(1), Max)); 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_TRUE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingAdd(Max, Max)); EXPECT_EQ(Max, SaturatingAdd(Max, Max));
EXPECT_EQ(Max, SaturatingAdd(Max, Max, ResultOverflowed)); EXPECT_EQ(Max, SaturatingAdd(Max, Max, &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed); EXPECT_TRUE(ResultOverflowed);
} }
@ -232,45 +232,45 @@ void SaturatingMultiplyTestHelper()
// Test basic multiplication. // Test basic multiplication.
EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2))); 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); EXPECT_FALSE(ResultOverflowed);
// Test multiplication by zero. // Test multiplication by zero.
EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0))); 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_FALSE(ResultOverflowed);
EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max)); 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); EXPECT_FALSE(ResultOverflowed);
// Test multiplication by maximum value. // Test multiplication by maximum value.
EXPECT_EQ(Max, SaturatingMultiply(Max, T(2))); 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_TRUE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingMultiply(T(2), Max)); 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_TRUE(ResultOverflowed);
EXPECT_EQ(Max, SaturatingMultiply(Max, Max)); EXPECT_EQ(Max, SaturatingMultiply(Max, Max));
EXPECT_EQ(Max, SaturatingMultiply(Max, Max, ResultOverflowed)); EXPECT_EQ(Max, SaturatingMultiply(Max, Max, &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed); EXPECT_TRUE(ResultOverflowed);
// Test interesting boundary conditions for algorithm - // Test interesting boundary conditions for algorithm -
@ -286,11 +286,11 @@ void SaturatingMultiplyTestHelper()
if(OverflowExpected) { if(OverflowExpected) {
EXPECT_EQ(Max, SaturatingMultiply(X, Y)); EXPECT_EQ(Max, SaturatingMultiply(X, Y));
EXPECT_EQ(Max, SaturatingMultiply(X, Y, ResultOverflowed)); EXPECT_EQ(Max, SaturatingMultiply(X, Y, &ResultOverflowed));
EXPECT_TRUE(ResultOverflowed); EXPECT_TRUE(ResultOverflowed);
} else { } else {
EXPECT_EQ(X * Y, SaturatingMultiply(X, Y)); 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); EXPECT_FALSE(ResultOverflowed);
} }
} }