[APInt] Add saturating multiply ops

Summary:
There are `*_ov()` functions already, so at least for consistency it may be good to also have saturating variants.
These may or may not be needed for `ConstantRange`'s `mulWithNoWrap()`

Reviewers: spatel, nikic

Reviewed By: nikic

Subscribers: hiraditya, dexonsmith, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D69397
This commit is contained in:
Roman Lebedev 2019-10-25 18:17:38 +03:00
parent 59a51d84b3
commit b2c184458e
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
3 changed files with 41 additions and 0 deletions

View File

@ -1109,6 +1109,8 @@ public:
APInt uadd_sat(const APInt &RHS) const;
APInt ssub_sat(const APInt &RHS) const;
APInt usub_sat(const APInt &RHS) const;
APInt smul_sat(const APInt &RHS) const;
APInt umul_sat(const APInt &RHS) const;
/// Array-indexing support.
///

View File

@ -2048,6 +2048,27 @@ APInt APInt::usub_sat(const APInt &RHS) const {
return APInt(BitWidth, 0);
}
APInt APInt::smul_sat(const APInt &RHS) const {
bool Overflow;
APInt Res = smul_ov(RHS, Overflow);
if (!Overflow)
return Res;
// The result is negative if one and only one of inputs is negative.
bool ResIsNegative = isNegative() ^ RHS.isNegative();
return ResIsNegative ? APInt::getSignedMinValue(BitWidth)
: APInt::getSignedMaxValue(BitWidth);
}
APInt APInt::umul_sat(const APInt &RHS) const {
bool Overflow;
APInt Res = umul_ov(RHS, Overflow);
if (!Overflow)
return Res;
return APInt::getMaxValue(BitWidth);
}
void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
// Check our assumptions here

View File

@ -1197,6 +1197,24 @@ TEST(APIntTest, SaturatingMath) {
EXPECT_EQ(APInt(8, 127), AP_100.ssub_sat(-AP_100));
EXPECT_EQ(APInt(8, -128), (-AP_100).ssub_sat(AP_100));
EXPECT_EQ(APInt(8, -128), APInt(8, -128).ssub_sat(APInt(8, 127)));
EXPECT_EQ(APInt(8, 250), APInt(8, 50).umul_sat(APInt(8, 5)));
EXPECT_EQ(APInt(8, 255), APInt(8, 50).umul_sat(APInt(8, 6)));
EXPECT_EQ(APInt(8, 255), APInt(8, -128).umul_sat(APInt(8, 3)));
EXPECT_EQ(APInt(8, 255), APInt(8, 3).umul_sat(APInt(8, -128)));
EXPECT_EQ(APInt(8, 255), APInt(8, -128).umul_sat(APInt(8, -128)));
EXPECT_EQ(APInt(8, 125), APInt(8, 25).smul_sat(APInt(8, 5)));
EXPECT_EQ(APInt(8, 127), APInt(8, 25).smul_sat(APInt(8, 6)));
EXPECT_EQ(APInt(8, 127), APInt(8, 127).smul_sat(APInt(8, 127)));
EXPECT_EQ(APInt(8, -125), APInt(8, -25).smul_sat(APInt(8, 5)));
EXPECT_EQ(APInt(8, -125), APInt(8, 25).smul_sat(APInt(8, -5)));
EXPECT_EQ(APInt(8, 125), APInt(8, -25).smul_sat(APInt(8, -5)));
EXPECT_EQ(APInt(8, 125), APInt(8, 25).smul_sat(APInt(8, 5)));
EXPECT_EQ(APInt(8, -128), APInt(8, -25).smul_sat(APInt(8, 6)));
EXPECT_EQ(APInt(8, -128), APInt(8, 25).smul_sat(APInt(8, -6)));
EXPECT_EQ(APInt(8, 127), APInt(8, -25).smul_sat(APInt(8, -6)));
EXPECT_EQ(APInt(8, 127), APInt(8, 25).smul_sat(APInt(8, 6)));
}
TEST(APIntTest, FromArray) {