diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Support/APInt.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Support/APInt.cpp | 126 |
1 files changed, 70 insertions, 56 deletions
diff --git a/contrib/llvm-project/llvm/lib/Support/APInt.cpp b/contrib/llvm-project/llvm/lib/Support/APInt.cpp index b536e9a9a6d0..f74178b1ba4e 100644 --- a/contrib/llvm-project/llvm/lib/Support/APInt.cpp +++ b/contrib/llvm-project/llvm/lib/Support/APInt.cpp @@ -343,7 +343,7 @@ void APInt::flipAllBitsSlowCase() { /// 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.zextOrSelf(NewWidth); + APInt Result = NewLSB.zext(NewWidth); Result.insertBits(*this, NewLSB.getBitWidth()); return Result; } @@ -502,12 +502,51 @@ uint64_t APInt::extractBitsAsZExtValue(unsigned numBits, return retBits; } +unsigned APInt::getSufficientBitsNeeded(StringRef Str, uint8_t Radix) { + assert(!Str.empty() && "Invalid string length"); + size_t StrLen = Str.size(); + + // Each computation below needs to know if it's negative. + unsigned IsNegative = false; + if (Str[0] == '-' || Str[0] == '+') { + IsNegative = Str[0] == '-'; + StrLen--; + assert(StrLen && "String is only a sign, needs a value."); + } + + // For radixes of power-of-two values, the bits required is accurately and + // easily computed. + if (Radix == 2) + return StrLen + IsNegative; + if (Radix == 8) + return StrLen * 3 + IsNegative; + if (Radix == 16) + return StrLen * 4 + IsNegative; + + // Compute a sufficient number of bits that is always large enough but might + // be too large. This avoids the assertion in the constructor. This + // calculation doesn't work appropriately for the numbers 0-9, so just use 4 + // bits in that case. + if (Radix == 10) + return (StrLen == 1 ? 4 : StrLen * 64 / 18) + IsNegative; + + assert(Radix == 36); + return (StrLen == 1 ? 7 : StrLen * 16 / 3) + IsNegative; +} + unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { - assert(!str.empty() && "Invalid string length"); - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2 || - radix == 36) && - "Radix should be 2, 8, 10, 16, or 36!"); + // Compute a sufficient number of bits that is always large enough but might + // be too large. + unsigned sufficient = getSufficientBitsNeeded(str, radix); + + // For bases 2, 8, and 16, the sufficient number of bits is exact and we can + // return the value directly. For bases 10 and 36, we need to do extra work. + if (radix == 2 || radix == 8 || radix == 16) + return sufficient; + // This is grossly inefficient but accurate. We could probably do something + // with a computation of roughly slen*64/20 and then adjust by the value of + // the first few digits. But, I'm not sure how accurate that could be. size_t slen = str.size(); // Each computation below needs to know if it's negative. @@ -519,28 +558,6 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { assert(slen && "String is only a sign, needs a value."); } - // For radixes of power-of-two values, the bits required is accurately and - // easily computed - if (radix == 2) - return slen + isNegative; - if (radix == 8) - return slen * 3 + isNegative; - if (radix == 16) - return slen * 4 + isNegative; - - // FIXME: base 36 - - // This is grossly inefficient but accurate. We could probably do something - // with a computation of roughly slen*64/20 and then adjust by the value of - // the first few digits. But, I'm not sure how accurate that could be. - - // Compute a sufficient number of bits that is always large enough but might - // be too large. This avoids the assertion in the constructor. This - // calculation doesn't work appropriately for the numbers 0-9, so just use 4 - // bits in that case. - unsigned sufficient - = radix == 10? (slen == 1 ? 4 : slen * 64/18) - : (slen == 1 ? 7 : slen * 16/3); // Convert to the actual binary value. APInt tmp(sufficient, StringRef(p, slen), radix); @@ -595,7 +612,7 @@ APInt APInt::getLoBits(unsigned numBits) const { APInt APInt::getSplat(unsigned NewLen, const APInt &V) { assert(NewLen >= V.getBitWidth() && "Can't splat to smaller bit width!"); - APInt Val = V.zextOrSelf(NewLen); + APInt Val = V.zext(NewLen); for (unsigned I = V.getBitWidth(); I < NewLen; I <<= 1) Val |= Val << I; @@ -879,11 +896,14 @@ double APInt::roundToDouble(bool isSigned) const { // Truncate to new width. APInt APInt::trunc(unsigned width) const { - assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width <= BitWidth && "Invalid APInt Truncate request"); if (width <= APINT_BITS_PER_WORD) return APInt(width, getRawData()[0]); + if (width == BitWidth) + return *this; + APInt Result(getMemory(getNumWords(width)), width); // Copy full words. @@ -901,7 +921,7 @@ APInt APInt::trunc(unsigned width) const { // Truncate to new width with unsigned saturation. APInt APInt::truncUSat(unsigned width) const { - assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width <= BitWidth && "Invalid APInt Truncate request"); // Can we just losslessly truncate it? if (isIntN(width)) @@ -912,7 +932,7 @@ APInt APInt::truncUSat(unsigned width) const { // Truncate to new width with signed saturation. APInt APInt::truncSSat(unsigned width) const { - assert(width < BitWidth && "Invalid APInt Truncate request"); + assert(width <= BitWidth && "Invalid APInt Truncate request"); // Can we just losslessly truncate it? if (isSignedIntN(width)) @@ -924,11 +944,14 @@ APInt APInt::truncSSat(unsigned width) const { // Sign extend to a new width. APInt APInt::sext(unsigned Width) const { - assert(Width > BitWidth && "Invalid APInt SignExtend request"); + assert(Width >= BitWidth && "Invalid APInt SignExtend request"); if (Width <= APINT_BITS_PER_WORD) return APInt(Width, SignExtend64(U.VAL, BitWidth)); + if (Width == BitWidth) + return *this; + APInt Result(getMemory(getNumWords(Width)), Width); // Copy words. @@ -948,11 +971,14 @@ APInt APInt::sext(unsigned Width) const { // Zero extend to a new width. APInt APInt::zext(unsigned width) const { - assert(width > BitWidth && "Invalid APInt ZeroExtend request"); + assert(width >= BitWidth && "Invalid APInt ZeroExtend request"); if (width <= APINT_BITS_PER_WORD) return APInt(width, U.VAL); + if (width == BitWidth) + return *this; + APInt Result(getMemory(getNumWords(width)), width); // Copy words. @@ -981,24 +1007,6 @@ APInt APInt::sextOrTrunc(unsigned width) const { return *this; } -APInt APInt::truncOrSelf(unsigned width) const { - if (BitWidth > width) - return trunc(width); - return *this; -} - -APInt APInt::zextOrSelf(unsigned width) const { - if (BitWidth < width) - return zext(width); - return *this; -} - -APInt APInt::sextOrSelf(unsigned width) const { - if (BitWidth < width) - return sext(width); - return *this; -} - /// Arithmetic right-shift this APInt by shiftAmt. /// Arithmetic right-shift function. void APInt::ashrInPlace(const APInt &shiftAmt) { @@ -2960,7 +2968,8 @@ llvm::APIntOps::GetMostSignificantDifferentBit(const APInt &A, const APInt &B) { return A.getBitWidth() - ((A ^ B).countLeadingZeros() + 1); } -APInt llvm::APIntOps::ScaleBitMask(const APInt &A, unsigned NewBitWidth) { +APInt llvm::APIntOps::ScaleBitMask(const APInt &A, unsigned NewBitWidth, + bool MatchAllBits) { unsigned OldBitWidth = A.getBitWidth(); assert((((OldBitWidth % NewBitWidth) == 0) || ((NewBitWidth % OldBitWidth) == 0)) && @@ -2984,11 +2993,16 @@ APInt llvm::APIntOps::ScaleBitMask(const APInt &A, unsigned NewBitWidth) { if (A[i]) NewA.setBits(i * Scale, (i + 1) * Scale); } else { - // Merge bits - if any old bit is set, then set scale equivalent new bit. unsigned Scale = OldBitWidth / NewBitWidth; - for (unsigned i = 0; i != NewBitWidth; ++i) - if (!A.extractBits(Scale, i * Scale).isZero()) - NewA.setBit(i); + for (unsigned i = 0; i != NewBitWidth; ++i) { + if (MatchAllBits) { + if (A.extractBits(Scale, i * Scale).isAllOnes()) + NewA.setBit(i); + } else { + if (!A.extractBits(Scale, i * Scale).isZero()) + NewA.setBit(i); + } + } } return NewA; |