[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