diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 879bdfaf57d..c26d4829275 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -542,32 +542,16 @@ bool APInt::slt(const APInt& RHS) const { return lhsSext < rhsSext; } - APInt lhs(*this); - APInt rhs(RHS); bool lhsNeg = isNegative(); - bool rhsNeg = rhs.isNegative(); - if (lhsNeg) { - // Sign bit is set so perform two's complement to make it positive - lhs.flipAllBits(); - ++lhs; - } - if (rhsNeg) { - // Sign bit is set so perform two's complement to make it positive - rhs.flipAllBits(); - ++rhs; - } + bool rhsNeg = RHS.isNegative(); - // Now we have unsigned values to compare so do the comparison if necessary - // based on the negativeness of the values. - if (lhsNeg) - if (rhsNeg) - return lhs.ugt(rhs); - else - return true; - else if (rhsNeg) - return false; - else - return lhs.ult(rhs); + // If the sign bits don't match, then (LHS < RHS) if LHS is negative + if (lhsNeg != rhsNeg) + return lhsNeg; + + // Otherwise we can just use an unsigned comparision, because even negative + // numbers compare correctly this way if both have the same signed-ness. + return ult(RHS); } void APInt::setBit(unsigned bitPosition) { diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 98504b762a1..b0d80c3c681 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -388,6 +388,34 @@ TEST(APIntTest, compareWithHalfInt64Max) { EXPECT_TRUE( a.sge(edgeM1)); } +TEST(APIntTest, compareLargeIntegers) { + // Make sure all the combinations of signed comparisons work with big ints. + auto One = APInt{128, static_cast(1), true}; + auto Two = APInt{128, static_cast(2), true}; + auto MinusOne = APInt{128, static_cast(-1), true}; + auto MinusTwo = APInt{128, static_cast(-2), true}; + + EXPECT_TRUE(!One.slt(One)); + EXPECT_TRUE(!Two.slt(One)); + EXPECT_TRUE(MinusOne.slt(One)); + EXPECT_TRUE(MinusTwo.slt(One)); + + EXPECT_TRUE(One.slt(Two)); + EXPECT_TRUE(!Two.slt(Two)); + EXPECT_TRUE(MinusOne.slt(Two)); + EXPECT_TRUE(MinusTwo.slt(Two)); + + EXPECT_TRUE(!One.slt(MinusOne)); + EXPECT_TRUE(!Two.slt(MinusOne)); + EXPECT_TRUE(!MinusOne.slt(MinusOne)); + EXPECT_TRUE(MinusTwo.slt(MinusOne)); + + EXPECT_TRUE(!One.slt(MinusTwo)); + EXPECT_TRUE(!Two.slt(MinusTwo)); + EXPECT_TRUE(!MinusOne.slt(MinusTwo)); + EXPECT_TRUE(!MinusTwo.slt(MinusTwo)); +} + // Tests different div/rem varaints using scheme (a * b + c) / a void testDiv(APInt a, APInt b, APInt c) {