forked from OSchip/llvm-project
[APInt] Add methods for saturated add and sub
This adds the sadd_sat, uadd_sat, ssub_sat, usub_sat methods for performing saturating additions and subtractions to APInt. Split out from D54237. Patch by: nikic (Nikita Popov) Differential Revision: https://reviews.llvm.org/D54332 llvm-svn: 347324
This commit is contained in:
parent
8ce71fb2c7
commit
7ef0b31389
|
@ -1105,6 +1105,12 @@ public:
|
|||
APInt sshl_ov(const APInt &Amt, bool &Overflow) const;
|
||||
APInt ushl_ov(const APInt &Amt, bool &Overflow) const;
|
||||
|
||||
// Operations that saturate
|
||||
APInt sadd_sat(const APInt &RHS) const;
|
||||
APInt uadd_sat(const APInt &RHS) const;
|
||||
APInt ssub_sat(const APInt &RHS) const;
|
||||
APInt usub_sat(const APInt &RHS) const;
|
||||
|
||||
/// Array-indexing support.
|
||||
///
|
||||
/// \returns the bit value at bitPosition
|
||||
|
|
|
@ -1947,7 +1947,43 @@ APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const {
|
|||
return *this << ShAmt;
|
||||
}
|
||||
|
||||
APInt APInt::sadd_sat(const APInt &RHS) const {
|
||||
bool Overflow;
|
||||
APInt Res = sadd_ov(RHS, Overflow);
|
||||
if (!Overflow)
|
||||
return Res;
|
||||
|
||||
return isNegative() ? APInt::getSignedMinValue(BitWidth)
|
||||
: APInt::getSignedMaxValue(BitWidth);
|
||||
}
|
||||
|
||||
APInt APInt::uadd_sat(const APInt &RHS) const {
|
||||
bool Overflow;
|
||||
APInt Res = uadd_ov(RHS, Overflow);
|
||||
if (!Overflow)
|
||||
return Res;
|
||||
|
||||
return APInt::getMaxValue(BitWidth);
|
||||
}
|
||||
|
||||
APInt APInt::ssub_sat(const APInt &RHS) const {
|
||||
bool Overflow;
|
||||
APInt Res = ssub_ov(RHS, Overflow);
|
||||
if (!Overflow)
|
||||
return Res;
|
||||
|
||||
return isNegative() ? APInt::getSignedMinValue(BitWidth)
|
||||
: APInt::getSignedMaxValue(BitWidth);
|
||||
}
|
||||
|
||||
APInt APInt::usub_sat(const APInt &RHS) const {
|
||||
bool Overflow;
|
||||
APInt Res = usub_ov(RHS, Overflow);
|
||||
if (!Overflow)
|
||||
return Res;
|
||||
|
||||
return APInt(BitWidth, 0);
|
||||
}
|
||||
|
||||
|
||||
void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
|
||||
|
|
|
@ -1176,6 +1176,30 @@ TEST(APIntTest, fromString) {
|
|||
EXPECT_EQ(APInt(32, uint64_t(-72LL)), APInt(32, "-20", 36));
|
||||
}
|
||||
|
||||
TEST(APIntTest, SaturatingMath) {
|
||||
APInt AP_10 = APInt(8, 10);
|
||||
APInt AP_100 = APInt(8, 100);
|
||||
APInt AP_200 = APInt(8, 200);
|
||||
|
||||
EXPECT_EQ(APInt(8, 200), AP_100.uadd_sat(AP_100));
|
||||
EXPECT_EQ(APInt(8, 255), AP_100.uadd_sat(AP_200));
|
||||
EXPECT_EQ(APInt(8, 255), APInt(8, 255).uadd_sat(APInt(8, 255)));
|
||||
|
||||
EXPECT_EQ(APInt(8, 110), AP_10.sadd_sat(AP_100));
|
||||
EXPECT_EQ(APInt(8, 127), AP_100.sadd_sat(AP_100));
|
||||
EXPECT_EQ(APInt(8, -128), (-AP_100).sadd_sat(-AP_100));
|
||||
EXPECT_EQ(APInt(8, -128), APInt(8, -128).sadd_sat(APInt(8, -128)));
|
||||
|
||||
EXPECT_EQ(APInt(8, 90), AP_100.usub_sat(AP_10));
|
||||
EXPECT_EQ(APInt(8, 0), AP_100.usub_sat(AP_200));
|
||||
EXPECT_EQ(APInt(8, 0), APInt(8, 0).usub_sat(APInt(8, 255)));
|
||||
|
||||
EXPECT_EQ(APInt(8, -90), AP_10.ssub_sat(AP_100));
|
||||
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)));
|
||||
}
|
||||
|
||||
TEST(APIntTest, FromArray) {
|
||||
EXPECT_EQ(APInt(32, uint64_t(1)), APInt(32, ArrayRef<uint64_t>(1)));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue