[llvm] r276470 - Use RValue refs in APInt add/sub methods.

Pete Cooper via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 22 13:55:46 PDT 2016


Author: pete
Date: Fri Jul 22 15:55:46 2016
New Revision: 276470

URL: http://llvm.org/viewvc/llvm-project?rev=276470&view=rev
Log:
Use RValue refs in APInt add/sub methods.

This adds versions of operator + and - which are optimized for the LHS/RHS of the
operator being RValue's.  When an RValue is available, we can use its storage space
instead of allocating new space.

On code such as ConstantRange which makes heavy use of APInt's over 64-bits in size,
this results in significant numbers of saved allocations.

Thanks to David Blaikie for all the review and most of the code here.

Modified:
    llvm/trunk/include/llvm/ADT/APInt.h
    llvm/trunk/lib/Support/APInt.cpp
    llvm/trunk/unittests/ADT/APIntTest.cpp

Modified: llvm/trunk/include/llvm/ADT/APInt.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=276470&r1=276469&r2=276470&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APInt.h (original)
+++ llvm/trunk/include/llvm/ADT/APInt.h Fri Jul 22 15:55:46 2016
@@ -40,6 +40,10 @@ const unsigned int host_char_bit = 8;
 const unsigned int integerPartWidth =
     host_char_bit * static_cast<unsigned int>(sizeof(integerPart));
 
+class APInt;
+
+inline APInt operator-(APInt);
+
 //===----------------------------------------------------------------------===//
 //                              APInt Class
 //===----------------------------------------------------------------------===//
@@ -620,18 +624,6 @@ public:
     return Result;
   }
 
-  /// \brief Unary negation operator
-  ///
-  /// Negates *this using two's complement logic.
-  ///
-  /// \returns An APInt value representing the negation of *this.
-  APInt operator-() const {
-    APInt Result(*this);
-    Result.flipAllBits();
-    ++Result;
-    return Result;
-  }
-
   /// \brief Logical negation operator.
   ///
   /// Performs logical negation operation on this APInt.
@@ -750,6 +742,7 @@ public:
   ///
   /// \returns *this
   APInt &operator+=(const APInt &RHS);
+  APInt &operator+=(uint64_t RHS);
 
   /// \brief Subtraction assignment operator.
   ///
@@ -757,6 +750,7 @@ public:
   ///
   /// \returns *this
   APInt &operator-=(const APInt &RHS);
+  APInt &operator-=(uint64_t RHS);
 
   /// \brief Left-shift assignment function.
   ///
@@ -836,18 +830,6 @@ public:
   /// Multiplies this APInt by RHS and returns the result.
   APInt operator*(const APInt &RHS) const;
 
-  /// \brief Addition operator.
-  ///
-  /// Adds RHS to this APInt and returns the result.
-  APInt operator+(const APInt &RHS) const;
-  APInt operator+(uint64_t RHS) const;
-
-  /// \brief Subtraction operator.
-  ///
-  /// Subtracts RHS from this APInt and returns the result.
-  APInt operator-(const APInt &RHS) const;
-  APInt operator-(uint64_t RHS) const;
-
   /// \brief Left logical shift operator.
   ///
   /// Shifts this APInt left by \p Bits and returns the result.
@@ -1532,7 +1514,9 @@ public:
 
   /// \returns the ceil log base 2 of this APInt.
   unsigned ceilLogBase2() const {
-    return BitWidth - (*this - 1).countLeadingZeros();
+    APInt temp(*this);
+    --temp;
+    return BitWidth - temp.countLeadingZeros();
   }
 
   /// \returns the nearest log base 2 of this APInt. Ties round up.
@@ -1750,6 +1734,55 @@ inline raw_ostream &operator<<(raw_ostre
   return OS;
 }
 
+inline APInt operator-(APInt v) {
+  v.flipAllBits();
+  ++v;
+  return v;
+}
+
+inline APInt operator+(APInt a, const APInt &b) {
+  a += b;
+  return a;
+}
+
+inline APInt operator+(const APInt &a, APInt &&b) {
+  b += a;
+  return std::move(b);
+}
+
+inline APInt operator+(APInt a, uint64_t RHS) {
+  a += RHS;
+  return a;
+}
+
+inline APInt operator+(uint64_t LHS, APInt b) {
+  b += LHS;
+  return b;
+}
+
+inline APInt operator-(APInt a, const APInt &b) {
+  a -= b;
+  return a;
+}
+
+inline APInt operator-(const APInt &a, APInt &&b) {
+  b = -std::move(b);
+  b += a;
+  return std::move(b);
+}
+
+inline APInt operator-(APInt a, uint64_t RHS) {
+  a -= RHS;
+  return a;
+}
+
+inline APInt operator-(uint64_t LHS, APInt b) {
+  b = -std::move(b);
+  b += LHS;
+  return b;
+}
+
+
 namespace APIntOps {
 
 /// \brief Determine the smaller of two APInts considered to be signed.

Modified: llvm/trunk/lib/Support/APInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=276470&r1=276469&r2=276470&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APInt.cpp (original)
+++ llvm/trunk/lib/Support/APInt.cpp Fri Jul 22 15:55:46 2016
@@ -260,6 +260,14 @@ APInt& APInt::operator+=(const APInt& RH
   return clearUnusedBits();
 }
 
+APInt& APInt::operator+=(uint64_t RHS) {
+  if (isSingleWord())
+    VAL += RHS;
+  else
+    add_1(pVal, pVal, getNumWords(), RHS);
+  return clearUnusedBits();
+}
+
 /// Subtracts the integer array y from the integer array x
 /// @returns returns the borrow out.
 /// @brief Generalized subtraction of 64-bit integer arrays.
@@ -286,6 +294,14 @@ APInt& APInt::operator-=(const APInt& RH
   return clearUnusedBits();
 }
 
+APInt& APInt::operator-=(uint64_t RHS) {
+  if (isSingleWord())
+    VAL -= RHS;
+  else
+    sub_1(pVal, getNumWords(), RHS);
+  return clearUnusedBits();
+}
+
 /// Multiplies an integer array, x, by a uint64_t integer and places the result
 /// into dest.
 /// @returns the carry out of the multiplication.
@@ -470,44 +486,6 @@ APInt APInt::operator*(const APInt& RHS)
   return Result;
 }
 
-APInt APInt::operator+(const APInt& RHS) const {
-  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
-  if (isSingleWord())
-    return APInt(BitWidth, VAL + RHS.VAL);
-  APInt Result(BitWidth, 0);
-  add(Result.pVal, this->pVal, RHS.pVal, getNumWords());
-  Result.clearUnusedBits();
-  return Result;
-}
-
-APInt APInt::operator+(uint64_t RHS) const {
-  if (isSingleWord())
-    return APInt(BitWidth, VAL + RHS);
-  APInt Result(*this);
-  add_1(Result.pVal, Result.pVal, getNumWords(), RHS);
-  Result.clearUnusedBits();
-  return Result;
-}
-
-APInt APInt::operator-(const APInt& RHS) const {
-  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
-  if (isSingleWord())
-    return APInt(BitWidth, VAL - RHS.VAL);
-  APInt Result(BitWidth, 0);
-  sub(Result.pVal, this->pVal, RHS.pVal, getNumWords());
-  Result.clearUnusedBits();
-  return Result;
-}
-
-APInt APInt::operator-(uint64_t RHS) const {
-  if (isSingleWord())
-    return APInt(BitWidth, VAL - RHS);
-  APInt Result(*this);
-  sub_1(Result.pVal, getNumWords(), RHS);
-  Result.clearUnusedBits();
-  return Result;
-}
-
 bool APInt::EqualSlowCase(const APInt& RHS) const {
   return std::equal(pVal, pVal + getNumWords(), RHS.pVal);
 }

Modified: llvm/trunk/unittests/ADT/APIntTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=276470&r1=276469&r2=276470&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APIntTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APIntTest.cpp Fri Jul 22 15:55:46 2016
@@ -416,6 +416,175 @@ TEST(APIntTest, compareLargeIntegers) {
   EXPECT_TRUE(!MinusTwo.slt(MinusTwo));
 }
 
+TEST(APIntTest, rvalue_arithmetic) {
+  // Test all combinations of lvalue/rvalue lhs/rhs of add/sub
+
+  // Lamdba to return an APInt by value, but also provide the raw value of the
+  // allocated data.
+  auto getRValue = [](const char *HexString, uint64_t const *&RawData) {
+    APInt V(129, HexString, 16);
+    RawData = V.getRawData();
+    return V;
+  };
+
+  APInt One(129, "1", 16);
+  APInt Two(129, "2", 16);
+  APInt Three(129, "3", 16);
+  APInt MinusOne = -One;
+
+  const uint64_t *RawDataL = nullptr;
+  const uint64_t *RawDataR = nullptr;
+
+  {
+    // 1 + 1 = 2
+    APInt AddLL = One + One;
+    EXPECT_EQ(AddLL, Two);
+
+    APInt AddLR = One + getRValue("1", RawDataR);
+    EXPECT_EQ(AddLR, Two);
+    EXPECT_EQ(AddLR.getRawData(), RawDataR);
+
+    APInt AddRL = getRValue("1", RawDataL) + One;
+    EXPECT_EQ(AddRL, Two);
+    EXPECT_EQ(AddRL.getRawData(), RawDataL);
+
+    APInt AddRR = getRValue("1", RawDataL) + getRValue("1", RawDataR);
+    EXPECT_EQ(AddRR, Two);
+    EXPECT_EQ(AddRR.getRawData(), RawDataR);
+
+    // LValue's and constants
+    APInt AddLK = One + 1;
+    EXPECT_EQ(AddLK, Two);
+
+    APInt AddKL = 1 + One;
+    EXPECT_EQ(AddKL, Two);
+
+    // RValue's and constants
+    APInt AddRK = getRValue("1", RawDataL) + 1;
+    EXPECT_EQ(AddRK, Two);
+    EXPECT_EQ(AddRK.getRawData(), RawDataL);
+
+    APInt AddKR = 1 + getRValue("1", RawDataR);
+    EXPECT_EQ(AddKR, Two);
+    EXPECT_EQ(AddKR.getRawData(), RawDataR);
+  }
+
+  {
+    // 0x0,FFFF...FFFF + 0x2 = 0x100...0001
+    APInt AllOnes(129, "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);
+    APInt HighOneLowOne(129, "100000000000000000000000000000001", 16);
+
+    APInt AddLL = AllOnes + Two;
+    EXPECT_EQ(AddLL, HighOneLowOne);
+
+    APInt AddLR = AllOnes + getRValue("2", RawDataR);
+    EXPECT_EQ(AddLR, HighOneLowOne);
+    EXPECT_EQ(AddLR.getRawData(), RawDataR);
+
+    APInt AddRL = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) + Two;
+    EXPECT_EQ(AddRL, HighOneLowOne);
+    EXPECT_EQ(AddRL.getRawData(), RawDataL);
+
+    APInt AddRR = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) +
+                  getRValue("2", RawDataR);
+    EXPECT_EQ(AddRR, HighOneLowOne);
+    EXPECT_EQ(AddRR.getRawData(), RawDataR);
+
+    // LValue's and constants
+    APInt AddLK = AllOnes + 2;
+    EXPECT_EQ(AddLK, HighOneLowOne);
+
+    APInt AddKL = 2 + AllOnes;
+    EXPECT_EQ(AddKL, HighOneLowOne);
+
+    // RValue's and constants
+    APInt AddRK = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) + 2;
+    EXPECT_EQ(AddRK, HighOneLowOne);
+    EXPECT_EQ(AddRK.getRawData(), RawDataL);
+
+    APInt AddKR = 2 + getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+    EXPECT_EQ(AddKR, HighOneLowOne);
+    EXPECT_EQ(AddKR.getRawData(), RawDataR);
+  }
+
+  {
+    // 2 - 1 = 1
+    APInt SubLL = Two - One;
+    EXPECT_EQ(SubLL, One);
+
+    APInt SubLR = Two - getRValue("1", RawDataR);
+    EXPECT_EQ(SubLR, One);
+    EXPECT_EQ(SubLR.getRawData(), RawDataR);
+
+    APInt SubRL = getRValue("2", RawDataL) - One;
+    EXPECT_EQ(SubRL, One);
+    EXPECT_EQ(SubRL.getRawData(), RawDataL);
+
+    APInt SubRR = getRValue("2", RawDataL) - getRValue("1", RawDataR);
+    EXPECT_EQ(SubRR, One);
+    EXPECT_EQ(SubRR.getRawData(), RawDataR);
+
+    // LValue's and constants
+    APInt SubLK = Two - 1;
+    EXPECT_EQ(SubLK, One);
+
+    APInt SubKL = 2 - One;
+    EXPECT_EQ(SubKL, One);
+
+    // RValue's and constants
+    APInt SubRK = getRValue("2", RawDataL) - 1;
+    EXPECT_EQ(SubRK, One);
+    EXPECT_EQ(SubRK.getRawData(), RawDataL);
+
+    APInt SubKR = 2 - getRValue("1", RawDataR);
+    EXPECT_EQ(SubKR, One);
+    EXPECT_EQ(SubKR.getRawData(), RawDataR);
+  }
+
+  {
+    // 0x100...0001 - 0x0,FFFF...FFFF = 0x2
+    APInt AllOnes(129, "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);
+    APInt HighOneLowOne(129, "100000000000000000000000000000001", 16);
+
+    APInt SubLL = HighOneLowOne - AllOnes;
+    EXPECT_EQ(SubLL, Two);
+
+    APInt SubLR = HighOneLowOne -
+                  getRValue("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+    EXPECT_EQ(SubLR, Two);
+    EXPECT_EQ(SubLR.getRawData(), RawDataR);
+
+    APInt SubRL = getRValue("100000000000000000000000000000001", RawDataL) -
+                  AllOnes;
+    EXPECT_EQ(SubRL, Two);
+    EXPECT_EQ(SubRL.getRawData(), RawDataL);
+
+    APInt SubRR = getRValue("100000000000000000000000000000001", RawDataL) -
+                  getRValue("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+    EXPECT_EQ(SubRR, Two);
+    EXPECT_EQ(SubRR.getRawData(), RawDataR);
+
+    // LValue's and constants
+    // 0x100...0001 - 0x2 = 0x0,FFFF...FFFF
+    APInt SubLK = HighOneLowOne - 2;
+    EXPECT_EQ(SubLK, AllOnes);
+
+    // 2 - (-1) = 3
+    APInt SubKL = 2 - MinusOne;
+    EXPECT_EQ(SubKL, Three);
+
+    // RValue's and constants
+    // 0x100...0001 - 0x2 = 0x0,FFFF...FFFF
+    APInt SubRK = getRValue("100000000000000000000000000000001", RawDataL) - 2;
+    EXPECT_EQ(SubRK, AllOnes);
+    EXPECT_EQ(SubRK.getRawData(), RawDataL);
+
+    APInt SubKR = 2 - getRValue("1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+    EXPECT_EQ(SubKR, Three);
+    EXPECT_EQ(SubKR.getRawData(), RawDataR);
+  }
+}
+
 
 // Tests different div/rem varaints using scheme (a * b + c) / a
 void testDiv(APInt a, APInt b, APInt c) {




More information about the llvm-commits mailing list