X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FAPInt.cpp;h=38b379005af0f77a910b5ba3accc4b82f37555f4;hb=ebb5a971d903aa4479bb2a21472597319a9b0086;hp=aa6cfa713e81026d5bce968a06824f2112c4f408;hpb=055c0b3a8f640a939bc6ff33338714fc05e79802;p=oota-llvm.git diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index aa6cfa713e8..38b379005af 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Sheng Zhou and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -14,7 +14,7 @@ #define DEBUG_TYPE "apint" #include "llvm/ADT/APInt.h" -#include "llvm/DerivedTypes.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include @@ -25,6 +25,15 @@ using namespace llvm; +/// This enumeration just provides for internal constants used in this +/// translation unit. +enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS +}; + /// A utility function for allocating memory, checking for allocation failures, /// and ensuring the contents are zeroed. inline static uint64_t* getClearedMemory(uint32_t numWords) { @@ -44,8 +53,8 @@ inline static uint64_t* getMemory(uint32_t numWords) { APInt::APInt(uint32_t numBits, uint64_t val, bool isSigned) : BitWidth(numBits), VAL(0) { - assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); + assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); if (isSingleWord()) VAL = val; else { @@ -60,8 +69,8 @@ APInt::APInt(uint32_t numBits, uint64_t val, bool isSigned) APInt::APInt(uint32_t numBits, uint32_t numWords, const uint64_t bigVal[]) : BitWidth(numBits), VAL(0) { - assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); + assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); assert(bigVal && "Null pointer detected!"); if (isSingleWord()) VAL = bigVal[0]; @@ -80,23 +89,23 @@ APInt::APInt(uint32_t numBits, uint32_t numWords, const uint64_t bigVal[]) APInt::APInt(uint32_t numbits, const char StrStart[], uint32_t slen, uint8_t radix) : BitWidth(numbits), VAL(0) { - assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); + assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); fromString(numbits, StrStart, slen, radix); } APInt::APInt(uint32_t numbits, const std::string& Val, uint8_t radix) : BitWidth(numbits), VAL(0) { - assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); + assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); assert(!Val.empty() && "String empty?"); - fromString(numbits, Val.c_str(), Val.size(), radix); + fromString(numbits, Val.c_str(), (uint32_t)Val.size(), radix); } APInt::APInt(const APInt& that) : BitWidth(that.BitWidth), VAL(0) { - assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); + assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); if (isSingleWord()) VAL = that.VAL; else { @@ -156,6 +165,20 @@ APInt& APInt::operator=(uint64_t RHS) { return clearUnusedBits(); } +/// Profile - This method 'profiles' an APInt for use with FoldingSet. +void APInt::Profile(FoldingSetNodeID& ID) const { + ID.AddInteger(BitWidth); + + if (isSingleWord()) { + ID.AddInteger(VAL); + return; + } + + uint32_t NumWords = getNumWords(); + for (unsigned i = 0; i < NumWords; ++i) + ID.AddInteger(pVal[i]); +} + /// add_1 - This function adds a single "digit" integer, y, to the multiple /// "digit" integer array, x[]. x[] is modified to reflect the addition and /// 1 is returned if there is a carry out, otherwise 0 is returned. @@ -745,7 +768,7 @@ uint32_t APInt::countLeadingZeros() const { uint32_t remainder = BitWidth % APINT_BITS_PER_WORD; if (remainder) Count -= APINT_BITS_PER_WORD - remainder; - return Count; + return std::min(Count, BitWidth); } static uint32_t countLeadingOnes_64(uint64_t V, uint32_t skip) { @@ -782,14 +805,26 @@ uint32_t APInt::countLeadingOnes() const { uint32_t APInt::countTrailingZeros() const { if (isSingleWord()) - return CountTrailingZeros_64(VAL); + return std::min(uint32_t(CountTrailingZeros_64(VAL)), BitWidth); uint32_t Count = 0; uint32_t i = 0; for (; i < getNumWords() && pVal[i] == 0; ++i) Count += APINT_BITS_PER_WORD; if (i < getNumWords()) Count += CountTrailingZeros_64(pVal[i]); - return Count; + return std::min(Count, BitWidth); +} + +uint32_t APInt::countTrailingOnes() const { + if (isSingleWord()) + return std::min(uint32_t(CountTrailingOnes_64(VAL)), BitWidth); + uint32_t Count = 0; + uint32_t i = 0; + for (; i < getNumWords() && pVal[i] == -1ULL; ++i) + Count += APINT_BITS_PER_WORD; + if (i < getNumWords()) + Count += CountTrailingOnes_64(pVal[i]); + return std::min(Count, BitWidth); } uint32_t APInt::countPopulation() const { @@ -870,7 +905,7 @@ APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, uint32_t width) { // Otherwise, we have to shift the mantissa bits up to the right location APInt Tmp(width, mantissa); - Tmp = Tmp.shl(exp - 52); + Tmp = Tmp.shl((uint32_t)exp - 52); return isNeg ? -Tmp : Tmp; } @@ -943,7 +978,7 @@ double APInt::roundToDouble(bool isSigned) const { // Truncate to new width. APInt &APInt::trunc(uint32_t width) { assert(width < BitWidth && "Invalid APInt Truncate request"); - assert(width >= IntegerType::MIN_INT_BITS && "Can't truncate to 0 bits"); + assert(width >= MIN_INT_BITS && "Can't truncate to 0 bits"); uint32_t wordsBefore = getNumWords(); BitWidth = width; uint32_t wordsAfter = getNumWords(); @@ -966,7 +1001,7 @@ APInt &APInt::trunc(uint32_t width) { // Sign extend to a new width. APInt &APInt::sext(uint32_t width) { assert(width > BitWidth && "Invalid APInt SignExtend request"); - assert(width <= IntegerType::MAX_INT_BITS && "Too many bits"); + assert(width <= MAX_INT_BITS && "Too many bits"); // If the sign bit isn't set, this is the same as zext. if (!isNegative()) { zext(width); @@ -1014,7 +1049,7 @@ APInt &APInt::sext(uint32_t width) { // Zero extend to a new width. APInt &APInt::zext(uint32_t width) { assert(width > BitWidth && "Invalid APInt ZeroExtend request"); - assert(width <= IntegerType::MAX_INT_BITS && "Too many bits"); + assert(width <= MAX_INT_BITS && "Too many bits"); uint32_t wordsBefore = getNumWords(); BitWidth = width; uint32_t wordsAfter = getNumWords(); @@ -1048,6 +1083,12 @@ APInt &APInt::sextOrTrunc(uint32_t width) { return *this; } +/// Arithmetic right-shift this APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt APInt::ashr(const APInt &shiftAmt) const { + return ashr((uint32_t)shiftAmt.getLimitedValue(BitWidth)); +} + /// Arithmetic right-shift this APInt by shiftAmt. /// @brief Arithmetic right-shift function. APInt APInt::ashr(uint32_t shiftAmt) const { @@ -1072,7 +1113,7 @@ APInt APInt::ashr(uint32_t shiftAmt) const { // issues in the algorithm below. if (shiftAmt == BitWidth) { if (isNegative()) - return APInt(BitWidth, -1ULL); + return APInt(BitWidth, -1ULL, true); else return APInt(BitWidth, 0); } @@ -1131,6 +1172,12 @@ APInt APInt::ashr(uint32_t shiftAmt) const { return APInt(val, BitWidth).clearUnusedBits(); } +/// Logical right-shift this APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt APInt::lshr(const APInt &shiftAmt) const { + return lshr((uint32_t)shiftAmt.getLimitedValue(BitWidth)); +} + /// Logical right-shift this APInt by shiftAmt. /// @brief Logical right-shift function. APInt APInt::lshr(uint32_t shiftAmt) const { @@ -1193,6 +1240,13 @@ APInt APInt::lshr(uint32_t shiftAmt) const { return APInt(val, BitWidth).clearUnusedBits(); } +/// Left-shift this APInt by shiftAmt. +/// @brief Left-shift function. +APInt APInt::shl(const APInt &shiftAmt) const { + // It's undefined behavior in C to shift by BitWidth or greater, but + return shl((uint32_t)shiftAmt.getLimitedValue(BitWidth)); +} + /// Left-shift this APInt by shiftAmt. /// @brief Left-shift function. APInt APInt::shl(uint32_t shiftAmt) const { @@ -1252,6 +1306,10 @@ APInt APInt::shl(uint32_t shiftAmt) const { return APInt(val, BitWidth).clearUnusedBits(); } +APInt APInt::rotl(const APInt &rotateAmt) const { + return rotl((uint32_t)rotateAmt.getLimitedValue(BitWidth)); +} + APInt APInt::rotl(uint32_t rotateAmt) const { if (rotateAmt == 0) return *this; @@ -1263,6 +1321,10 @@ APInt APInt::rotl(uint32_t rotateAmt) const { return hi | lo; } +APInt APInt::rotr(const APInt &rotateAmt) const { + return rotr((uint32_t)rotateAmt.getLimitedValue(BitWidth)); +} + APInt APInt::rotr(uint32_t rotateAmt) const { if (rotateAmt == 0) return *this; @@ -1455,8 +1517,8 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, uint64_t result = u_tmp - subtrahend; uint32_t k = j + i; - u[k++] = result & (b-1); // subtract low word - u[k++] = result >> 32; // subtract high word + u[k++] = (uint32_t)(result & (b-1)); // subtract low word + u[k++] = (uint32_t)(result >> 32); // subtract high word while (borrow && k <= m+n) { // deal with borrow to the left borrow = u[k] == 0; u[k]--; @@ -1487,7 +1549,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was // negative, go to step D6; otherwise go on to step D7. - q[j] = qp; + q[j] = (uint32_t)qp; if (isNeg) { // D6. [Add back]. The probability that this step is necessary is very // small, on the order of only 2/b. Make sure that test data accounts for @@ -1583,8 +1645,8 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, memset(U, 0, (m+n+1)*sizeof(uint32_t)); for (unsigned i = 0; i < lhsWords; ++i) { uint64_t tmp = (LHS.getNumWords() == 1 ? LHS.VAL : LHS.pVal[i]); - U[i * 2] = tmp & mask; - U[i * 2 + 1] = tmp >> (sizeof(uint32_t)*8); + U[i * 2] = (uint32_t)(tmp & mask); + U[i * 2 + 1] = (uint32_t)(tmp >> (sizeof(uint32_t)*8)); } U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. @@ -1592,8 +1654,8 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, memset(V, 0, (n)*sizeof(uint32_t)); for (unsigned i = 0; i < rhsWords; ++i) { uint64_t tmp = (RHS.getNumWords() == 1 ? RHS.VAL : RHS.pVal[i]); - V[i * 2] = tmp & mask; - V[i * 2 + 1] = tmp >> (sizeof(uint32_t)*8); + V[i * 2] = (uint32_t)(tmp & mask); + V[i * 2 + 1] = (uint32_t)(tmp >> (sizeof(uint32_t)*8)); } // initialize the quotient and remainder @@ -1629,13 +1691,13 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, remainder = 0; } else if (partial_dividend < divisor) { Q[i] = 0; - remainder = partial_dividend; + remainder = (uint32_t)partial_dividend; } else if (partial_dividend == divisor) { Q[i] = 1; remainder = 0; } else { - Q[i] = partial_dividend / divisor; - remainder = partial_dividend - (Q[i] * divisor); + Q[i] = (uint32_t)(partial_dividend / divisor); + remainder = (uint32_t)(partial_dividend - (Q[i] * divisor)); } } if (R) @@ -1878,6 +1940,10 @@ void APInt::fromString(uint32_t numbits, const char *str, uint32_t slen, assert(0 && "huh? we shouldn't get here"); } else if (isdigit(cdigit)) { digit = cdigit - '0'; + assert((radix == 10 || + (radix == 8 && digit != 8 && digit != 9) || + (radix == 2 && (digit == 0 || digit == 1))) && + "Invalid digit in string for given radix"); } else { assert(0 && "Invalid character in digit string"); } @@ -1905,7 +1971,7 @@ void APInt::fromString(uint32_t numbits, const char *str, uint32_t slen, std::string APInt::toString(uint8_t radix, bool wantSigned) const { assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && "Radix should be 2, 8, 10, or 16!"); - static const char *digits[] = { + static const char *const digits[] = { "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" }; std::string result; @@ -1925,7 +1991,7 @@ std::string APInt::toString(uint8_t radix, bool wantSigned) const { memset(buf, 0, 65); uint64_t v = VAL; while (bits_used) { - uint32_t bit = v & 1; + uint32_t bit = (uint32_t)v & 1; bits_used--; buf[bits_used] = digits[bit][0]; v >>=1; @@ -1960,7 +2026,8 @@ std::string APInt::toString(uint8_t radix, bool wantSigned) const { uint64_t mask = radix - 1; APInt zero(tmp.getBitWidth(), 0); while (tmp.ne(zero)) { - unsigned digit = (tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask; + unsigned digit = + (unsigned)((tmp.isSingleWord() ? tmp.VAL : tmp.pVal[0]) & mask); result.insert(insert_at, digits[digit]); tmp = tmp.lshr(shift); } @@ -1981,14 +2048,14 @@ std::string APInt::toString(uint8_t radix, bool wantSigned) const { result = "-"; insert_at = 1; } - if (tmp == APInt(tmp.getBitWidth(), 0)) + if (tmp == zero) result = "0"; else while (tmp.ne(zero)) { APInt APdigit(1,0); APInt tmp2(tmp.getBitWidth(), 0); divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, &APdigit); - uint32_t digit = APdigit.getZExtValue(); + uint32_t digit = (uint32_t)APdigit.getZExtValue(); assert(digit < radix && "divide failed"); result.insert(insert_at,digits[digit]); tmp = tmp2; @@ -2021,7 +2088,7 @@ namespace { /* Returns the integer part with the least significant BITS set. BITS cannot be zero. */ - inline integerPart + static inline integerPart lowBitMask(unsigned int bits) { assert (bits != 0 && bits <= integerPartWidth); @@ -2030,14 +2097,14 @@ namespace { } /* Returns the value of the lower half of PART. */ - inline integerPart + static inline integerPart lowHalf(integerPart part) { return part & lowBitMask(integerPartWidth / 2); } /* Returns the value of the upper half of PART. */ - inline integerPart + static inline integerPart highHalf(integerPart part) { return part >> (integerPartWidth / 2); @@ -2045,7 +2112,7 @@ namespace { /* Returns the bit number of the most significant set bit of a part. If the input number has no bits set -1U is returned. */ - unsigned int + static unsigned int partMSB(integerPart value) { unsigned int n, msb; @@ -2070,7 +2137,7 @@ namespace { /* Returns the bit number of the least significant set bit of a part. If the input number has no bits set -1U is returned. */ - unsigned int + static unsigned int partLSB(integerPart value) { unsigned int n, lsb; @@ -2101,6 +2168,8 @@ APInt::tcSet(integerPart *dst, integerPart part, unsigned int parts) { unsigned int i; + assert (parts > 0); + dst[0] = part; for(i = 1; i < parts; i++) dst[i] = 0; @@ -2182,6 +2251,43 @@ APInt::tcMSB(const integerPart *parts, unsigned int n) return -1U; } +/* Copy the bit vector of width srcBITS from SRC, starting at bit + srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes + the least significant bit of DST. All high bits above srcBITS in + DST are zero-filled. */ +void +APInt::tcExtract(integerPart *dst, unsigned int dstCount, const integerPart *src, + unsigned int srcBits, unsigned int srcLSB) +{ + unsigned int firstSrcPart, dstParts, shift, n; + + dstParts = (srcBits + integerPartWidth - 1) / integerPartWidth; + assert (dstParts <= dstCount); + + firstSrcPart = srcLSB / integerPartWidth; + tcAssign (dst, src + firstSrcPart, dstParts); + + shift = srcLSB % integerPartWidth; + tcShiftRight (dst, dstParts, shift); + + /* We now have (dstParts * integerPartWidth - shift) bits from SRC + in DST. If this is less that srcBits, append the rest, else + clear the high bits. */ + n = dstParts * integerPartWidth - shift; + if (n < srcBits) { + integerPart mask = lowBitMask (srcBits - n); + dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask) + << n % integerPartWidth); + } else if (n > srcBits) { + if (srcBits % integerPartWidth) + dst[dstParts - 1] &= lowBitMask (srcBits % integerPartWidth); + } + + /* Clear high parts. */ + while (dstParts < dstCount) + dst[dstParts++] = 0; +} + /* DST += RHS + C where C is zero or one. Returns the carry flag. */ integerPart APInt::tcAdd(integerPart *dst, const integerPart *rhs, @@ -2451,31 +2557,33 @@ APInt::tcDivide(integerPart *lhs, const integerPart *rhs, void APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count) { - unsigned int jump, shift; + if (count) { + unsigned int jump, shift; - /* Jump is the inter-part jump; shift is is intra-part shift. */ - jump = count / integerPartWidth; - shift = count % integerPartWidth; + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; - while (parts > jump) { - integerPart part; + while (parts > jump) { + integerPart part; - parts--; + parts--; - /* dst[i] comes from the two parts src[i - jump] and, if we have - an intra-part shift, src[i - jump - 1]. */ - part = dst[parts - jump]; - if (shift) { - part <<= shift; + /* dst[i] comes from the two parts src[i - jump] and, if we have + an intra-part shift, src[i - jump - 1]. */ + part = dst[parts - jump]; + if (shift) { + part <<= shift; if (parts >= jump + 1) part |= dst[parts - jump - 1] >> (integerPartWidth - shift); } - dst[parts] = part; - } + dst[parts] = part; + } - while (parts > 0) - dst[--parts] = 0; + while (parts > 0) + dst[--parts] = 0; + } } /* Shift a bignum right COUNT bits in-place. Shifted in bits are @@ -2483,29 +2591,31 @@ APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count) void APInt::tcShiftRight(integerPart *dst, unsigned int parts, unsigned int count) { - unsigned int i, jump, shift; + if (count) { + unsigned int i, jump, shift; - /* Jump is the inter-part jump; shift is is intra-part shift. */ - jump = count / integerPartWidth; - shift = count % integerPartWidth; + /* Jump is the inter-part jump; shift is is intra-part shift. */ + jump = count / integerPartWidth; + shift = count % integerPartWidth; - /* Perform the shift. This leaves the most significant COUNT bits - of the result at zero. */ - for(i = 0; i < parts; i++) { - integerPart part; + /* Perform the shift. This leaves the most significant COUNT bits + of the result at zero. */ + for(i = 0; i < parts; i++) { + integerPart part; - if (i + jump >= parts) { - part = 0; - } else { - part = dst[i + jump]; - if (shift) { - part >>= shift; - if (i + jump + 1 < parts) - part |= dst[i + jump + 1] << (integerPartWidth - shift); + if (i + jump >= parts) { + part = 0; + } else { + part = dst[i + jump]; + if (shift) { + part >>= shift; + if (i + jump + 1 < parts) + part |= dst[i + jump + 1] << (integerPartWidth - shift); + } } - } - dst[i] = part; + dst[i] = part; + } } }