diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:03:47 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:04:23 +0000 |
commit | 7fa27ce4a07f19b07799a767fc29416f3b625afb (patch) | |
tree | 27825c83636c4de341eb09a74f49f5d38a15d165 /llvm/lib/Support/APInt.cpp | |
parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) |
Diffstat (limited to 'llvm/lib/Support/APInt.cpp')
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 99 |
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, |