llvm.org GIT mirror llvm / b97b302
Add checkMulAdd helper function to CheckedArithmetic Multiplication followed by addition (https://en.wikipedia.org/wiki/Multiply–accumulate_operation) is a sufficiently common use-case to warrant a separate helper. Differential Revision: https://reviews.llvm.org/D48138 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334635 91177308-0d34-0410-b5e6-96231b3b80d8 George Karpenkov 1 year, 4 months ago
2 changed file(s) with 45 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
5656 return checkedOp(LHS, RHS, &llvm::APInt::smul_ov);
5757 }
5858
59 /// Multiply A and B, and add C to the resulting product.
60 /// Return the value if available, None if overflowing.
61 template
62 typename std::enable_if::value, llvm::Optional>::type
63 checkedMulAdd(T A, T B, T C) {
64 if (auto Product = checkedMul(A, B))
65 return checkedAdd(*Product, C);
66 return llvm::None;
67 }
68
5969 /// Add two unsigned integers \p LHS and \p RHS, return wrapped result
6070 /// if available.
6171 template
7282 return checkedOp(LHS, RHS, &llvm::APInt::umul_ov, /*Signed=*/false);
7383 }
7484
85 /// Multiply unsigned A and B, and add C to the resulting product.
86 /// Return the value if available, None if overflowing.
87 template
88 typename std::enable_if::value, llvm::Optional>::type
89 checkedMulAddUnsigned(T A, T B, T C) {
90 if (auto Product = checkedMulUnsigned(A, B))
91 return checkedAddUnsigned(*Product, C);
92 return llvm::None;
93 }
94
7595 } // End llvm namespace
7696
7797 #endif
3131 EXPECT_EQ(checkedMul(10, 2), Optional(20));
3232 }
3333
34 TEST(CheckedArithmetic, CheckedMulAdd) {
35 const int64_t Max = std::numeric_limits::max();
36 const int64_t Min = std::numeric_limits::min();
37 EXPECT_EQ(checkedMulAdd(Max, 1, 2), None);
38 EXPECT_EQ(checkedMulAdd(1, 1, Max), None);
39 EXPECT_EQ(checkedMulAdd(1, -1, Min), None);
40 EXPECT_EQ(checkedMulAdd(10, 2, 3), Optional(23));
41 }
42
3443 TEST(CheckedArithmetic, CheckedMulSmall) {
3544 const int16_t Max = std::numeric_limits::max();
3645 const int16_t Min = std::numeric_limits::min();
3847 EXPECT_EQ(checkedMul(Max, Max), None);
3948 EXPECT_EQ(checkedMul(Min, 2), None);
4049 EXPECT_EQ(checkedMul(10, 2), Optional(20));
50 }
51
52 TEST(CheckedArithmetic, CheckedMulAddSmall) {
53 const int16_t Max = std::numeric_limits::max();
54 const int16_t Min = std::numeric_limits::min();
55 EXPECT_EQ(checkedMulAdd(Max, 1, 2), None);
56 EXPECT_EQ(checkedMulAdd(1, 1, Max), None);
57 EXPECT_EQ(checkedMulAdd(1, -1, Min), None);
58 EXPECT_EQ(checkedMulAdd(10, 2, 3), Optional(23));
4159 }
4260
4361 TEST(CheckedArithmetic, CheckedAddUnsigned) {
5472 EXPECT_EQ(checkedMulUnsigned(10, 2), Optional(20));
5573 }
5674
75 TEST(CheckedArithmetic, CheckedMulAddUnsigned) {
76 const uint64_t Max = std::numeric_limits::max();
77 EXPECT_EQ(checkedMulAddUnsigned(Max, 1, 2), None);
78 EXPECT_EQ(checkedMulAddUnsigned(1, 1, Max), None);
79 EXPECT_EQ(checkedMulAddUnsigned(10, 2, 3), Optional(23));
80 }
81
5782
5883 } // namespace