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

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 25 10:36:35 PDT 2016


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.

On Fri, Jul 22, 2016 at 2:03 PM Pete Cooper via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> 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) {
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160725/5ec71f71/attachment-0001.html>


More information about the llvm-commits mailing list