[PATCH] D15385: [Support] Add saturating multiply-add support function
Nathan Slingerland via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 9 10:51:36 PST 2015
slingn created this revision.
slingn added reviewers: davidxl, silvas.
slingn added a subscriber: llvm-commits.
Add SaturatingMultiplyAdd convenience function template since A + (X * Y) comes up frequently when doing weighted arithmetic.
http://reviews.llvm.org/D15385
Files:
include/llvm/Support/MathExtras.h
unittests/Support/MathExtrasTest.cpp
Index: unittests/Support/MathExtrasTest.cpp
===================================================================
--- unittests/Support/MathExtrasTest.cpp
+++ unittests/Support/MathExtrasTest.cpp
@@ -304,4 +304,66 @@
SaturatingMultiplyTestHelper<uint64_t>();
}
+template<typename T>
+void SaturatingMultiplyAddTestHelper()
+{
+ const T Max = std::numeric_limits<T>::max();
+ bool ResultOverflowed;
+
+ // Test basic multiply-add.
+ EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10)));
+ EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ // Test multiply overflows, add doesn't overflow
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(0), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test multiply doesn't overflow, add overflows
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test multiply-add with Max as operand
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max));
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), Max, T(1)));
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), Max, T(1), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(1)));
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(1), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, Max));
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test multiply-add with 0 as operand
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(1), T(0)));
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(1), T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(0), T(1)));
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(0), T(1), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(0), T(0), T(1)));
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(0), T(0), T(1), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(0), SaturatingMultiplyAdd(T(0), T(0), T(0)));
+ EXPECT_EQ(T(0), SaturatingMultiplyAdd(T(0), T(0), T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+}
+
+TEST(MathExtras, SaturatingMultiplyAdd) {
+ SaturatingMultiplyAddTestHelper<uint8_t>();
+ SaturatingMultiplyAddTestHelper<uint16_t>();
+ SaturatingMultiplyAddTestHelper<uint32_t>();
+ SaturatingMultiplyAddTestHelper<uint64_t>();
+}
+
}
Index: include/llvm/Support/MathExtras.h
===================================================================
--- include/llvm/Support/MathExtras.h
+++ include/llvm/Support/MathExtras.h
@@ -717,6 +717,24 @@
return Z;
}
+/// \brief Multiply two unsigned integers, X and Y, of type T. Add the
+/// unsigned integer, A, also of type T, to the product.
+/// 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 T>
+typename std::enable_if<std::is_unsigned<T>::value, T>::type
+SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
+ bool Dummy;
+ bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
+
+ T Product = SaturatingMultiply(X, Y, &Overflowed);
+ if (Overflowed)
+ return Product;
+
+ return SaturatingAdd(A, Product, &Overflowed);
+}
+
extern const float huge_valf;
} // End llvm namespace
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D15385.42319.patch
Type: text/x-patch
Size: 3672 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151209/bc095ad3/attachment.bin>
More information about the llvm-commits
mailing list