diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h index de2813094a950..6beaafeb53f89 100644 --- a/llvm/include/llvm/Support/MathExtras.h +++ b/llvm/include/llvm/Support/MathExtras.h @@ -601,24 +601,39 @@ constexpr T AbsoluteDifference(U X, V Y) { return X > Y ? (X - Y) : (Y - X); } -/// 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 +/// Add two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. +template +std::enable_if_t, T> SaturatingAdd(T X, T Y) { + T Z = X + Y; + // Z < X and Z < Y are equivalent overflow checks, so one suffices + return Z | -(Z < X); +} + +/// Add two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. Overflowed indicates if /// the result is larger than the maximum representable value of type T. template -std::enable_if_t, T> -SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) { - bool Dummy; - bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy; - // Hacker's Delight, p. 29 +std::enable_if_t, T> SaturatingAdd(T X, T Y, + bool &Overflowed) { T Z = X + Y; - Overflowed = (Z < X || Z < Y); - if (Overflowed) - return std::numeric_limits::max(); - else - return Z; + // Z < X and Z < Y are equivalent overflow checks, so one suffices + Overflowed = (Z < X); + return Z | -Overflowed; +} + +/// Add two unsigned integers, X and Y, of type T. Clamp the result to the +/// maximum representable value of T on overflow. Overflowed indicates if +/// the result is larger than the maximum representable value of type T. +template +std::enable_if_t, T> SaturatingAdd(T X, T Y, + bool *Overflowed) { + bool Dummy; + bool &OverflowedRef = Overflowed ? *Overflowed : Dummy; + return SaturatingAdd(X, Y, OverflowedRef); } -/// Add multiple unsigned integers of type T. Clamp the result to the +/// Add multiple unsigned integers of type T. Clamp the result to the /// maximum representable value of T on overflow. template std::enable_if_t, T> SaturatingAdd(T X, T Y, T Z, @@ -670,7 +685,7 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) { } Z <<= 1; if (X & 1) - return SaturatingAdd(Z, Y, ResultOverflowed); + return SaturatingAdd(Z, Y, Overflowed); return Z; } @@ -689,7 +704,7 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) { if (Overflowed) return Product; - return SaturatingAdd(A, Product, &Overflowed); + return SaturatingAdd(A, Product, Overflowed); } /// Use this rather than HUGE_VALF; the latter causes warnings on MSVC. diff --git a/llvm/lib/IR/DIExpressionOptimizer.cpp b/llvm/lib/IR/DIExpressionOptimizer.cpp index be9e13a34235a..069991f60c08e 100644 --- a/llvm/lib/IR/DIExpressionOptimizer.cpp +++ b/llvm/lib/IR/DIExpressionOptimizer.cpp @@ -48,7 +48,7 @@ foldOperationIfPossible(uint64_t Const1, uint64_t Const2, bool ResultOverflowed; switch (Operator) { case dwarf::DW_OP_plus: { - auto Result = SaturatingAdd(Const1, Const2, &ResultOverflowed); + auto Result = SaturatingAdd(Const1, Const2, ResultOverflowed); if (ResultOverflowed) return std::nullopt; return Result; diff --git a/llvm/unittests/Support/MathExtrasTest.cpp b/llvm/unittests/Support/MathExtrasTest.cpp index 27e8b26e8801d..84b00c771785d 100644 --- a/llvm/unittests/Support/MathExtrasTest.cpp +++ b/llvm/unittests/Support/MathExtrasTest.cpp @@ -237,23 +237,23 @@ template 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); EXPECT_EQ(T(6), SaturatingAdd(T(1), T(2), T(3)));