X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FAPInt.cpp;h=77033428b577dd7aca8b2a19ea3be65febb3f868;hb=a75ce9f5d2236d93c117e861e60e6f3f748c9555;hp=50025d214bcbe23c45a2baf2746c126fae8ae677;hpb=67eadb397a9baf56ff6c227ffefa7c3cff86ae4b;p=oota-llvm.git diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 50025d214bc..77033428b57 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -102,7 +102,7 @@ APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]) clearUnusedBits(); } -APInt::APInt(unsigned numbits, const StringRef& Str, uint8_t radix) +APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix) : BitWidth(numbits), VAL(0) { assert(BitWidth && "Bitwidth too small"); fromString(numbits, Str, radix); @@ -361,7 +361,7 @@ APInt& APInt::operator*=(const APInt& RHS) { unsigned rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; if (!rhsWords) { // X * 0 ===> 0 - clear(); + clearAllBits(); return *this; } @@ -373,7 +373,7 @@ APInt& APInt::operator*=(const APInt& RHS) { mul(dest, pVal, lhsWords, RHS.pVal, rhsWords); // Copy result back into *this - clear(); + clearAllBits(); unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords; memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE); @@ -483,6 +483,7 @@ APInt APInt::operator-(const APInt& RHS) const { } bool APInt::operator[](unsigned bitPosition) const { + assert(bitPosition < getBitWidth() && "Bit position out of bounds!"); return (maskBit(bitPosition) & (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; } @@ -561,12 +562,12 @@ bool APInt::slt(const APInt& RHS) const { bool rhsNeg = rhs.isNegative(); if (lhsNeg) { // Sign bit is set so perform two's complement to make it positive - lhs.flip(); + lhs.flipAllBits(); lhs++; } if (rhsNeg) { // Sign bit is set so perform two's complement to make it positive - rhs.flip(); + rhs.flipAllBits(); rhs++; } @@ -583,22 +584,20 @@ bool APInt::slt(const APInt& RHS) const { return lhs.ult(rhs); } -APInt& APInt::set(unsigned bitPosition) { +void APInt::setBit(unsigned bitPosition) { if (isSingleWord()) VAL |= maskBit(bitPosition); else pVal[whichWord(bitPosition)] |= maskBit(bitPosition); - return *this; } /// Set the given bit to 0 whose position is given as "bitPosition". /// @brief Set a given bit to 0. -APInt& APInt::clear(unsigned bitPosition) { +void APInt::clearBit(unsigned bitPosition) { if (isSingleWord()) VAL &= ~maskBit(bitPosition); else pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); - return *this; } /// @brief Toggle every bit to its opposite value. @@ -606,14 +605,13 @@ APInt& APInt::clear(unsigned bitPosition) { /// Toggle a given bit to its opposite value whose position is given /// as "bitPosition". /// @brief Toggles a given bit to its opposite value. -APInt& APInt::flip(unsigned bitPosition) { +void APInt::flipBit(unsigned bitPosition) { assert(bitPosition < BitWidth && "Out of the bit-width range!"); - if ((*this)[bitPosition]) clear(bitPosition); - else set(bitPosition); - return *this; + if ((*this)[bitPosition]) clearBit(bitPosition); + else setBit(bitPosition); } -unsigned APInt::getBitsNeeded(const StringRef& str, uint8_t radix) { +unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) { assert(!str.empty() && "Invalid string length"); assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && "Radix should be 2, 8, 10, or 16!"); @@ -761,10 +759,6 @@ APInt APInt::getLoBits(unsigned numBits) const { BitWidth - numBits); } -bool APInt::isPowerOf2() const { - return (!!*this) && !(*this & (*this - APInt(BitWidth,1))); -} - unsigned APInt::countLeadingZerosSlowCase() const { // Treat the most significand word differently because it might have // meaningless bits set beyond the precision. @@ -1001,96 +995,90 @@ double APInt::roundToDouble(bool isSigned) const { } // Truncate to new width. -APInt &APInt::trunc(unsigned width) { +APInt APInt::trunc(unsigned width) const { assert(width < BitWidth && "Invalid APInt Truncate request"); assert(width && "Can't truncate to 0 bits"); - unsigned wordsBefore = getNumWords(); - BitWidth = width; - unsigned wordsAfter = getNumWords(); - if (wordsBefore != wordsAfter) { - if (wordsAfter == 1) { - uint64_t *tmp = pVal; - VAL = pVal[0]; - delete [] tmp; - } else { - uint64_t *newVal = getClearedMemory(wordsAfter); - for (unsigned i = 0; i < wordsAfter; ++i) - newVal[i] = pVal[i]; - delete [] pVal; - pVal = newVal; - } - } - return clearUnusedBits(); + + if (width <= APINT_BITS_PER_WORD) + return APInt(width, getRawData()[0]); + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy full words. + unsigned i; + for (i = 0; i != width / APINT_BITS_PER_WORD; i++) + Result.pVal[i] = pVal[i]; + + // Truncate and copy any partial word. + unsigned bits = (0 - width) % APINT_BITS_PER_WORD; + if (bits != 0) + Result.pVal[i] = pVal[i] << bits >> bits; + + return Result; } // Sign extend to a new width. -APInt &APInt::sext(unsigned width) { +APInt APInt::sext(unsigned width) const { assert(width > BitWidth && "Invalid APInt SignExtend request"); - // If the sign bit isn't set, this is the same as zext. - if (!isNegative()) { - zext(width); - return *this; + + if (width <= APINT_BITS_PER_WORD) { + uint64_t val = VAL << (APINT_BITS_PER_WORD - BitWidth); + val = (int64_t)val >> (width - BitWidth); + return APInt(width, val >> (APINT_BITS_PER_WORD - width)); } - // The sign bit is set. First, get some facts - unsigned wordsBefore = getNumWords(); - unsigned wordBits = BitWidth % APINT_BITS_PER_WORD; - BitWidth = width; - unsigned wordsAfter = getNumWords(); - - // Mask the high order word appropriately - if (wordsBefore == wordsAfter) { - unsigned newWordBits = width % APINT_BITS_PER_WORD; - // The extension is contained to the wordsBefore-1th word. - uint64_t mask = ~0ULL; - if (newWordBits) - mask >>= APINT_BITS_PER_WORD - newWordBits; - mask <<= wordBits; - if (wordsBefore == 1) - VAL |= mask; - else - pVal[wordsBefore-1] |= mask; - return clearUnusedBits(); + APInt Result(getMemory(getNumWords(width)), width); + + // Copy full words. + unsigned i; + uint64_t word = 0; + for (i = 0; i != BitWidth / APINT_BITS_PER_WORD; i++) { + word = getRawData()[i]; + Result.pVal[i] = word; } - uint64_t mask = wordBits == 0 ? 0 : ~0ULL << wordBits; - uint64_t *newVal = getMemory(wordsAfter); - if (wordsBefore == 1) - newVal[0] = VAL | mask; - else { - for (unsigned i = 0; i < wordsBefore; ++i) - newVal[i] = pVal[i]; - newVal[wordsBefore-1] |= mask; + // Read and sign-extend any partial word. + unsigned bits = (0 - BitWidth) % APINT_BITS_PER_WORD; + if (bits != 0) + word = (int64_t)getRawData()[i] << bits >> bits; + else + word = (int64_t)word >> (APINT_BITS_PER_WORD - 1); + + // Write remaining full words. + for (; i != width / APINT_BITS_PER_WORD; i++) { + Result.pVal[i] = word; + word = (int64_t)word >> (APINT_BITS_PER_WORD - 1); } - for (unsigned i = wordsBefore; i < wordsAfter; i++) - newVal[i] = -1ULL; - if (wordsBefore != 1) - delete [] pVal; - pVal = newVal; - return clearUnusedBits(); + + // Write any partial word. + bits = (0 - width) % APINT_BITS_PER_WORD; + if (bits != 0) + Result.pVal[i] = word << bits >> bits; + + return Result; } // Zero extend to a new width. -APInt &APInt::zext(unsigned width) { +APInt APInt::zext(unsigned width) const { assert(width > BitWidth && "Invalid APInt ZeroExtend request"); - unsigned wordsBefore = getNumWords(); - BitWidth = width; - unsigned wordsAfter = getNumWords(); - if (wordsBefore != wordsAfter) { - uint64_t *newVal = getClearedMemory(wordsAfter); - if (wordsBefore == 1) - newVal[0] = VAL; - else - for (unsigned i = 0; i < wordsBefore; ++i) - newVal[i] = pVal[i]; - if (wordsBefore != 1) - delete [] pVal; - pVal = newVal; - } - return *this; + + if (width <= APINT_BITS_PER_WORD) + return APInt(width, VAL); + + APInt Result(getMemory(getNumWords(width)), width); + + // Copy words. + unsigned i; + for (i = 0; i != getNumWords(); i++) + Result.pVal[i] = getRawData()[i]; + + // Zero remaining words. + memset(&Result.pVal[i], 0, (Result.getNumWords() - i) * APINT_WORD_SIZE); + + return Result; } -APInt &APInt::zextOrTrunc(unsigned width) { +APInt APInt::zextOrTrunc(unsigned width) const { if (BitWidth < width) return zext(width); if (BitWidth > width) @@ -1098,7 +1086,7 @@ APInt &APInt::zextOrTrunc(unsigned width) { return *this; } -APInt &APInt::sextOrTrunc(unsigned width) { +APInt APInt::sextOrTrunc(unsigned width) const { if (BitWidth < width) return sext(width); if (BitWidth > width) @@ -1382,13 +1370,12 @@ APInt APInt::sqrt() const { // libc sqrt function which will probably use a hardware sqrt computation. // This should be faster than the algorithm below. if (magnitude < 52) { -#if defined( _MSC_VER ) || defined(_MINIX) - // Amazingly, VC++ and Minix don't have round(). +#if HAVE_ROUND return APInt(BitWidth, - uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); #else return APInt(BitWidth, - uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); + uint64_t(::sqrt(double(isSingleWord()?VAL:pVal[0]))) + 0.5); #endif } @@ -1874,7 +1861,7 @@ void APInt::divide(const APInt LHS, unsigned lhsWords, if (!Quotient->isSingleWord()) Quotient->pVal = getClearedMemory(Quotient->getNumWords()); } else - Quotient->clear(); + Quotient->clearAllBits(); // The quotient is in Q. Reconstitute the quotient into Quotient's low // order words. @@ -1905,7 +1892,7 @@ void APInt::divide(const APInt LHS, unsigned lhsWords, if (!Remainder->isSingleWord()) Remainder->pVal = getClearedMemory(Remainder->getNumWords()); } else - Remainder->clear(); + Remainder->clearAllBits(); // The remainder is in R. Reconstitute the remainder into Remainder's low // order words. @@ -2047,7 +2034,65 @@ void APInt::udivrem(const APInt &LHS, const APInt &RHS, divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); } -void APInt::fromString(unsigned numbits, const StringRef& str, uint8_t radix) { +APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this+RHS; + Overflow = isNonNegative() == RHS.isNonNegative() && + Res.isNonNegative() != isNonNegative(); + return Res; +} + +APInt APInt::uadd_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this+RHS; + Overflow = Res.ult(RHS); + return Res; +} + +APInt APInt::ssub_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this - RHS; + Overflow = isNonNegative() != RHS.isNonNegative() && + Res.isNonNegative() != isNonNegative(); + return Res; +} + +APInt APInt::usub_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this-RHS; + Overflow = Res.ugt(*this); + return Res; +} + +APInt APInt::sdiv_ov(const APInt &RHS, bool &Overflow) const { + // MININT/-1 --> overflow. + Overflow = isMinSignedValue() && RHS.isAllOnesValue(); + return sdiv(RHS); +} + +APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const { + APInt Res = *this * RHS; + + if (*this != 0 && RHS != 0) + Overflow = Res.sdiv(RHS) != *this || Res.sdiv(*this) != RHS; + else + Overflow = false; + return Res; +} + +APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { + Overflow = ShAmt >= getBitWidth(); + if (Overflow) + ShAmt = getBitWidth()-1; + + if (isNonNegative()) // Don't allow sign change. + Overflow = ShAmt >= countLeadingZeros(); + else + Overflow = ShAmt >= countLeadingOnes(); + + return *this << ShAmt; +} + + + + +void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { // Check our assumptions here assert(!str.empty() && "Invalid string length"); assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && @@ -2102,7 +2147,7 @@ void APInt::fromString(unsigned numbits, const StringRef& str, uint8_t radix) { // If its negative, put it in two's complement form if (isNeg) { (*this)--; - this->flip(); + this->flipAllBits(); } } @@ -2124,15 +2169,16 @@ void APInt::toString(SmallVectorImpl &Str, unsigned Radix, char *BufPtr = Buffer+65; uint64_t N; - if (Signed) { + if (!Signed) { + N = getZExtValue(); + } else { int64_t I = getSExtValue(); - if (I < 0) { + if (I >= 0) { + N = I; + } else { Str.push_back('-'); - I = -I; + N = -(uint64_t)I; } - N = I; - } else { - N = getZExtValue(); } while (N) { @@ -2149,7 +2195,7 @@ void APInt::toString(SmallVectorImpl &Str, unsigned Radix, // They want to print the signed version and it is a negative value // Flip the bits and add one to turn it into the equivalent positive // value and put a '-' in the result. - Tmp.flip(); + Tmp.flipAllBits(); Tmp++; Str.push_back('-'); }