Index: lib/Support/APInt.cpp =================================================================== --- lib/Support/APInt.cpp +++ lib/Support/APInt.cpp @@ -1904,6 +1904,14 @@ } APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const { +#if __has_builtin(__builtin_smulll_overflow) + if (isSingleWord()) { + long long V; + Overflow = __builtin_smulll_overflow(U.VAL, RHS.U.VAL, &V); + return APInt(BitWidth, (uint64_t)V); + } +#endif + APInt Res = *this * RHS; if (*this != 0 && RHS != 0) @@ -1914,6 +1922,14 @@ } APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { +#if __has_builtin(__builtin_umulll_overflow) + if (isSingleWord()) { + unsigned long long V; + Overflow = __builtin_umulll_overflow(U.VAL, RHS.U.VAL, &V); + return APInt(BitWidth, V); + } +#endif + APInt Res = *this * RHS; if (*this != 0 && RHS != 0) Index: unittests/ADT/APIntTest.cpp =================================================================== --- unittests/ADT/APIntTest.cpp +++ unittests/ADT/APIntTest.cpp @@ -2381,6 +2381,65 @@ } } +TEST(APIntTest, smul_ov) { + const std::pair Overflows[] = { + {0x8000000000000000, 2}, + {0x8000000000000000, -1}, + {0x2aaaaaaaaaaaaaab, 3}, + {-0x2aaaaaaaaaaaaaab, 3}, + {0x80000000, 0x100000000}, + }; + + const std::pair NonOverflows[] = { + {-0x7fffffffffffffff, -1}, + {0x2aaaaaaaaaaaaaaa, 3}, + {-0x2aaaaaaaaaaaaaaa, 3}, + {0x7fffffff, 0x100000000}, + }; + + bool Overflow; + for (auto &X : Overflows) { + APInt A(64, X.first); + APInt B(64, X.second); + (void)A.smul_ov(B, Overflow); + EXPECT_TRUE(Overflow); + } + for (auto &X : NonOverflows) { + APInt A(64, X.first); + APInt B(64, X.second); + (void)A.smul_ov(B, Overflow); + EXPECT_FALSE(Overflow); + } +} + +TEST(APIntTest, umul_ov) { + const std::pair Overflows[] = { + {0x8000000000000000, 2}, + {0x5555555555555556, 3}, + {4294967296, 4294967296}, + {4294967295, 4294967298}, + }; + const std::pair NonOverflows[] = { + {0x7fffffffffffffff, 2}, + {0x5555555555555555, 3}, + {4294967295, 4294967297}, + }; + + bool Overflow; + for (auto &X : Overflows) { + APInt A(64, X.first); + APInt B(64, X.second); + (void)A.umul_ov(B, Overflow); + EXPECT_TRUE(Overflow); + } + for (auto &X : NonOverflows) { + APInt A(64, X.first); + APInt B(64, X.second); + (void)A.umul_ov(B, Overflow); + EXPECT_FALSE(Overflow); + } +} + TEST(APIntTest, SolveQuadraticEquationWrap) { // Verify that "Solution" is the first non-negative integer that solves // Ax^2 + Bx + C = "0 or overflow", i.e. that it is a correct solution