[llvm] 8b4afc5 - [APInt] Add a concat method, use LLVM_UNLIKELY to help optimizer.
Chris Lattner via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 13 22:02:58 PDT 2021
Author: Chris Lattner
Date: 2021-09-13T22:02:54-07:00
New Revision: 8b4afc5aef148aff26047ca7bad4cdcf58c35e25
URL: https://github.com/llvm/llvm-project/commit/8b4afc5aef148aff26047ca7bad4cdcf58c35e25
DIFF: https://github.com/llvm/llvm-project/commit/8b4afc5aef148aff26047ca7bad4cdcf58c35e25.diff
LOG: [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
Added:
Modified:
llvm/include/llvm/ADT/APInt.h
llvm/lib/Support/APInt.cpp
llvm/unittests/ADT/APIntTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index e00709a54465f..03f244a67fae8 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -348,9 +348,10 @@ class LLVM_NODISCARD APInt {
/// 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 @@ class LLVM_NODISCARD APInt {
return *this;
}
- AssignSlowCase(RHS);
+ assignSlowCase(RHS);
return *this;
}
@@ -632,7 +633,7 @@ class LLVM_NODISCARD APInt {
if (isSingleWord())
U.VAL &= RHS.U.VAL;
else
- AndAssignSlowCase(RHS);
+ andAssignSlowCase(RHS);
return *this;
}
@@ -662,7 +663,7 @@ class LLVM_NODISCARD APInt {
if (isSingleWord())
U.VAL |= RHS.U.VAL;
else
- OrAssignSlowCase(RHS);
+ orAssignSlowCase(RHS);
return *this;
}
@@ -691,7 +692,7 @@ class LLVM_NODISCARD APInt {
if (isSingleWord())
U.VAL ^= RHS.U.VAL;
else
- XorAssignSlowCase(RHS);
+ xorAssignSlowCase(RHS);
return *this;
}
@@ -877,6 +878,17 @@ class LLVM_NODISCARD APInt {
/// 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 @@ class LLVM_NODISCARD APInt {
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 @@ class LLVM_NODISCARD APInt {
/// 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 @@ class LLVM_NODISCARD APInt {
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 @@ class LLVM_NODISCARD APInt {
// 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 @@ class LLVM_NODISCARD APInt {
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 @@ class LLVM_NODISCARD APInt {
/// 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 a630050c0157a..d64ee053dc467 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 6da9d2ddeb993..fe7a231d33fe2 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);
More information about the llvm-commits
mailing list