OSDN Git Service

Don't allocate in APInt::slt. NFC.
authorPete Cooper <peter_cooper@apple.com>
Thu, 26 May 2016 17:40:07 +0000 (17:40 +0000)
committerPete Cooper <peter_cooper@apple.com>
Thu, 26 May 2016 17:40:07 +0000 (17:40 +0000)
APInt::slt was copying the LHS and RHS in to temporaries then making
them unsigned so that it could use an unsigned comparision.  It did
this even on the paths which were trivial to give results for, such
as the sign bit of the LHS being set while RHS was not set.

This changes the logic to return out immediately in the trivial cases,
and use an unsigned comparison in the remaining cases.  But this time,
just use the unsigned comparison directly without creating any temporaries.

This works because, for example:
  true = (-2 slt -1) = (0xFE ult 0xFF)

Also added some tests explicitly for slt with APInt's larger than 64-bits
so that this new code is tested.

Using the memory for 'opt -O2 verify-uselistorder.lto.opt.bc -o opt.bc'
(see r236629 for details), this reduces the number of allocations from
26.8M to 23.9M.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270881 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/APInt.cpp
unittests/ADT/APIntTest.cpp

index 879bdfa..c26d482 100644 (file)
@@ -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;
-  }
-
-  // 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);
+  bool rhsNeg = RHS.isNegative();
+
+  // 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) {
index 98504b7..b0d80c3 100644 (file)
@@ -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<uint64_t>(1), true};
+  auto Two = APInt{128, static_cast<uint64_t>(2), true};
+  auto MinusOne = APInt{128, static_cast<uint64_t>(-1), true};
+  auto MinusTwo = APInt{128, static_cast<uint64_t>(-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) {