<div dir="ltr">Another thought that occurred to me: If APInt doesn't have a small-size optimization (which I'm guessing it doesn't, if you're trying to avoid constructing and disposing of an APInt from a uint64_t), perhaps adding one would address these same issues without the proliferation of operator overloads, etc. But might be a bit more work, etc.</div><br><div class="gmail_quote"><div dir="ltr">On Fri, Jul 22, 2016 at 2:03 PM Pete Cooper via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: pete<br>
Date: Fri Jul 22 15:55:46 2016<br>
New Revision: 276470<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=276470&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=276470&view=rev</a><br>
Log:<br>
Use RValue refs in APInt add/sub methods.<br>
<br>
This adds versions of operator + and - which are optimized for the LHS/RHS of the<br>
operator being RValue's.  When an RValue is available, we can use its storage space<br>
instead of allocating new space.<br>
<br>
On code such as ConstantRange which makes heavy use of APInt's over 64-bits in size,<br>
this results in significant numbers of saved allocations.<br>
<br>
Thanks to David Blaikie for all the review and most of the code here.<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/ADT/APInt.h<br>
    llvm/trunk/lib/Support/APInt.cpp<br>
    llvm/trunk/unittests/ADT/APIntTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/ADT/APInt.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=276470&r1=276469&r2=276470&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APInt.h?rev=276470&r1=276469&r2=276470&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ADT/APInt.h (original)<br>
+++ llvm/trunk/include/llvm/ADT/APInt.h Fri Jul 22 15:55:46 2016<br>
@@ -40,6 +40,10 @@ const unsigned int host_char_bit = 8;<br>
 const unsigned int integerPartWidth =<br>
     host_char_bit * static_cast<unsigned int>(sizeof(integerPart));<br>
<br>
+class APInt;<br>
+<br>
+inline APInt operator-(APInt);<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 //                              APInt Class<br>
 //===----------------------------------------------------------------------===//<br>
@@ -620,18 +624,6 @@ public:<br>
     return Result;<br>
   }<br>
<br>
-  /// \brief Unary negation operator<br>
-  ///<br>
-  /// Negates *this using two's complement logic.<br>
-  ///<br>
-  /// \returns An APInt value representing the negation of *this.<br>
-  APInt operator-() const {<br>
-    APInt Result(*this);<br>
-    Result.flipAllBits();<br>
-    ++Result;<br>
-    return Result;<br>
-  }<br>
-<br>
   /// \brief Logical negation operator.<br>
   ///<br>
   /// Performs logical negation operation on this APInt.<br>
@@ -750,6 +742,7 @@ public:<br>
   ///<br>
   /// \returns *this<br>
   APInt &operator+=(const APInt &RHS);<br>
+  APInt &operator+=(uint64_t RHS);<br>
<br>
   /// \brief Subtraction assignment operator.<br>
   ///<br>
@@ -757,6 +750,7 @@ public:<br>
   ///<br>
   /// \returns *this<br>
   APInt &operator-=(const APInt &RHS);<br>
+  APInt &operator-=(uint64_t RHS);<br>
<br>
   /// \brief Left-shift assignment function.<br>
   ///<br>
@@ -836,18 +830,6 @@ public:<br>
   /// Multiplies this APInt by RHS and returns the result.<br>
   APInt operator*(const APInt &RHS) const;<br>
<br>
-  /// \brief Addition operator.<br>
-  ///<br>
-  /// Adds RHS to this APInt and returns the result.<br>
-  APInt operator+(const APInt &RHS) const;<br>
-  APInt operator+(uint64_t RHS) const;<br>
-<br>
-  /// \brief Subtraction operator.<br>
-  ///<br>
-  /// Subtracts RHS from this APInt and returns the result.<br>
-  APInt operator-(const APInt &RHS) const;<br>
-  APInt operator-(uint64_t RHS) const;<br>
-<br>
   /// \brief Left logical shift operator.<br>
   ///<br>
   /// Shifts this APInt left by \p Bits and returns the result.<br>
@@ -1532,7 +1514,9 @@ public:<br>
<br>
   /// \returns the ceil log base 2 of this APInt.<br>
   unsigned ceilLogBase2() const {<br>
-    return BitWidth - (*this - 1).countLeadingZeros();<br>
+    APInt temp(*this);<br>
+    --temp;<br>
+    return BitWidth - temp.countLeadingZeros();<br>
   }<br>
<br>
   /// \returns the nearest log base 2 of this APInt. Ties round up.<br>
@@ -1750,6 +1734,55 @@ inline raw_ostream &operator<<(raw_ostre<br>
   return OS;<br>
 }<br>
<br>
+inline APInt operator-(APInt v) {<br>
+  v.flipAllBits();<br>
+  ++v;<br>
+  return v;<br>
+}<br>
+<br>
+inline APInt operator+(APInt a, const APInt &b) {<br>
+  a += b;<br>
+  return a;<br>
+}<br>
+<br>
+inline APInt operator+(const APInt &a, APInt &&b) {<br>
+  b += a;<br>
+  return std::move(b);<br>
+}<br>
+<br>
+inline APInt operator+(APInt a, uint64_t RHS) {<br>
+  a += RHS;<br>
+  return a;<br>
+}<br>
+<br>
+inline APInt operator+(uint64_t LHS, APInt b) {<br>
+  b += LHS;<br>
+  return b;<br>
+}<br>
+<br>
+inline APInt operator-(APInt a, const APInt &b) {<br>
+  a -= b;<br>
+  return a;<br>
+}<br>
+<br>
+inline APInt operator-(const APInt &a, APInt &&b) {<br>
+  b = -std::move(b);<br>
+  b += a;<br>
+  return std::move(b);<br>
+}<br>
+<br>
+inline APInt operator-(APInt a, uint64_t RHS) {<br>
+  a -= RHS;<br>
+  return a;<br>
+}<br>
+<br>
+inline APInt operator-(uint64_t LHS, APInt b) {<br>
+  b = -std::move(b);<br>
+  b += LHS;<br>
+  return b;<br>
+}<br>
+<br>
+<br>
 namespace APIntOps {<br>
<br>
 /// \brief Determine the smaller of two APInts considered to be signed.<br>
<br>
Modified: llvm/trunk/lib/Support/APInt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=276470&r1=276469&r2=276470&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=276470&r1=276469&r2=276470&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Support/APInt.cpp (original)<br>
+++ llvm/trunk/lib/Support/APInt.cpp Fri Jul 22 15:55:46 2016<br>
@@ -260,6 +260,14 @@ APInt& APInt::operator+=(const APInt& RH<br>
   return clearUnusedBits();<br>
 }<br>
<br>
+APInt& APInt::operator+=(uint64_t RHS) {<br>
+  if (isSingleWord())<br>
+    VAL += RHS;<br>
+  else<br>
+    add_1(pVal, pVal, getNumWords(), RHS);<br>
+  return clearUnusedBits();<br>
+}<br>
+<br>
 /// Subtracts the integer array y from the integer array x<br>
 /// @returns returns the borrow out.<br>
 /// @brief Generalized subtraction of 64-bit integer arrays.<br>
@@ -286,6 +294,14 @@ APInt& APInt::operator-=(const APInt& RH<br>
   return clearUnusedBits();<br>
 }<br>
<br>
+APInt& APInt::operator-=(uint64_t RHS) {<br>
+  if (isSingleWord())<br>
+    VAL -= RHS;<br>
+  else<br>
+    sub_1(pVal, getNumWords(), RHS);<br>
+  return clearUnusedBits();<br>
+}<br>
+<br>
 /// Multiplies an integer array, x, by a uint64_t integer and places the result<br>
 /// into dest.<br>
 /// @returns the carry out of the multiplication.<br>
@@ -470,44 +486,6 @@ APInt APInt::operator*(const APInt& RHS)<br>
   return Result;<br>
 }<br>
<br>
-APInt APInt::operator+(const APInt& RHS) const {<br>
-  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");<br>
-  if (isSingleWord())<br>
-    return APInt(BitWidth, VAL + RHS.VAL);<br>
-  APInt Result(BitWidth, 0);<br>
-  add(Result.pVal, this->pVal, RHS.pVal, getNumWords());<br>
-  Result.clearUnusedBits();<br>
-  return Result;<br>
-}<br>
-<br>
-APInt APInt::operator+(uint64_t RHS) const {<br>
-  if (isSingleWord())<br>
-    return APInt(BitWidth, VAL + RHS);<br>
-  APInt Result(*this);<br>
-  add_1(Result.pVal, Result.pVal, getNumWords(), RHS);<br>
-  Result.clearUnusedBits();<br>
-  return Result;<br>
-}<br>
-<br>
-APInt APInt::operator-(const APInt& RHS) const {<br>
-  assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");<br>
-  if (isSingleWord())<br>
-    return APInt(BitWidth, VAL - RHS.VAL);<br>
-  APInt Result(BitWidth, 0);<br>
-  sub(Result.pVal, this->pVal, RHS.pVal, getNumWords());<br>
-  Result.clearUnusedBits();<br>
-  return Result;<br>
-}<br>
-<br>
-APInt APInt::operator-(uint64_t RHS) const {<br>
-  if (isSingleWord())<br>
-    return APInt(BitWidth, VAL - RHS);<br>
-  APInt Result(*this);<br>
-  sub_1(Result.pVal, getNumWords(), RHS);<br>
-  Result.clearUnusedBits();<br>
-  return Result;<br>
-}<br>
-<br>
 bool APInt::EqualSlowCase(const APInt& RHS) const {<br>
   return std::equal(pVal, pVal + getNumWords(), RHS.pVal);<br>
 }<br>
<br>
Modified: llvm/trunk/unittests/ADT/APIntTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=276470&r1=276469&r2=276470&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APIntTest.cpp?rev=276470&r1=276469&r2=276470&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ADT/APIntTest.cpp (original)<br>
+++ llvm/trunk/unittests/ADT/APIntTest.cpp Fri Jul 22 15:55:46 2016<br>
@@ -416,6 +416,175 @@ TEST(APIntTest, compareLargeIntegers) {<br>
   EXPECT_TRUE(!MinusTwo.slt(MinusTwo));<br>
 }<br>
<br>
+TEST(APIntTest, rvalue_arithmetic) {<br>
+  // Test all combinations of lvalue/rvalue lhs/rhs of add/sub<br>
+<br>
+  // Lamdba to return an APInt by value, but also provide the raw value of the<br>
+  // allocated data.<br>
+  auto getRValue = [](const char *HexString, uint64_t const *&RawData) {<br>
+    APInt V(129, HexString, 16);<br>
+    RawData = V.getRawData();<br>
+    return V;<br>
+  };<br>
+<br>
+  APInt One(129, "1", 16);<br>
+  APInt Two(129, "2", 16);<br>
+  APInt Three(129, "3", 16);<br>
+  APInt MinusOne = -One;<br>
+<br>
+  const uint64_t *RawDataL = nullptr;<br>
+  const uint64_t *RawDataR = nullptr;<br>
+<br>
+  {<br>
+    // 1 + 1 = 2<br>
+    APInt AddLL = One + One;<br>
+    EXPECT_EQ(AddLL, Two);<br>
+<br>
+    APInt AddLR = One + getRValue("1", RawDataR);<br>
+    EXPECT_EQ(AddLR, Two);<br>
+    EXPECT_EQ(AddLR.getRawData(), RawDataR);<br>
+<br>
+    APInt AddRL = getRValue("1", RawDataL) + One;<br>
+    EXPECT_EQ(AddRL, Two);<br>
+    EXPECT_EQ(AddRL.getRawData(), RawDataL);<br>
+<br>
+    APInt AddRR = getRValue("1", RawDataL) + getRValue("1", RawDataR);<br>
+    EXPECT_EQ(AddRR, Two);<br>
+    EXPECT_EQ(AddRR.getRawData(), RawDataR);<br>
+<br>
+    // LValue's and constants<br>
+    APInt AddLK = One + 1;<br>
+    EXPECT_EQ(AddLK, Two);<br>
+<br>
+    APInt AddKL = 1 + One;<br>
+    EXPECT_EQ(AddKL, Two);<br>
+<br>
+    // RValue's and constants<br>
+    APInt AddRK = getRValue("1", RawDataL) + 1;<br>
+    EXPECT_EQ(AddRK, Two);<br>
+    EXPECT_EQ(AddRK.getRawData(), RawDataL);<br>
+<br>
+    APInt AddKR = 1 + getRValue("1", RawDataR);<br>
+    EXPECT_EQ(AddKR, Two);<br>
+    EXPECT_EQ(AddKR.getRawData(), RawDataR);<br>
+  }<br>
+<br>
+  {<br>
+    // 0x0,FFFF...FFFF + 0x2 = 0x100...0001<br>
+    APInt AllOnes(129, "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);<br>
+    APInt HighOneLowOne(129, "100000000000000000000000000000001", 16);<br>
+<br>
+    APInt AddLL = AllOnes + Two;<br>
+    EXPECT_EQ(AddLL, HighOneLowOne);<br>
+<br>
+    APInt AddLR = AllOnes + getRValue("2", RawDataR);<br>
+    EXPECT_EQ(AddLR, HighOneLowOne);<br>
+    EXPECT_EQ(AddLR.getRawData(), RawDataR);<br>
+<br>
+    APInt AddRL = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) + Two;<br>
+    EXPECT_EQ(AddRL, HighOneLowOne);<br>
+    EXPECT_EQ(AddRL.getRawData(), RawDataL);<br>
+<br>
+    APInt AddRR = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) +<br>
+                  getRValue("2", RawDataR);<br>
+    EXPECT_EQ(AddRR, HighOneLowOne);<br>
+    EXPECT_EQ(AddRR.getRawData(), RawDataR);<br>
+<br>
+    // LValue's and constants<br>
+    APInt AddLK = AllOnes + 2;<br>
+    EXPECT_EQ(AddLK, HighOneLowOne);<br>
+<br>
+    APInt AddKL = 2 + AllOnes;<br>
+    EXPECT_EQ(AddKL, HighOneLowOne);<br>
+<br>
+    // RValue's and constants<br>
+    APInt AddRK = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) + 2;<br>
+    EXPECT_EQ(AddRK, HighOneLowOne);<br>
+    EXPECT_EQ(AddRK.getRawData(), RawDataL);<br>
+<br>
+    APInt AddKR = 2 + getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);<br>
+    EXPECT_EQ(AddKR, HighOneLowOne);<br>
+    EXPECT_EQ(AddKR.getRawData(), RawDataR);<br>
+  }<br>
+<br>
+  {<br>
+    // 2 - 1 = 1<br>
+    APInt SubLL = Two - One;<br>
+    EXPECT_EQ(SubLL, One);<br>
+<br>
+    APInt SubLR = Two - getRValue("1", RawDataR);<br>
+    EXPECT_EQ(SubLR, One);<br>
+    EXPECT_EQ(SubLR.getRawData(), RawDataR);<br>
+<br>
+    APInt SubRL = getRValue("2", RawDataL) - One;<br>
+    EXPECT_EQ(SubRL, One);<br>
+    EXPECT_EQ(SubRL.getRawData(), RawDataL);<br>
+<br>
+    APInt SubRR = getRValue("2", RawDataL) - getRValue("1", RawDataR);<br>
+    EXPECT_EQ(SubRR, One);<br>
+    EXPECT_EQ(SubRR.getRawData(), RawDataR);<br>
+<br>
+    // LValue's and constants<br>
+    APInt SubLK = Two - 1;<br>
+    EXPECT_EQ(SubLK, One);<br>
+<br>
+    APInt SubKL = 2 - One;<br>
+    EXPECT_EQ(SubKL, One);<br>
+<br>
+    // RValue's and constants<br>
+    APInt SubRK = getRValue("2", RawDataL) - 1;<br>
+    EXPECT_EQ(SubRK, One);<br>
+    EXPECT_EQ(SubRK.getRawData(), RawDataL);<br>
+<br>
+    APInt SubKR = 2 - getRValue("1", RawDataR);<br>
+    EXPECT_EQ(SubKR, One);<br>
+    EXPECT_EQ(SubKR.getRawData(), RawDataR);<br>
+  }<br>
+<br>
+  {<br>
+    // 0x100...0001 - 0x0,FFFF...FFFF = 0x2<br>
+    APInt AllOnes(129, "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);<br>
+    APInt HighOneLowOne(129, "100000000000000000000000000000001", 16);<br>
+<br>
+    APInt SubLL = HighOneLowOne - AllOnes;<br>
+    EXPECT_EQ(SubLL, Two);<br>
+<br>
+    APInt SubLR = HighOneLowOne -<br>
+                  getRValue("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);<br>
+    EXPECT_EQ(SubLR, Two);<br>
+    EXPECT_EQ(SubLR.getRawData(), RawDataR);<br>
+<br>
+    APInt SubRL = getRValue("100000000000000000000000000000001", RawDataL) -<br>
+                  AllOnes;<br>
+    EXPECT_EQ(SubRL, Two);<br>
+    EXPECT_EQ(SubRL.getRawData(), RawDataL);<br>
+<br>
+    APInt SubRR = getRValue("100000000000000000000000000000001", RawDataL) -<br>
+                  getRValue("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);<br>
+    EXPECT_EQ(SubRR, Two);<br>
+    EXPECT_EQ(SubRR.getRawData(), RawDataR);<br>
+<br>
+    // LValue's and constants<br>
+    // 0x100...0001 - 0x2 = 0x0,FFFF...FFFF<br>
+    APInt SubLK = HighOneLowOne - 2;<br>
+    EXPECT_EQ(SubLK, AllOnes);<br>
+<br>
+    // 2 - (-1) = 3<br>
+    APInt SubKL = 2 - MinusOne;<br>
+    EXPECT_EQ(SubKL, Three);<br>
+<br>
+    // RValue's and constants<br>
+    // 0x100...0001 - 0x2 = 0x0,FFFF...FFFF<br>
+    APInt SubRK = getRValue("100000000000000000000000000000001", RawDataL) - 2;<br>
+    EXPECT_EQ(SubRK, AllOnes);<br>
+    EXPECT_EQ(SubRK.getRawData(), RawDataL);<br>
+<br>
+    APInt SubKR = 2 - getRValue("1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);<br>
+    EXPECT_EQ(SubKR, Three);<br>
+    EXPECT_EQ(SubKR.getRawData(), RawDataR);<br>
+  }<br>
+}<br>
+<br>
<br>
 // Tests different div/rem varaints using scheme (a * b + c) / a<br>
 void testDiv(APInt a, APInt b, APInt c) {<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>