diff options
author | Chris Lattner <clattner@nondot.org> | 2021-09-10 11:31:26 -0700 |
---|---|---|
committer | Chris Lattner <clattner@nondot.org> | 2021-09-13 22:02:54 -0700 |
commit | 8b4afc5aef148aff26047ca7bad4cdcf58c35e25 (patch) | |
tree | b00e9e61cf55968c445821361b6ee0e610bf2d2e | |
parent | 946e69d253f23d62ed56f8f969414bb07a655e4e (diff) | |
download | llvm-8b4afc5aef148aff26047ca7bad4cdcf58c35e25.zip llvm-8b4afc5aef148aff26047ca7bad4cdcf58c35e25.tar.gz llvm-8b4afc5aef148aff26047ca7bad4cdcf58c35e25.tar.bz2 |
[APInt] Add a concat method, use LLVM_UNLIKELY to help optimizer.
Three unrelated changes:
1) Add a concat method as a convenience to help write bitvector
use cases in a nicer way.
2) Use LLVM_UNLIKELY as suggested by @xbolva00 in a previous patch.
3) Fix casing of some "slow" methods to follow naming standards.
Differential Revision: https://reviews.llvm.org/D109620
-rw-r--r-- | llvm/include/llvm/ADT/APInt.h | 46 | ||||
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 25 | ||||
-rw-r--r-- | llvm/unittests/ADT/APIntTest.cpp | 12 |
3 files changed, 60 insertions, 23 deletions
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index e00709a5..03f244a 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -348,9 +348,10 @@ public: /// Determine if all bits are set. bool isAllOnes() const { if (isSingleWord()) { - if (BitWidth == 0) - return false; - return U.VAL == WORDTYPE_MAX >> (APINT_BITS_PER_WORD - BitWidth); + // Calculate the shift amount, handling the zero-bit wide case without UB. + unsigned ShiftAmt = + (APINT_BITS_PER_WORD - BitWidth) % APINT_BITS_PER_WORD; + return U.VAL == WORDTYPE_MAX >> ShiftAmt; } return countTrailingOnesSlowCase() == BitWidth; } @@ -580,7 +581,7 @@ public: return *this; } - AssignSlowCase(RHS); + assignSlowCase(RHS); return *this; } @@ -632,7 +633,7 @@ public: if (isSingleWord()) U.VAL &= RHS.U.VAL; else - AndAssignSlowCase(RHS); + andAssignSlowCase(RHS); return *this; } @@ -662,7 +663,7 @@ public: if (isSingleWord()) U.VAL |= RHS.U.VAL; else - OrAssignSlowCase(RHS); + orAssignSlowCase(RHS); return *this; } @@ -691,7 +692,7 @@ public: if (isSingleWord()) U.VAL ^= RHS.U.VAL; else - XorAssignSlowCase(RHS); + xorAssignSlowCase(RHS); return *this; } @@ -877,6 +878,17 @@ public: /// Rotate right by rotateAmt. APInt rotr(const APInt &rotateAmt) const; + /// Concatenate the bits from "NewLSB" onto the bottom of *this. This is + /// equivalent to: + /// (this->zext(NewWidth) << NewLSB.getBitWidth()) | NewLSB.zext(NewWidth) + APInt concat(const APInt &NewLSB) const { + /// If the result will be small, then both the merged values are small. + unsigned NewWidth = getBitWidth() + NewLSB.getBitWidth(); + if (NewWidth <= APINT_BITS_PER_WORD) + return APInt(NewWidth, (U.VAL << NewLSB.getBitWidth()) | NewLSB.U.VAL); + return concatSlowCase(NewLSB); + } + /// Unsigned division operation. /// /// Perform an unsigned divide operation on this APInt by RHS. Both this and @@ -971,7 +983,7 @@ public: assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); if (isSingleWord()) return U.VAL == RHS.U.VAL; - return EqualSlowCase(RHS); + return equalSlowCase(RHS); } /// Equality operator. @@ -1491,7 +1503,7 @@ public: /// of 1 bits from the most significant to the least unsigned countLeadingOnes() const { if (isSingleWord()) { - if (BitWidth == 0) + if (LLVM_UNLIKELY(BitWidth == 0)) return 0; return llvm::countLeadingOnes(U.VAL << (APINT_BITS_PER_WORD - BitWidth)); } @@ -1799,7 +1811,6 @@ private: unsigned BitWidth; ///< The number of bits in this APInt. friend struct DenseMapInfo<APInt>; - friend class APSInt; /// This constructor is used only internally for speed of construction of @@ -1841,7 +1852,7 @@ private: // Mask out the high bits. uint64_t mask = WORDTYPE_MAX >> (APINT_BITS_PER_WORD - WordBits); - if (BitWidth == 0) + if (LLVM_UNLIKELY(BitWidth == 0)) mask = 0; if (isSingleWord()) @@ -1905,10 +1916,10 @@ private: void ashrSlowCase(unsigned ShiftAmt); /// out-of-line slow case for operator= - void AssignSlowCase(const APInt &RHS); + void assignSlowCase(const APInt &RHS); /// out-of-line slow case for operator== - bool EqualSlowCase(const APInt &RHS) const LLVM_READONLY; + bool equalSlowCase(const APInt &RHS) const LLVM_READONLY; /// out-of-line slow case for countLeadingZeros unsigned countLeadingZerosSlowCase() const LLVM_READONLY; @@ -1937,14 +1948,17 @@ private: /// out-of-line slow case for flipAllBits. void flipAllBitsSlowCase(); + /// out-of-line slow case for concat. + APInt concatSlowCase(const APInt &NewLSB) const; + /// out-of-line slow case for operator&=. - void AndAssignSlowCase(const APInt &RHS); + void andAssignSlowCase(const APInt &RHS); /// out-of-line slow case for operator|=. - void OrAssignSlowCase(const APInt &RHS); + void orAssignSlowCase(const APInt &RHS); /// out-of-line slow case for operator^=. - void XorAssignSlowCase(const APInt &RHS); + void xorAssignSlowCase(const APInt &RHS); /// Unsigned comparison. Returns -1, 0, or 1 if this APInt is less than, equal /// to, or greater than RHS. diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index a630050..d64ee05 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -137,7 +137,7 @@ void APInt::reallocate(unsigned NewBitWidth) { U.pVal = getMemory(getNumWords()); } -void APInt::AssignSlowCase(const APInt& RHS) { +void APInt::assignSlowCase(const APInt &RHS) { // Don't do anything for X = X if (this == &RHS) return; @@ -235,19 +235,19 @@ APInt APInt::operator*(const APInt& RHS) const { return Result; } -void APInt::AndAssignSlowCase(const APInt &RHS) { +void APInt::andAssignSlowCase(const APInt &RHS) { WordType *dst = U.pVal, *rhs = RHS.U.pVal; for (size_t i = 0, e = getNumWords(); i != e; ++i) dst[i] &= rhs[i]; } -void APInt::OrAssignSlowCase(const APInt &RHS) { +void APInt::orAssignSlowCase(const APInt &RHS) { WordType *dst = U.pVal, *rhs = RHS.U.pVal; for (size_t i = 0, e = getNumWords(); i != e; ++i) dst[i] |= rhs[i]; } -void APInt::XorAssignSlowCase(const APInt &RHS) { +void APInt::xorAssignSlowCase(const APInt &RHS) { WordType *dst = U.pVal, *rhs = RHS.U.pVal; for (size_t i = 0, e = getNumWords(); i != e; ++i) dst[i] ^= rhs[i]; @@ -268,7 +268,7 @@ APInt& APInt::operator*=(uint64_t RHS) { return clearUnusedBits(); } -bool APInt::EqualSlowCase(const APInt& RHS) const { +bool APInt::equalSlowCase(const APInt &RHS) const { return std::equal(U.pVal, U.pVal + getNumWords(), RHS.U.pVal); } @@ -339,6 +339,17 @@ void APInt::flipAllBitsSlowCase() { clearUnusedBits(); } +/// Concatenate the bits from "NewLSB" onto the bottom of *this. This is +/// equivalent to: +/// (this->zext(NewWidth) << NewLSB.getBitWidth()) | NewLSB.zext(NewWidth) +/// In the slow case, we know the result is large. +APInt APInt::concatSlowCase(const APInt &NewLSB) const { + unsigned NewWidth = getBitWidth() + NewLSB.getBitWidth(); + APInt Result = NewLSB.zext(NewWidth); + Result.insertBits(*this, NewLSB.getBitWidth()); + return Result; +} + /// Toggle a given bit to its opposite value whose position is given /// as "bitPosition". /// Toggles a given bit to its opposite value. @@ -1064,7 +1075,7 @@ void APInt::shlSlowCase(unsigned ShiftAmt) { // Calculate the rotate amount modulo the bit width. static unsigned rotateModulo(unsigned BitWidth, const APInt &rotateAmt) { - if (BitWidth == 0) + if (LLVM_UNLIKELY(BitWidth == 0)) return 0; unsigned rotBitWidth = rotateAmt.getBitWidth(); APInt rot = rotateAmt; @@ -1082,7 +1093,7 @@ APInt APInt::rotl(const APInt &rotateAmt) const { } APInt APInt::rotl(unsigned rotateAmt) const { - if (BitWidth == 0) + if (LLVM_UNLIKELY(BitWidth == 0)) return *this; rotateAmt %= BitWidth; if (rotateAmt == 0) diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 6da9d2d..fe7a231 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -2587,6 +2587,18 @@ TEST(APIntTest, truncOrSelf) { EXPECT_EQ(0xFFFFFFFF, val.truncOrSelf(64)); } +TEST(APIntTest, concatMSB) { + APInt Int1(4, 0x1ULL); + APInt Int3(4, 0x3ULL); + + EXPECT_EQ(0x31, Int3.concat(Int1)); + EXPECT_EQ(APInt(12, 0x313), Int3.concat(Int1).concat(Int3)); + EXPECT_EQ(APInt(16, 0x3313), Int3.concat(Int3).concat(Int1).concat(Int3)); + + APInt I64(64, 0x3ULL); + EXPECT_EQ(I64, I64.concat(I64).lshr(64).trunc(64)); +} + TEST(APIntTest, multiply) { APInt i64(64, 1234); |