aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/APInt.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /llvm/lib/Support/APInt.cpp
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'llvm/lib/Support/APInt.cpp')
-rw-r--r--llvm/lib/Support/APInt.cpp99
1 files changed, 59 insertions, 40 deletions
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index afe7478a8b2a..05b1526da95f 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/bit.h"
#include "llvm/Config/llvm-config.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
@@ -68,7 +69,7 @@ inline static unsigned getDigit(char cdigit, uint8_t radix) {
if (r < radix)
return r;
- return -1U;
+ return UINT_MAX;
}
@@ -164,6 +165,14 @@ void APInt::Profile(FoldingSetNodeID& ID) const {
ID.AddInteger(U.pVal[i]);
}
+bool APInt::isAligned(Align A) const {
+ if (isZero())
+ return true;
+ const unsigned TrailingZeroes = countr_zero();
+ const unsigned MinimumTrailingZeroes = Log2(A);
+ return TrailingZeroes >= MinimumTrailingZeroes;
+}
+
/// Prefix increment operator. Increments the APInt by one.
APInt& APInt::operator++() {
if (isSingleWord())
@@ -479,7 +488,6 @@ APInt APInt::extractBits(unsigned numBits, unsigned bitPosition) const {
uint64_t APInt::extractBitsAsZExtValue(unsigned numBits,
unsigned bitPosition) const {
- assert(numBits > 0 && "Can't extract zero bits");
assert(bitPosition < BitWidth && (numBits + bitPosition) <= BitWidth &&
"Illegal bit extraction");
assert(numBits <= 64 && "Illegal bit extraction");
@@ -626,7 +634,7 @@ unsigned APInt::countLeadingZerosSlowCase() const {
if (V == 0)
Count += APINT_BITS_PER_WORD;
else {
- Count += llvm::countLeadingZeros(V);
+ Count += llvm::countl_zero(V);
break;
}
}
@@ -646,13 +654,13 @@ unsigned APInt::countLeadingOnesSlowCase() const {
shift = APINT_BITS_PER_WORD - highWordBits;
}
int i = getNumWords() - 1;
- unsigned Count = llvm::countLeadingOnes(U.pVal[i] << shift);
+ unsigned Count = llvm::countl_one(U.pVal[i] << shift);
if (Count == highWordBits) {
for (i--; i >= 0; --i) {
if (U.pVal[i] == WORDTYPE_MAX)
Count += APINT_BITS_PER_WORD;
else {
- Count += llvm::countLeadingOnes(U.pVal[i]);
+ Count += llvm::countl_one(U.pVal[i]);
break;
}
}
@@ -666,7 +674,7 @@ unsigned APInt::countTrailingZerosSlowCase() const {
for (; i < getNumWords() && U.pVal[i] == 0; ++i)
Count += APINT_BITS_PER_WORD;
if (i < getNumWords())
- Count += llvm::countTrailingZeros(U.pVal[i]);
+ Count += llvm::countr_zero(U.pVal[i]);
return std::min(Count, BitWidth);
}
@@ -676,7 +684,7 @@ unsigned APInt::countTrailingOnesSlowCase() const {
for (; i < getNumWords() && U.pVal[i] == WORDTYPE_MAX; ++i)
Count += APINT_BITS_PER_WORD;
if (i < getNumWords())
- Count += llvm::countTrailingOnes(U.pVal[i]);
+ Count += llvm::countr_one(U.pVal[i]);
assert(Count <= BitWidth);
return Count;
}
@@ -707,18 +715,18 @@ bool APInt::isSubsetOfSlowCase(const APInt &RHS) const {
APInt APInt::byteSwap() const {
assert(BitWidth >= 16 && BitWidth % 8 == 0 && "Cannot byteswap!");
if (BitWidth == 16)
- return APInt(BitWidth, ByteSwap_16(uint16_t(U.VAL)));
+ return APInt(BitWidth, llvm::byteswap<uint16_t>(U.VAL));
if (BitWidth == 32)
- return APInt(BitWidth, ByteSwap_32(unsigned(U.VAL)));
+ return APInt(BitWidth, llvm::byteswap<uint32_t>(U.VAL));
if (BitWidth <= 64) {
- uint64_t Tmp1 = ByteSwap_64(U.VAL);
+ uint64_t Tmp1 = llvm::byteswap<uint64_t>(U.VAL);
Tmp1 >>= (64 - BitWidth);
return APInt(BitWidth, Tmp1);
}
APInt Result(getNumWords() * APINT_BITS_PER_WORD, 0);
for (unsigned I = 0, N = getNumWords(); I != N; ++I)
- Result.U.pVal[I] = ByteSwap_64(U.pVal[N - I - 1]);
+ Result.U.pVal[I] = llvm::byteswap<uint64_t>(U.pVal[N - I - 1]);
if (Result.BitWidth != BitWidth) {
Result.lshrInPlace(Result.BitWidth - BitWidth);
Result.BitWidth = BitWidth;
@@ -767,8 +775,8 @@ APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {
// Count common powers of 2 and remove all other powers of 2.
unsigned Pow2;
{
- unsigned Pow2_A = A.countTrailingZeros();
- unsigned Pow2_B = B.countTrailingZeros();
+ unsigned Pow2_A = A.countr_zero();
+ unsigned Pow2_B = B.countr_zero();
if (Pow2_A > Pow2_B) {
A.lshrInPlace(Pow2_A - Pow2_B);
Pow2 = Pow2_B;
@@ -789,10 +797,10 @@ APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {
while (A != B) {
if (A.ugt(B)) {
A -= B;
- A.lshrInPlace(A.countTrailingZeros() - Pow2);
+ A.lshrInPlace(A.countr_zero() - Pow2);
} else {
B -= A;
- B.lshrInPlace(B.countTrailingZeros() - Pow2);
+ B.lshrInPlace(B.countr_zero() - Pow2);
}
}
@@ -1318,7 +1326,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
// and v so that its high bits are shifted to the top of v's range without
// overflow. Note that this can require an extra word in u so that u must
// be of length m+n+1.
- unsigned shift = countLeadingZeros(v[n-1]);
+ unsigned shift = llvm::countl_zero(v[n - 1]);
uint32_t v_carry = 0;
uint32_t u_carry = 0;
if (shift) {
@@ -1967,7 +1975,7 @@ APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const {
}
APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
- if (countLeadingZeros() + RHS.countLeadingZeros() + 2 <= BitWidth) {
+ if (countl_zero() + RHS.countl_zero() + 2 <= BitWidth) {
Overflow = true;
return *this * RHS;
}
@@ -1984,24 +1992,32 @@ APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
}
APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const {
- Overflow = ShAmt.uge(getBitWidth());
+ return sshl_ov(ShAmt.getLimitedValue(getBitWidth()), Overflow);
+}
+
+APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const {
+ Overflow = ShAmt >= getBitWidth();
if (Overflow)
return APInt(BitWidth, 0);
if (isNonNegative()) // Don't allow sign change.
- Overflow = ShAmt.uge(countLeadingZeros());
+ Overflow = ShAmt >= countl_zero();
else
- Overflow = ShAmt.uge(countLeadingOnes());
+ Overflow = ShAmt >= countl_one();
return *this << ShAmt;
}
APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const {
- Overflow = ShAmt.uge(getBitWidth());
+ return ushl_ov(ShAmt.getLimitedValue(getBitWidth()), Overflow);
+}
+
+APInt APInt::ushl_ov(unsigned ShAmt, bool &Overflow) const {
+ Overflow = ShAmt >= getBitWidth();
if (Overflow)
return APInt(BitWidth, 0);
- Overflow = ShAmt.ugt(countLeadingZeros());
+ Overflow = ShAmt > countl_zero();
return *this << ShAmt;
}
@@ -2067,6 +2083,10 @@ APInt APInt::umul_sat(const APInt &RHS) const {
}
APInt APInt::sshl_sat(const APInt &RHS) const {
+ return sshl_sat(RHS.getLimitedValue(getBitWidth()));
+}
+
+APInt APInt::sshl_sat(unsigned RHS) const {
bool Overflow;
APInt Res = sshl_ov(RHS, Overflow);
if (!Overflow)
@@ -2077,6 +2097,10 @@ APInt APInt::sshl_sat(const APInt &RHS) const {
}
APInt APInt::ushl_sat(const APInt &RHS) const {
+ return ushl_sat(RHS.getLimitedValue(getBitWidth()));
+}
+
+APInt APInt::ushl_sat(unsigned RHS) const {
bool Overflow;
APInt Res = ushl_ov(RHS, Overflow);
if (!Overflow)
@@ -2136,8 +2160,8 @@ void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
this->negate();
}
-void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
- bool Signed, bool formatAsCLiteral) const {
+void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix, bool Signed,
+ bool formatAsCLiteral, bool UpperCase) const {
assert((Radix == 10 || Radix == 8 || Radix == 16 || Radix == 2 ||
Radix == 36) &&
"Radix should be 2, 8, 10, 16, or 36!");
@@ -2173,7 +2197,9 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
return;
}
- static const char Digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ static const char BothDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *Digits = BothDigits + (UpperCase ? 36 : 0);
if (isSingleWord()) {
char Buffer[65];
@@ -2290,14 +2316,6 @@ static inline APInt::WordType highHalf(APInt::WordType part) {
return part >> (APInt::APINT_BITS_PER_WORD / 2);
}
-/// Returns the bit number of the most significant set bit of a part.
-/// If the input number has no bits set -1U is returned.
-static unsigned partMSB(APInt::WordType value) { return findLastSet(value); }
-
-/// Returns the bit number of the least significant set bit of a part. If the
-/// input number has no bits set -1U is returned.
-static unsigned partLSB(APInt::WordType value) { return findFirstSet(value); }
-
/// Sets the least significant part of a bignum to the input value, and zeroes
/// out higher parts.
void APInt::tcSet(WordType *dst, WordType part, unsigned parts) {
@@ -2338,32 +2356,33 @@ void APInt::tcClearBit(WordType *parts, unsigned bit) {
}
/// Returns the bit number of the least significant set bit of a number. If the
-/// input number has no bits set -1U is returned.
+/// input number has no bits set UINT_MAX is returned.
unsigned APInt::tcLSB(const WordType *parts, unsigned n) {
for (unsigned i = 0; i < n; i++) {
if (parts[i] != 0) {
- unsigned lsb = partLSB(parts[i]);
+ unsigned lsb = llvm::countr_zero(parts[i]);
return lsb + i * APINT_BITS_PER_WORD;
}
}
- return -1U;
+ return UINT_MAX;
}
/// Returns the bit number of the most significant set bit of a number.
-/// If the input number has no bits set -1U is returned.
+/// If the input number has no bits set UINT_MAX is returned.
unsigned APInt::tcMSB(const WordType *parts, unsigned n) {
do {
--n;
if (parts[n] != 0) {
- unsigned msb = partMSB(parts[n]);
+ static_assert(sizeof(parts[n]) <= sizeof(uint64_t));
+ unsigned msb = llvm::Log2_64(parts[n]);
return msb + n * APINT_BITS_PER_WORD;
}
} while (n);
- return -1U;
+ return UINT_MAX;
}
/// Copy the bit vector of width srcBITS from SRC, starting at bit srcLSB, to
@@ -2961,7 +2980,7 @@ llvm::APIntOps::GetMostSignificantDifferentBit(const APInt &A, const APInt &B) {
assert(A.getBitWidth() == B.getBitWidth() && "Must have the same bitwidth");
if (A == B)
return std::nullopt;
- return A.getBitWidth() - ((A ^ B).countLeadingZeros() + 1);
+ return A.getBitWidth() - ((A ^ B).countl_zero() + 1);
}
APInt llvm::APIntOps::ScaleBitMask(const APInt &A, unsigned NewBitWidth,