X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FAPInt.cpp;h=5a6bb66247c5afac8b1cf12ac7fc9558781182df;hb=f09aef7698bbae79a67287a353c63c1ca31055b0;hp=c8ab2d762b6bc84ffeef3b434770e951ce289c51;hpb=ab2b2c827c4a60e558efaea3bfeb1ebd13b5985b;p=oota-llvm.git diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index c8ab2d762b6..5a6bb66247c 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -2,30 +2,31 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Sheng Zhou and is distributed under the +// 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 implements a class to represent arbitrary precision integral -// constant values. +// This file implements a class to represent arbitrary precision integer +// constant values and provide a variety of arithmetic operations on them. // //===----------------------------------------------------------------------===// +#define DEBUG_TYPE "apint" #include "llvm/ADT/APInt.h" #include "llvm/DerivedTypes.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" #include #include #ifndef NDEBUG -#include #include #endif using namespace llvm; -// A utility function for allocating memory, checking for allocation failures, -// and ensuring the contents is zeroed. +/// A utility function for allocating memory, checking for allocation failures, +/// and ensuring the contents are zeroed. inline static uint64_t* getClearedMemory(uint32_t numWords) { uint64_t * result = new uint64_t[numWords]; assert(result && "APInt memory allocation fails!"); @@ -33,23 +34,24 @@ inline static uint64_t* getClearedMemory(uint32_t numWords) { return result; } -// A utility function for allocating memory and checking for allocation failure. +/// A utility function for allocating memory and checking for allocation +/// failure. The content is not zeroed. inline static uint64_t* getMemory(uint32_t numWords) { uint64_t * result = new uint64_t[numWords]; assert(result && "APInt memory allocation fails!"); return result; } -APInt::APInt(uint32_t numBits, uint64_t val) - : BitWidth(numBits), VAL(0) { +APInt::APInt(uint32_t numBits, uint64_t val) : BitWidth(numBits), VAL(0) { assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small"); assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); - if (isSingleWord()) - VAL = val & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth)); + if (isSingleWord()) + VAL = val; else { pVal = getClearedMemory(getNumWords()); pVal[0] = val; } + clearUnusedBits(); } APInt::APInt(uint32_t numBits, uint32_t numWords, uint64_t bigVal[]) @@ -58,38 +60,31 @@ APInt::APInt(uint32_t numBits, uint32_t numWords, uint64_t bigVal[]) assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large"); assert(bigVal && "Null pointer detected!"); if (isSingleWord()) - VAL = bigVal[0] & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth)); + VAL = bigVal[0]; else { - pVal = getMemory(getNumWords()); - // Calculate the actual length of bigVal[]. - uint32_t maxN = std::max(numWords, getNumWords()); - uint32_t minN = std::min(numWords, getNumWords()); - memcpy(pVal, bigVal, (minN - 1) * APINT_WORD_SIZE); - pVal[minN-1] = bigVal[minN-1] & - (~uint64_t(0ULL) >> - (APINT_BITS_PER_WORD - BitWidth % APINT_BITS_PER_WORD)); - if (maxN == getNumWords()) - memset(pVal+numWords, 0, (getNumWords() - numWords) * APINT_WORD_SIZE); + // Get memory, cleared to 0 + pVal = getClearedMemory(getNumWords()); + // Calculate the number of words to copy + uint32_t words = std::min(numWords, getNumWords()); + // Copy the words from bigVal to pVal + memcpy(pVal, bigVal, words * APINT_WORD_SIZE); } + // Make sure unused high bits are cleared + clearUnusedBits(); } -/// @brief Create a new APInt by translating the char array represented -/// integer value. APInt::APInt(uint32_t numbits, const char StrStart[], uint32_t slen, uint8_t radix) : BitWidth(numbits), VAL(0) { fromString(numbits, StrStart, slen, radix); } -/// @brief Create a new APInt by translating the string represented -/// integer value. APInt::APInt(uint32_t numbits, const std::string& Val, uint8_t radix) : BitWidth(numbits), VAL(0) { assert(!Val.empty() && "String empty?"); fromString(numbits, Val.c_str(), Val.size(), radix); } -/// @brief Copy constructor APInt::APInt(const APInt& that) : BitWidth(that.BitWidth), VAL(0) { if (isSingleWord()) @@ -102,22 +97,45 @@ APInt::APInt(const APInt& that) APInt::~APInt() { if (!isSingleWord() && pVal) - delete[] pVal; + delete [] pVal; } -/// @brief Copy assignment operator. Create a new object from the given -/// APInt one by initialization. APInt& APInt::operator=(const APInt& RHS) { - assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) + // Don't do anything for X = X + if (this == &RHS) + return *this; + + // If the bitwidths are the same, we can avoid mucking with memory + if (BitWidth == RHS.getBitWidth()) { + if (isSingleWord()) + VAL = RHS.VAL; + else + memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE); + return *this; + } + + if (isSingleWord()) + if (RHS.isSingleWord()) + VAL = RHS.VAL; + else { + VAL = 0; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } + else if (getNumWords() == RHS.getNumWords()) + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + else if (RHS.isSingleWord()) { + delete [] pVal; VAL = RHS.VAL; - else - memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE); - return *this; + } else { + delete [] pVal; + pVal = getMemory(RHS.getNumWords()); + memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); + } + BitWidth = RHS.BitWidth; + return clearUnusedBits(); } -/// @brief Assignment operator. Assigns a common case integer value to -/// the APInt. APInt& APInt::operator=(uint64_t RHS) { if (isSingleWord()) VAL = RHS; @@ -125,22 +143,20 @@ APInt& APInt::operator=(uint64_t RHS) { pVal[0] = RHS; memset(pVal+1, 0, (getNumWords() - 1) * APINT_WORD_SIZE); } - return *this; + return clearUnusedBits(); } /// 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. /// @returns the carry of the addition. -static uint64_t add_1(uint64_t dest[], - uint64_t x[], uint32_t len, - uint64_t y) { +static bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { for (uint32_t i = 0; i < len; ++i) { dest[i] = y + x[i]; if (dest[i] < y) - y = 1; + y = 1; // Carry one to next digit. else { - y = 0; + y = 0; // No need to carry so exit early break; } } @@ -153,8 +169,7 @@ APInt& APInt::operator++() { ++VAL; else add_1(pVal, pVal, getNumWords(), 1); - clearUnusedBits(); - return *this; + return clearUnusedBits(); } /// sub_1 - This function subtracts a single "digit" (64-bit word), y, from @@ -162,8 +177,8 @@ APInt& APInt::operator++() { /// no further borrowing is neeeded or it runs out of "digits" in x. The result /// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. /// In other words, if y > x then this function returns 1, otherwise 0. -static uint64_t sub_1(uint64_t x[], uint32_t len, - uint64_t y) { +/// @returns the borrow out of the subtraction +static bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { for (uint32_t i = 0; i < len; ++i) { uint64_t X = x[i]; x[i] -= y; @@ -174,7 +189,7 @@ static uint64_t sub_1(uint64_t x[], uint32_t len, break; // Remaining digits are unchanged so exit early } } - return y; + return bool(y); } /// @brief Prefix decrement operator. Decrements the APInt by one. @@ -183,24 +198,27 @@ APInt& APInt::operator--() { --VAL; else sub_1(pVal, getNumWords(), 1); - clearUnusedBits(); - return *this; + return clearUnusedBits(); } -/// add - This function adds the integer array x[] by integer array -/// y[] and returns the carry. -static uint64_t add(uint64_t dest[], uint64_t x[], uint64_t y[], uint32_t len) { - uint64_t carry = 0; +/// add - This function adds the integer array x to the integer array Y and +/// places the result in dest. +/// @returns the carry out from the addition +/// @brief General addition of 64-bit integer arrays +static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t len) { + bool carry = false; for (uint32_t i = 0; i< len; ++i) { + uint64_t limit = std::min(x[i],y[i]); // must come first in case dest == x dest[i] = x[i] + y[i] + carry; - uint64_t limit = std::min(x[i],y[i]); carry = dest[i] < limit || (carry && dest[i] == limit); } return carry; } -/// @brief Addition assignment operator. Adds this APInt by the given APInt& -/// RHS and assigns the result to this APInt. +/// Adds the RHS APint to this APInt. +/// @returns this, after addition of RHS. +/// @brief Addition assignment operator. APInt& APInt::operator+=(const APInt& RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) @@ -208,14 +226,14 @@ APInt& APInt::operator+=(const APInt& RHS) { else { add(pVal, pVal, RHS.pVal, getNumWords()); } - clearUnusedBits(); - return *this; + return clearUnusedBits(); } -/// sub - This function subtracts the integer array x[] by -/// integer array y[], and returns the borrow-out carry. -static uint64_t sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, - uint32_t len) { +/// Subtracts the integer array y from the integer array x +/// @returns returns the borrow out. +/// @brief Generalized subtraction of 64-bit integer arrays. +static bool sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, + uint32_t len) { bool borrow = false; for (uint32_t i = 0; i < len; ++i) { uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; @@ -225,31 +243,33 @@ static uint64_t sub(uint64_t *dest, const uint64_t *x, const uint64_t *y, return borrow; } -/// @brief Subtraction assignment operator. Subtracts this APInt by the given -/// APInt &RHS and assigns the result to this APInt. +/// Subtracts the RHS APInt from this APInt +/// @returns this, after subtraction +/// @brief Subtraction assignment operator. APInt& APInt::operator-=(const APInt& RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) VAL -= RHS.VAL; else sub(pVal, pVal, RHS.pVal, getNumWords()); - clearUnusedBits(); - return *this; + return clearUnusedBits(); } -/// mul_1 - This function performs the multiplication operation on a -/// large integer (represented as an integer array) and a uint64_t integer. -/// @returns the carry of the multiplication. -static uint64_t mul_1(uint64_t dest[], - uint64_t x[], uint32_t len, - uint64_t y) { - // Split y into high 32-bit part and low 32-bit part. +/// Multiplies an integer array, x by a a uint64_t integer and places the result +/// into dest. +/// @returns the carry out of the multiplication. +/// @brief Multiply a multi-digit APInt by a single digit (64-bit) integer. +static uint64_t mul_1(uint64_t dest[], uint64_t x[], uint32_t len, uint64_t y) { + // Split y into high 32-bit part (hy) and low 32-bit part (ly) uint64_t ly = y & 0xffffffffULL, hy = y >> 32; - uint64_t carry = 0, lx, hx; + uint64_t carry = 0; + + // For each digit of x. for (uint32_t i = 0; i < len; ++i) { - lx = x[i] & 0xffffffffULL; - hx = x[i] >> 32; - // hasCarry - A flag to indicate if has carry. + // Split x into high and low words + uint64_t lx = x[i] & 0xffffffffULL; + uint64_t hx = x[i] >> 32; + // hasCarry - A flag to indicate if there is a carry to the next digit. // hasCarry == 0, no carry // hasCarry == 1, has carry // hasCarry == 2, no carry and the calculation result == 0. @@ -267,17 +287,15 @@ static uint64_t mul_1(uint64_t dest[], carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) + (carry >> 32) + ((lx * hy) >> 32) + hx * hy; } - return carry; } -/// mul - This function multiplies integer array x[] by integer array y[] and -/// stores the result into integer array dest[]. -/// Note the array dest[]'s size should no less than xlen + ylen. -static void mul(uint64_t dest[], uint64_t x[], uint32_t xlen, - uint64_t y[], uint32_t ylen) { +/// Multiplies integer array x by integer array y and stores the result into +/// the integer array dest. Note that dest's size must be >= xlen + ylen. +/// @brief Generalized multiplicate of integer arrays. +static void mul(uint64_t dest[], uint64_t x[], uint32_t xlen, uint64_t y[], + uint32_t ylen) { dest[xlen] = mul_1(dest, x, xlen, y[0]); - for (uint32_t i = 1; i < ylen; ++i) { uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32; uint64_t carry = 0, lx = 0, hx = 0; @@ -305,8 +323,6 @@ static void mul(uint64_t dest[], uint64_t x[], uint32_t xlen, } } -/// @brief Multiplication assignment operator. Multiplies this APInt by the -/// given APInt& RHS and assigns the result to this APInt. APInt& APInt::operator*=(const APInt& RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) { @@ -348,8 +364,6 @@ APInt& APInt::operator*=(const APInt& RHS) { return *this; } -/// @brief Bitwise AND assignment operator. Performs bitwise AND operation on -/// this APInt and the given APInt& RHS, assigns the result to this APInt. APInt& APInt::operator&=(const APInt& RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) { @@ -362,8 +376,6 @@ APInt& APInt::operator&=(const APInt& RHS) { return *this; } -/// @brief Bitwise OR assignment operator. Performs bitwise OR operation on -/// this APInt and the given APInt& RHS, assigns the result to this APInt. APInt& APInt::operator|=(const APInt& RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) { @@ -376,8 +388,6 @@ APInt& APInt::operator|=(const APInt& RHS) { return *this; } -/// @brief Bitwise XOR assignment operator. Performs bitwise XOR operation on -/// this APInt and the given APInt& RHS, assigns the result to this APInt. APInt& APInt::operator^=(const APInt& RHS) { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) { @@ -388,56 +398,47 @@ APInt& APInt::operator^=(const APInt& RHS) { uint32_t numWords = getNumWords(); for (uint32_t i = 0; i < numWords; ++i) pVal[i] ^= RHS.pVal[i]; - this->clearUnusedBits(); - return *this; + return clearUnusedBits(); } -/// @brief Bitwise AND operator. Performs bitwise AND operation on this APInt -/// and the given APInt& RHS. APInt APInt::operator&(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) return APInt(getBitWidth(), VAL & RHS.VAL); - APInt Result(*this); uint32_t numWords = getNumWords(); + uint64_t* val = getMemory(numWords); for (uint32_t i = 0; i < numWords; ++i) - Result.pVal[i] &= RHS.pVal[i]; - return Result; + val[i] = pVal[i] & RHS.pVal[i]; + return APInt(val, getBitWidth()); } -/// @brief Bitwise OR operator. Performs bitwise OR operation on this APInt -/// and the given APInt& RHS. APInt APInt::operator|(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) return APInt(getBitWidth(), VAL | RHS.VAL); - APInt Result(*this); uint32_t numWords = getNumWords(); + uint64_t *val = getMemory(numWords); for (uint32_t i = 0; i < numWords; ++i) - Result.pVal[i] |= RHS.pVal[i]; - return Result; + val[i] = pVal[i] | RHS.pVal[i]; + return APInt(val, getBitWidth()); } -/// @brief Bitwise XOR operator. Performs bitwise XOR operation on this APInt -/// and the given APInt& RHS. APInt APInt::operator^(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) { - APInt Result(BitWidth, VAL ^ RHS.VAL); - Result.clearUnusedBits(); - return Result; - } - APInt Result(*this); + if (isSingleWord()) + return APInt(BitWidth, VAL ^ RHS.VAL); + uint32_t numWords = getNumWords(); + uint64_t *val = getMemory(numWords); for (uint32_t i = 0; i < numWords; ++i) - Result.pVal[i] ^= RHS.pVal[i]; - return Result; + val[i] = pVal[i] ^ RHS.pVal[i]; + + // 0^0==1 so clear the high bits in case they got set. + return APInt(val, getBitWidth()).clearUnusedBits(); } -/// @brief Logical negation operator. Performs logical negation operation on -/// this APInt. bool APInt::operator !() const { if (isSingleWord()) return !VAL; @@ -448,77 +449,62 @@ bool APInt::operator !() const { return true; } -/// @brief Multiplication operator. Multiplies this APInt by the given APInt& -/// RHS. APInt APInt::operator*(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) { - APInt Result(BitWidth, VAL * RHS.VAL); - Result.clearUnusedBits(); - return Result; - } + if (isSingleWord()) + return APInt(BitWidth, VAL * RHS.VAL); APInt Result(*this); Result *= RHS; - Result.clearUnusedBits(); - return Result; + return Result.clearUnusedBits(); } -/// @brief Addition operator. Adds this APInt by the given APInt& RHS. APInt APInt::operator+(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) { - APInt Result(BitWidth, VAL + RHS.VAL); - Result.clearUnusedBits(); - return Result; - } + if (isSingleWord()) + return APInt(BitWidth, VAL + RHS.VAL); APInt Result(BitWidth, 0); add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - Result.clearUnusedBits(); - return Result; + return Result.clearUnusedBits(); } -/// @brief Subtraction operator. Subtracts this APInt by the given APInt& RHS APInt APInt::operator-(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) { - APInt Result(BitWidth, VAL - RHS.VAL); - Result.clearUnusedBits(); - return Result; - } + if (isSingleWord()) + return APInt(BitWidth, VAL - RHS.VAL); APInt Result(BitWidth, 0); sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - Result.clearUnusedBits(); - return Result; + return Result.clearUnusedBits(); } -/// @brief Array-indexing support. bool APInt::operator[](uint32_t bitPosition) const { - return (maskBit(bitPosition) & (isSingleWord() ? - VAL : pVal[whichWord(bitPosition)])) != 0; + return (maskBit(bitPosition) & + (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; } -/// @brief Equality operator. Compare this APInt with the given APInt& RHS -/// for the validity of the equality relationship. bool APInt::operator==(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); if (isSingleWord()) return VAL == RHS.VAL; + // Get some facts about the number of bits used in the two operands. uint32_t n1 = getActiveBits(); uint32_t n2 = RHS.getActiveBits(); + + // If the number of bits isn't the same, they aren't equal if (n1 != n2) return false; + // If the number of bits fits in a word, we only need to compare the low word. if (n1 <= APINT_BITS_PER_WORD) return pVal[0] == RHS.pVal[0]; + // Otherwise, compare everything for (int i = whichWord(n1 - 1); i >= 0; --i) if (pVal[i] != RHS.pVal[i]) return false; return true; } -/// @brief Equality operator. Compare this APInt with the given uint64_t value -/// for the validity of the equality relationship. bool APInt::operator==(uint64_t Val) const { if (isSingleWord()) return VAL == Val; @@ -530,29 +516,38 @@ bool APInt::operator==(uint64_t Val) const { return false; } -/// @brief Unsigned less than comparison bool APInt::ult(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); if (isSingleWord()) return VAL < RHS.VAL; - else { - uint32_t n1 = getActiveBits(); - uint32_t n2 = RHS.getActiveBits(); - if (n1 < n2) - return true; - else if (n2 < n1) + + // Get active bit length of both operands + uint32_t n1 = getActiveBits(); + uint32_t n2 = RHS.getActiveBits(); + + // If magnitude of LHS is less than RHS, return true. + if (n1 < n2) + return true; + + // If magnitude of RHS is greather than LHS, return false. + if (n2 < n1) + return false; + + // If they bot fit in a word, just compare the low order word + if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) + return pVal[0] < RHS.pVal[0]; + + // Otherwise, compare all words + uint32_t topWord = whichWord(std::max(n1,n2)-1); + for (int i = topWord; i >= 0; --i) { + if (pVal[i] > RHS.pVal[i]) return false; - else if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) - return pVal[0] < RHS.pVal[0]; - for (int i = whichWord(n1 - 1); i >= 0; --i) { - if (pVal[i] > RHS.pVal[i]) return false; - else if (pVal[i] < RHS.pVal[i]) return true; - } + if (pVal[i] < RHS.pVal[i]) + return true; } return false; } -/// @brief Signed less than comparison bool APInt::slt(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison"); if (isSingleWord()) { @@ -562,49 +557,52 @@ bool APInt::slt(const APInt& RHS) const { } APInt lhs(*this); - APInt rhs(*this); - bool lhsNegative = false; - bool rhsNegative = false; - if (lhs[BitWidth-1]) { - lhsNegative = true; + APInt rhs(RHS); + bool lhsNeg = isNegative(); + bool rhsNeg = rhs.isNegative(); + if (lhsNeg) { + // Sign bit is set so perform two's complement to make it positive lhs.flip(); lhs++; } - if (rhs[BitWidth-1]) { - rhsNegative = true; + if (rhsNeg) { + // Sign bit is set so perform two's complement to make it positive rhs.flip(); rhs++; } - if (lhsNegative) - if (rhsNegative) - return !lhs.ult(rhs); + + // Now we have unsigned values to compare so do the comparison if necessary + // based on the negativeness of the values. + if (lhsNeg) + if (rhsNeg) + return lhs.ugt(rhs); else return true; - else if (rhsNegative) + else if (rhsNeg) return false; else return lhs.ult(rhs); } -/// Set the given bit to 1 whose poition is given as "bitPosition". -/// @brief Set a given bit to 1. APInt& APInt::set(uint32_t bitPosition) { - if (isSingleWord()) VAL |= maskBit(bitPosition); - else pVal[whichWord(bitPosition)] |= maskBit(bitPosition); + if (isSingleWord()) + VAL |= maskBit(bitPosition); + else + pVal[whichWord(bitPosition)] |= maskBit(bitPosition); return *this; } -/// @brief Set every bit to 1. APInt& APInt::set() { - if (isSingleWord()) - VAL = ~0ULL >> (APINT_BITS_PER_WORD - BitWidth); - else { - for (uint32_t i = 0; i < getNumWords() - 1; ++i) - pVal[i] = -1ULL; - pVal[getNumWords() - 1] = ~0ULL >> - (APINT_BITS_PER_WORD - BitWidth % APINT_BITS_PER_WORD); + if (isSingleWord()) { + VAL = -1ULL; + return clearUnusedBits(); } - return *this; + + // Set all the bits in all the words. + for (uint32_t i = 0; i < getNumWords() - 1; ++i) + pVal[i] = -1ULL; + // Clear the unused ones + return clearUnusedBits(); } /// Set the given bit to 0 whose position is given as "bitPosition". @@ -629,24 +627,20 @@ APInt& APInt::clear() { /// @brief Bitwise NOT operator. Performs a bitwise logical NOT operation on /// this APInt. APInt APInt::operator~() const { - APInt API(*this); - API.flip(); - return API; + APInt Result(*this); + Result.flip(); + return Result; } /// @brief Toggle every bit to its opposite value. APInt& APInt::flip() { - if (isSingleWord()) VAL = (~(VAL << - (APINT_BITS_PER_WORD - BitWidth))) >> (APINT_BITS_PER_WORD - BitWidth); - else { - uint32_t i = 0; - for (; i < getNumWords() - 1; ++i) - pVal[i] = ~pVal[i]; - uint32_t offset = - APINT_BITS_PER_WORD - (BitWidth - APINT_BITS_PER_WORD * (i - 1)); - pVal[i] = (~(pVal[i] << offset)) >> offset; + if (isSingleWord()) { + VAL ^= -1ULL; + return clearUnusedBits(); } - return *this; + for (uint32_t i = 0; i < getNumWords(); ++i) + pVal[i] ^= -1ULL; + return clearUnusedBits(); } /// Toggle a given bit to its opposite value whose position is given @@ -659,37 +653,17 @@ APInt& APInt::flip(uint32_t bitPosition) { return *this; } -/// getMaxValue - This function returns the largest value -/// for an APInt of the specified bit-width and if isSign == true, -/// it should be largest signed value, otherwise unsigned value. -APInt APInt::getMaxValue(uint32_t numBits, bool isSign) { - APInt Result(numBits, 0); - Result.set(); - if (isSign) - Result.clear(numBits - 1); - return Result; -} +uint64_t APInt::getHashValue() const { + // Put the bit width into the low order bits. + uint64_t hash = BitWidth; -/// getMinValue - This function returns the smallest value for -/// an APInt of the given bit-width and if isSign == true, -/// it should be smallest signed value, otherwise zero. -APInt APInt::getMinValue(uint32_t numBits, bool isSign) { - APInt Result(numBits, 0); - if (isSign) - Result.set(numBits - 1); - return Result; -} - -/// getAllOnesValue - This function returns an all-ones value for -/// an APInt of the specified bit-width. -APInt APInt::getAllOnesValue(uint32_t numBits) { - return getMaxValue(numBits, false); -} - -/// getNullValue - This function creates an '0' value for an -/// APInt of the specified bit-width. -APInt APInt::getNullValue(uint32_t numBits) { - return getMinValue(numBits, false); + // Add the sum of the words to the hash. + if (isSingleWord()) + hash += VAL << 6; // clear separation of up to 64 bits + else + for (uint32_t i = 0; i < getNumWords(); ++i) + hash += pVal[i] << 6; // clear sepration of up to 64 bits + return hash; } /// HiBits - This function returns the high "numBits" bits of this APInt. @@ -707,11 +681,6 @@ bool APInt::isPowerOf2() const { return (!!*this) && !(*this & (*this - APInt(BitWidth,1))); } -/// countLeadingZeros - This function is a APInt version corresponding to -/// llvm/include/llvm/Support/MathExtras.h's function -/// countLeadingZeros_{32, 64}. It performs platform optimal form of counting -/// the number of zeros from the most significant bit to the first one bit. -/// @returns numWord() * 64 if the value is zero. uint32_t APInt::countLeadingZeros() const { uint32_t Count = 0; if (isSingleWord()) @@ -732,22 +701,50 @@ uint32_t APInt::countLeadingZeros() const { return Count; } -/// countTrailingZeros - This function is a APInt version corresponding to -/// llvm/include/llvm/Support/MathExtras.h's function -/// countTrailingZeros_{32, 64}. It performs platform optimal form of counting -/// the number of zeros from the least significant bit to the first one bit. -/// @returns numWord() * 64 if the value is zero. +static uint32_t countLeadingOnes_64(uint64_t V, uint32_t skip) { + uint32_t Count = 0; + if (skip) + V <<= skip; + while (V && (V & (1ULL << 63))) { + Count++; + V <<= 1; + } + return Count; +} + +uint32_t APInt::countLeadingOnes() const { + if (isSingleWord()) + return countLeadingOnes_64(VAL, APINT_BITS_PER_WORD - BitWidth); + + uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; + uint32_t shift = (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); + int i = getNumWords() - 1; + uint32_t Count = countLeadingOnes_64(pVal[i], shift); + if (Count == highWordBits) { + for (i--; i >= 0; --i) { + if (pVal[i] == -1ULL) + Count += APINT_BITS_PER_WORD; + else { + Count += countLeadingOnes_64(pVal[i], 0); + break; + } + } + } + return Count; +} + uint32_t APInt::countTrailingZeros() const { if (isSingleWord()) return CountTrailingZeros_64(VAL); - APInt Tmp( ~(*this) & ((*this) - APInt(BitWidth,1)) ); - return getNumWords() * APINT_BITS_PER_WORD - Tmp.countLeadingZeros(); + 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; } -/// countPopulation - This function is a APInt version corresponding to -/// llvm/include/llvm/Support/MathExtras.h's function -/// countPopulation_{32, 64}. It counts the number of set bits in a value. -/// @returns 0 if the value is zero. uint32_t APInt::countPopulation() const { if (isSingleWord()) return CountPopulation_64(VAL); @@ -757,9 +754,6 @@ uint32_t APInt::countPopulation() const { return Count; } - -/// byteSwap - This function returns a byte-swapped representation of the -/// this APInt. APInt APInt::byteSwap() const { assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!"); if (BitWidth == 16) @@ -788,8 +782,6 @@ APInt APInt::byteSwap() const { } } -/// GreatestCommonDivisor - This function returns the greatest common -/// divisor of the two APInt values using Enclid's algorithm. APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1, const APInt& API2) { APInt A = API1, B = API2; @@ -801,23 +793,38 @@ APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1, return A; } -/// DoubleRoundToAPInt - This function convert a double value to -/// a APInt value. -APInt llvm::APIntOps::RoundDoubleToAPInt(double Double) { +APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, uint32_t width) { union { double D; uint64_t I; } T; T.D = Double; + + // Get the sign bit from the highest order bit bool isNeg = T.I >> 63; + + // Get the 11-bit exponent and adjust for the 1023 bit bias int64_t exp = ((T.I >> 52) & 0x7ff) - 1023; + + // If the exponent is negative, the value is < 0 so just return 0. if (exp < 0) - return APInt(64ull, 0u); - uint64_t mantissa = ((T.I << 12) >> 12) | (1ULL << 52); + return APInt(width, 0u); + + // Extract the mantissa by clearing the top 12 bits (sign + exponent). + uint64_t mantissa = (T.I & (~0ULL >> 12)) | 1ULL << 52; + + // If the exponent doesn't shift all bits out of the mantissa if (exp < 52) - return isNeg ? -APInt(64u, mantissa >> (52 - exp)) : - APInt(64u, mantissa >> (52 - exp)); - APInt Tmp(exp + 1, mantissa); + return isNeg ? -APInt(width, mantissa >> (52 - exp)) : + APInt(width, mantissa >> (52 - exp)); + + // If the client didn't provide enough bits for us to shift the mantissa into + // then the result is undefined, just return 0 + if (width <= exp - 52) + return APInt(width, 0); + + // Otherwise, we have to shift the mantissa bits up to the right location + APInt Tmp(width, mantissa); Tmp = Tmp.shl(exp - 52); return isNeg ? -Tmp : Tmp; } @@ -889,154 +896,369 @@ double APInt::roundToDouble(bool isSigned) const { } // Truncate to new width. -void APInt::trunc(uint32_t 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"); + uint32_t wordsBefore = getNumWords(); + BitWidth = width; + uint32_t wordsAfter = getNumWords(); + if (wordsBefore != wordsAfter) { + if (wordsAfter == 1) { + uint64_t *tmp = pVal; + VAL = pVal[0]; + delete [] tmp; + } else { + uint64_t *newVal = getClearedMemory(wordsAfter); + for (uint32_t i = 0; i < wordsAfter; ++i) + newVal[i] = pVal[i]; + delete [] pVal; + pVal = newVal; + } + } + return clearUnusedBits(); } // Sign extend to a new width. -void APInt::sext(uint32_t width) { +APInt &APInt::sext(uint32_t width) { assert(width > BitWidth && "Invalid APInt SignExtend request"); + assert(width <= IntegerType::MAX_INT_BITS && "Too many bits"); + // If the sign bit isn't set, this is the same as zext. + if (!isNegative()) { + zext(width); + return *this; + } + + // The sign bit is set. First, get some facts + uint32_t wordsBefore = getNumWords(); + uint32_t wordBits = BitWidth % APINT_BITS_PER_WORD; + BitWidth = width; + uint32_t wordsAfter = getNumWords(); + + // Mask the high order word appropriately + if (wordsBefore == wordsAfter) { + uint32_t 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(); + } + + uint64_t mask = wordBits == 0 ? 0 : ~0ULL << wordBits; + uint64_t *newVal = getMemory(wordsAfter); + if (wordsBefore == 1) + newVal[0] = VAL | mask; + else { + for (uint32_t i = 0; i < wordsBefore; ++i) + newVal[i] = pVal[i]; + newVal[wordsBefore-1] |= mask; + } + for (uint32_t i = wordsBefore; i < wordsAfter; i++) + newVal[i] = -1ULL; + if (wordsBefore != 1) + delete [] pVal; + pVal = newVal; + return clearUnusedBits(); } // Zero extend to a new width. -void APInt::zext(uint32_t width) { +APInt &APInt::zext(uint32_t width) { assert(width > BitWidth && "Invalid APInt ZeroExtend request"); + assert(width <= IntegerType::MAX_INT_BITS && "Too many bits"); + uint32_t wordsBefore = getNumWords(); + BitWidth = width; + uint32_t wordsAfter = getNumWords(); + if (wordsBefore != wordsAfter) { + uint64_t *newVal = getClearedMemory(wordsAfter); + if (wordsBefore == 1) + newVal[0] = VAL; + else + for (uint32_t i = 0; i < wordsBefore; ++i) + newVal[i] = pVal[i]; + if (wordsBefore != 1) + delete [] pVal; + pVal = newVal; + } + return *this; +} + +APInt &APInt::zextOrTrunc(uint32_t width) { + if (BitWidth < width) + return zext(width); + if (BitWidth > width) + return trunc(width); + return *this; +} + +APInt &APInt::sextOrTrunc(uint32_t width) { + if (BitWidth < width) + return sext(width); + if (BitWidth > width) + return trunc(width); + return *this; } /// Arithmetic right-shift this APInt by shiftAmt. /// @brief Arithmetic right-shift function. APInt APInt::ashr(uint32_t shiftAmt) const { - APInt API(*this); - if (API.isSingleWord()) - API.VAL = - (((int64_t(API.VAL) << (APINT_BITS_PER_WORD - API.BitWidth)) >> - (APINT_BITS_PER_WORD - API.BitWidth)) >> shiftAmt) & - (~uint64_t(0UL) >> (APINT_BITS_PER_WORD - API.BitWidth)); - else { - if (shiftAmt >= API.BitWidth) { - memset(API.pVal, API[API.BitWidth-1] ? 1 : 0, - (API.getNumWords()-1) * APINT_WORD_SIZE); - API.pVal[API.getNumWords() - 1] = - ~uint64_t(0UL) >> - (APINT_BITS_PER_WORD - API.BitWidth % APINT_BITS_PER_WORD); - } else { - uint32_t i = 0; - for (; i < API.BitWidth - shiftAmt; ++i) - if (API[i+shiftAmt]) - API.set(i); - else - API.clear(i); - for (; i < API.BitWidth; ++i) - if (API[API.BitWidth-1]) - API.set(i); - else API.clear(i); + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // undefined + else { + uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth; + return APInt(BitWidth, + (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt)); } } - return API; + + // If all the bits were shifted out, the result is 0 or -1. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. + if (shiftAmt == BitWidth) + if (isNegative()) + return APInt(BitWidth, -1ULL); + else + return APInt(BitWidth, 0); + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = getNumWords()-1; i >= 0; --i) { + val[i] = (pVal[i] >> shiftAmt) | carry; + carry = pVal[i] << (APINT_BITS_PER_WORD - shiftAmt); + } + return APInt(val, BitWidth).clearUnusedBits(); + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < getNumWords() - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = getNumWords()-offset; i < getNumWords(); i++) + val[i] = (isNegative() ? -1ULL : 0); + return APInt(val,BitWidth).clearUnusedBits(); + } + + // Shift the low order words + uint32_t breakWord = getNumWords() - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + uint32_t SignBit = APINT_BITS_PER_WORD - (BitWidth % APINT_BITS_PER_WORD); + val[breakWord] = uint64_t( + (((int64_t(pVal[breakWord+offset]) << SignBit) >> SignBit) >> wordShift)); + + // Remaining words are 0 or -1 + for (uint32_t i = breakWord+1; i < getNumWords(); ++i) + val[i] = (isNegative() ? -1ULL : 0); + return APInt(val, BitWidth).clearUnusedBits(); } /// Logical right-shift this APInt by shiftAmt. /// @brief Logical right-shift function. APInt APInt::lshr(uint32_t shiftAmt) const { - APInt API(*this); - if (API.isSingleWord()) - API.VAL >>= shiftAmt; - else { - if (shiftAmt >= API.BitWidth) - memset(API.pVal, 0, API.getNumWords() * APINT_WORD_SIZE); - uint32_t i = 0; - for (i = 0; i < API.BitWidth - shiftAmt; ++i) - if (API[i+shiftAmt]) API.set(i); - else API.clear(i); - for (; i < API.BitWidth; ++i) - API.clear(i); + if (isSingleWord()) + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + else + return APInt(BitWidth, this->VAL >> shiftAmt); + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, compute the shift with a simple carry + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (int i = getNumWords()-1; i >= 0; --i) { + val[i] = (pVal[i] >> shiftAmt) | carry; + carry = pVal[i] << (APINT_BITS_PER_WORD - shiftAmt); + } + return APInt(val, BitWidth).clearUnusedBits(); + } + + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < getNumWords() - offset; ++i) + val[i] = pVal[i+offset]; + for (uint32_t i = getNumWords()-offset; i < getNumWords(); i++) + val[i] = 0; + return APInt(val,BitWidth).clearUnusedBits(); } - return API; + + // Shift the low order words + uint32_t breakWord = getNumWords() - offset -1; + for (uint32_t i = 0; i < breakWord; ++i) + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + // Shift the break word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Remaining words are 0 + for (uint32_t i = breakWord+1; i < getNumWords(); ++i) + val[i] = 0; + return APInt(val, BitWidth).clearUnusedBits(); } /// Left-shift this APInt by shiftAmt. /// @brief Left-shift function. APInt APInt::shl(uint32_t shiftAmt) const { - APInt API(*this); - if (API.isSingleWord()) - API.VAL <<= shiftAmt; - else if (shiftAmt >= API.BitWidth) - memset(API.pVal, 0, API.getNumWords() * APINT_WORD_SIZE); - else { - if (uint32_t offset = shiftAmt / APINT_BITS_PER_WORD) { - for (uint32_t i = API.getNumWords() - 1; i > offset - 1; --i) - API.pVal[i] = API.pVal[i-offset]; - memset(API.pVal, 0, offset * APINT_WORD_SIZE); + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // avoid undefined shift results + return APInt(BitWidth, VAL << shiftAmt); + } + + // If all the bits were shifted out, the result is 0. This avoids issues + // with shifting by the size of the integer type, which produces undefined + // results. We define these "undefined results" to always be 0. + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // If we are shifting less than a word, do it the easy way + if (shiftAmt < APINT_BITS_PER_WORD) { + uint64_t carry = 0; + for (uint32_t i = 0; i < getNumWords(); i++) { + val[i] = pVal[i] << shiftAmt | carry; + carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt); } - shiftAmt %= APINT_BITS_PER_WORD; - uint32_t i; - for (i = API.getNumWords() - 1; i > 0; --i) - API.pVal[i] = (API.pVal[i] << shiftAmt) | - (API.pVal[i-1] >> (APINT_BITS_PER_WORD - shiftAmt)); - API.pVal[i] <<= shiftAmt; - } - API.clearUnusedBits(); - return API; -} - -#if 0 -/// subMul - This function substracts x[len-1:0] * y from -/// dest[offset+len-1:offset], and returns the most significant -/// word of the product, minus the borrow-out from the subtraction. -static uint32_t subMul(uint32_t dest[], uint32_t offset, - uint32_t x[], uint32_t len, uint32_t y) { - uint64_t yl = (uint64_t) y & 0xffffffffL; - uint32_t carry = 0; - uint32_t j = 0; - do { - uint64_t prod = ((uint64_t) x[j] & 0xffffffffUL) * yl; - uint32_t prod_low = (uint32_t) prod; - uint32_t prod_high = (uint32_t) (prod >> 32); - prod_low += carry; - carry = (prod_low < carry ? 1 : 0) + prod_high; - uint32_t x_j = dest[offset+j]; - prod_low = x_j - prod_low; - if (prod_low > x_j) ++carry; - dest[offset+j] = prod_low; - } while (++j < len); - return carry; -} + return APInt(val, BitWidth).clearUnusedBits(); + } -/// unitDiv - This function divides N by D, -/// and returns (remainder << 32) | quotient. -/// Assumes (N >> 32) < D. -static uint64_t unitDiv(uint64_t N, uint32_t D) { - uint64_t q, r; // q: quotient, r: remainder. - uint64_t a1 = N >> 32; // a1: high 32-bit part of N. - uint64_t a0 = N & 0xffffffffL; // a0: low 32-bit part of N - if (a1 < ((D - a1 - (a0 >> 31)) & 0xffffffffL)) { - q = N / D; - r = N % D; + // Compute some values needed by the remaining shift algorithms + uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; + uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + for (uint32_t i = 0; i < offset; i++) + val[i] = 0; + for (uint32_t i = offset; i < getNumWords(); i++) + val[i] = pVal[i-offset]; + return APInt(val,BitWidth).clearUnusedBits(); } - else { - // Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d - uint64_t c = N - ((uint64_t) D << 31); - // Divide (c1*2^32 + c0) by d - q = c / D; - r = c % D; - // Add 2^31 to quotient - q += 1 << 31; + + // Copy whole words from this to Result. + uint32_t i = getNumWords() - 1; + for (; i > offset; --i) + val[i] = pVal[i-offset] << wordShift | + pVal[i-offset-1] >> (APINT_BITS_PER_WORD - wordShift); + val[offset] = pVal[0] << wordShift; + for (i = 0; i < offset; ++i) + val[i] = 0; + return APInt(val, BitWidth).clearUnusedBits(); +} + + +// Square Root - this method computes and returns the square root of "this". +// Three mechanisms are used for computation. For small values (<= 5 bits), +// a table lookup is done. This gets some performance for common cases. For +// values using less than 52 bits, the value is converted to double and then +// the libc sqrt function is called. The result is rounded and then converted +// back to a uint64_t which is then used to construct the result. Finally, +// the Babylonian method for computing square roots is used. +APInt APInt::sqrt() const { + + // Determine the magnitude of the value. + uint32_t magnitude = getActiveBits(); + + // Use a fast table for some small values. This also gets rid of some + // rounding errors in libc sqrt for small values. + if (magnitude <= 5) { + static const uint8_t results[32] = { + /* 0 */ 0, + /* 1- 2 */ 1, 1, + /* 3- 6 */ 2, 2, 2, 2, + /* 7-12 */ 3, 3, 3, 3, 3, 3, + /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, + /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + /* 31 */ 6 + }; + return APInt(BitWidth, results[ (isSingleWord() ? VAL : pVal[0]) ]); } - return (r << 32) | (q & 0xFFFFFFFFl); -} + // If the magnitude of the value fits in less than 52 bits (the precision of + // an IEEE double precision floating point value), then we can use the + // libc sqrt function which will probably use a hardware sqrt computation. + // This should be faster than the algorithm below. + if (magnitude < 52) + return APInt(BitWidth, + uint64_t(::round(::sqrt(double(isSingleWord()?VAL:pVal[0]))))); + + // Okay, all the short cuts are exhausted. We must compute it. The following + // is a classical Babylonian method for computing the square root. This code + // was adapted to APINt from a wikipedia article on such computations. + // See http://www.wikipedia.org/ and go to the page named + // Calculate_an_integer_square_root. + uint32_t nbits = BitWidth, i = 4; + APInt testy(BitWidth, 16); + APInt x_old(BitWidth, 1); + APInt x_new(BitWidth, 0); + APInt two(BitWidth, 2); + + // Select a good starting value using binary logarithms. + for (;; i += 2, testy = testy.shl(2)) + if (i >= nbits || this->ule(testy)) { + x_old = x_old.shl(i / 2); + break; + } -#endif + // Use the Babylonian method to arrive at the integer square root: + for (;;) { + x_new = (this->udiv(x_old) + x_old).udiv(two); + if (x_old.ule(x_new)) + break; + x_old = x_new; + } -/// div - This is basically Knuth's formulation of the classical algorithm. -/// Correspondance with Knuth's notation: -/// Knuth's u[0:m+n] == zds[nx:0]. -/// Knuth's v[1:n] == y[ny-1:0] -/// Knuth's n == ny. -/// Knuth's m == nx-ny. -/// Our nx == Knuth's m+n. -/// Could be re-implemented using gmp's mpn_divrem: -/// zds[nx] = mpn_divrem (&zds[ny], 0, zds, nx, y, ny). + // Make sure we return the closest approximation + // NOTE: The rounding calculation below is correct. It will produce an + // off-by-one discrepancy with results from pari/gp. That discrepancy has been + // determined to be a rounding issue with pari/gp as it begins to use a + // floating point representation after 192 bits. There are no discrepancies + // between this algorithm and pari/gp for bit widths < 192 bits. + APInt square(x_old * x_old); + APInt nextSquare((x_old + 1) * (x_old +1)); + if (this->ult(square)) + return x_old; + else if (this->ule(nextSquare)) { + APInt midpoint((nextSquare - square).udiv(two)); + APInt offset(*this - square); + if (offset.ult(midpoint)) + return x_old; + else + return x_old + 1; + } else + assert(0 && "Error in APInt::sqrt computation"); + return x_old + 1; +} /// Implementation of Knuth's Algorithm D (Division of nonnegative integers) /// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The @@ -1047,12 +1269,19 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, assert(u && "Must provide dividend"); assert(v && "Must provide divisor"); assert(q && "Must provide quotient"); + assert(u != v && u != q && v != q && "Must us different memory"); assert(n>1 && "n must be > 1"); // Knuth uses the value b as the base of the number system. In our case b // is 2^31 so we just set it to -1u. uint64_t b = uint64_t(1) << 32; + DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); + DEBUG(cerr << "KnuthDiv: original:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + DEBUG(cerr << " by"); + DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + DEBUG(cerr << '\n'); // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of // u and v by d. Note that we have taken Knuth's advice here to use a power // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of @@ -1077,10 +1306,16 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, } } u[m+n] = u_carry; + DEBUG(cerr << "KnuthDiv: normal:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << u[i]); + DEBUG(cerr << " by"); + DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << v[i-1]); + DEBUG(cerr << '\n'); // D2. [Initialize j.] Set j to m. This is the loop counter over the places. int j = m; do { + DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); // D3. [Calculate q'.]. // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') @@ -1089,53 +1324,92 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, // on v[n-2] determines at high speed most of the cases in which the trial // value qp is one too large, and it eliminates all cases where qp is two // too large. - uint64_t qp = ((uint64_t(u[j+n]) << 32) | uint64_t(u[j+n-1])) / v[n-1]; - uint64_t rp = ((uint64_t(u[j+n]) << 32) | uint64_t(u[j+n-1])) % v[n-1]; + uint64_t dividend = ((uint64_t(u[j+n]) << 32) + u[j+n-1]); + DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); + uint64_t qp = dividend / v[n-1]; + uint64_t rp = dividend % v[n-1]; if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { qp--; rp += v[n-1]; - } - if (rp < b) - if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) { + if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2])) qp--; - rp += v[n-1]; - } + } + DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); - // D4. [Multiply and subtract.] Replace u with u - q*v (for each word). - uint32_t borrow = 0; - for (uint32_t i = 0; i < n; i++) { - uint32_t save = u[j+i]; - u[j+i] = uint64_t(u[j+i]) - (qp * v[i]) - borrow; - if (u[j+i] > save) { - borrow = 1; - u[j+i+1] += b; - } else { - borrow = 0; + // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with + // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation + // consists of a simple multiplication by a one-place number, combined with + // a subtraction. + bool isNeg = false; + for (uint32_t i = 0; i < n; ++i) { + uint64_t u_tmp = uint64_t(u[j+i]) | (uint64_t(u[j+i+1]) << 32); + uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); + bool borrow = subtrahend > u_tmp; + DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp + << ", subtrahend == " << subtrahend + << ", borrow = " << borrow << '\n'); + + 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 + while (borrow && k <= m+n) { // deal with borrow to the left + borrow = u[k] == 0; + u[k]--; + k++; + } + isNeg |= borrow; + DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << + u[j+i+1] << '\n'); + } + DEBUG(cerr << "KnuthDiv: after subtraction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n'); + // The digits (u[j+n]...u[j]) should be kept positive; if the result of + // this step is actually negative, (u[j+n]...u[j]) should be left as the + // true value plus b**(n+1), namely as the b's complement of + // the true value, and a "borrow" to the left should be remembered. + // + if (isNeg) { + bool carry = true; // true because b's complement is "complement + 1" + for (uint32_t i = 0; i <= m+n; ++i) { + u[i] = ~u[i] + carry; // b's complement + carry = carry && u[i] == 0; } } - if (borrow) - u[j+n] += 1; + DEBUG(cerr << "KnuthDiv: after complement:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); + DEBUG(cerr << '\n'); // 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; - if (borrow) { + 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 - // this possibility. Decreate qj by 1 and add v[...] to u[...]. A carry - // will occur to the left of u[j+n], and it should be ignored since it - // cancels with the borrow that occurred in D4. - uint32_t carry = 0; + // this possibility. Decrease q[j] by 1 + q[j]--; + // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). + // A carry will occur to the left of u[j+n], and it should be ignored + // since it cancels with the borrow that occurred in D4. + bool carry = false; for (uint32_t i = 0; i < n; i++) { - uint32_t save = u[j+i]; + uint32_t limit = std::min(u[j+i],v[i]); u[j+i] += v[i] + carry; - carry = u[j+i] < save; + carry = u[j+i] < limit || (carry && u[j+i] == limit); } + u[j+n] += carry; } + DEBUG(cerr << "KnuthDiv: after correction:"); + DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); + DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n'); - // D7. [Loop on j.] Decreate j by one. Now if j >= 0, go back to D3. - j--; - } while (j >= 0); + // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. + } while (--j >= 0); + + DEBUG(cerr << "KnuthDiv: quotient:"); + DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); + DEBUG(cerr << '\n'); // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired // remainder may be obtained by dividing u[...] by d. If r is non-null we @@ -1144,19 +1418,25 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r, // The value d is expressed by the "shift" value above since we avoided // multiplication by d by using a shift left. So, all we have to do is // shift right here. In order to mak - uint32_t mask = ~0u >> (32 - shift); - uint32_t carry = 0; - for (int i = n-1; i >= 0; i--) { - uint32_t save = u[i] & mask; - r[i] = (u[i] >> shift) | carry; - carry = save; + if (shift) { + uint32_t carry = 0; + DEBUG(cerr << "KnuthDiv: remainder:"); + for (int i = n-1; i >= 0; i--) { + r[i] = (u[i] >> shift) | carry; + carry = u[i] << (32 - shift); + DEBUG(cerr << " " << r[i]); + } + } else { + for (int i = n-1; i >= 0; i--) { + r[i] = u[i]; + DEBUG(cerr << " " << r[i]); + } } + DEBUG(cerr << '\n'); } + DEBUG(cerr << std::setbase(10) << '\n'); } -// This function makes calling KnuthDiv a little more convenient. It uses -// APInt parameters instead of uint32_t* parameters. It can also divide APInt -// values of different widths. void APInt::divide(const APInt LHS, uint32_t lhsWords, const APInt &RHS, uint32_t rhsWords, APInt *Quotient, APInt *Remainder) @@ -1173,32 +1453,49 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, uint64_t mask = ~0ull >> (sizeof(uint32_t)*8); uint32_t n = rhsWords * 2; uint32_t m = (lhsWords * 2) - n; - // FIXME: allocate space on stack if m and n are sufficiently small. - uint32_t *U = new uint32_t[m + n + 1]; + + // Allocate space for the temporary values we need either on the stack, if + // it will fit, or on the heap if it won't. + uint32_t SPACE[128]; + uint32_t *U = 0; + uint32_t *V = 0; + uint32_t *Q = 0; + uint32_t *R = 0; + if ((Remainder?4:3)*n+2*m+1 <= 128) { + U = &SPACE[0]; + V = &SPACE[m+n+1]; + Q = &SPACE[(m+n+1) + n]; + if (Remainder) + R = &SPACE[(m+n+1) + n + (m+n)]; + } else { + U = new uint32_t[m + n + 1]; + V = new uint32_t[n]; + Q = new uint32_t[m+n]; + if (Remainder) + R = new uint32_t[n]; + } + + // Initialize the dividend memset(U, 0, (m+n+1)*sizeof(uint32_t)); for (unsigned i = 0; i < lhsWords; ++i) { - uint64_t tmp = (lhsWords == 1 ? LHS.VAL : LHS.pVal[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[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm. - uint32_t *V = new uint32_t[n]; + // Initialize the divisor memset(V, 0, (n)*sizeof(uint32_t)); for (unsigned i = 0; i < rhsWords; ++i) { - uint64_t tmp = (rhsWords == 1 ? RHS.VAL : RHS.pVal[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); } - // Set up the quotient and remainder - uint32_t *Q = new uint32_t[m+n]; + // initialize the quotient and remainder memset(Q, 0, (m+n) * sizeof(uint32_t)); - uint32_t *R = 0; - if (Remainder) { - R = new uint32_t[n]; + if (Remainder) memset(R, 0, n * sizeof(uint32_t)); - } // Now, adjust m and n for the Knuth division. n is the number of words in // the divisor. m is the number of words by which the dividend exceeds the @@ -1252,7 +1549,7 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, if (Quotient->isSingleWord()) Quotient->VAL = 0; else - delete Quotient->pVal; + delete [] Quotient->pVal; Quotient->BitWidth = LHS.BitWidth; if (!Quotient->isSingleWord()) Quotient->pVal = getClearedMemory(Quotient->getNumWords()); @@ -1283,7 +1580,7 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, if (Remainder->isSingleWord()) Remainder->VAL = 0; else - delete Remainder->pVal; + delete [] Remainder->pVal; Remainder->BitWidth = RHS.BitWidth; if (!Remainder->isSingleWord()) Remainder->pVal = getClearedMemory(Remainder->getNumWords()); @@ -1308,14 +1605,14 @@ void APInt::divide(const APInt LHS, uint32_t lhsWords, } // Clean up the memory we allocated. - delete [] U; - delete [] V; - delete [] Q; - delete [] R; + if (U != &SPACE[0]) { + delete [] U; + delete [] V; + delete [] Q; + delete [] R; + } } -/// Unsigned divide this APInt by APInt RHS. -/// @brief Unsigned division function for APInt. APInt APInt::udiv(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); @@ -1353,8 +1650,6 @@ APInt APInt::udiv(const APInt& RHS) const { return Quotient; } -/// Unsigned remainder operation on APInt. -/// @brief Function for unsigned remainder operation. APInt APInt::urem(const APInt& RHS) const { assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); if (isSingleWord()) { @@ -1392,13 +1687,15 @@ APInt APInt::urem(const APInt& RHS) const { return Remainder; } -/// @brief Converts a char array into an integer. void APInt::fromString(uint32_t numbits, const char *str, uint32_t slen, uint8_t radix) { // Check our assumptions here assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && "Radix should be 2, 8, 10, or 16!"); assert(str && "String is null?"); + bool isNeg = str[0] == '-'; + if (isNeg) + str++, slen--; assert(slen <= numbits || radix != 2 && "Insufficient bit width"); assert(slen*3 <= numbits || radix != 8 && "Insufficient bit width"); assert(slen*4 <= numbits || radix != 16 && "Insufficient bit width"); @@ -1440,12 +1737,19 @@ void APInt::fromString(uint32_t numbits, const char *str, uint32_t slen, *this *= apradix; // Add in the digit we just interpreted - apdigit.pVal[0] = digit; + if (apdigit.isSingleWord()) + apdigit.VAL = digit; + else + apdigit.pVal[0] = digit; *this += apdigit; } + // If its negative, put it in two's complement form + if (isNeg) { + (*this)--; + this->flip(); + } } -/// to_string - This function translates the APInt into a string. 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!"); @@ -1513,7 +1817,7 @@ std::string APInt::toString(uint8_t radix, bool wantSigned) const { APInt tmp2(tmp.getBitWidth(), 0); divide(tmp, tmp.getNumWords(), divisor, divisor.getNumWords(), &tmp2, &APdigit); - uint32_t digit = APdigit.getValue(); + uint32_t digit = APdigit.getZExtValue(); assert(digit < radix && "divide failed"); result.insert(insert_at,digits[digit]); tmp = tmp2; @@ -1525,12 +1829,13 @@ std::string APInt::toString(uint8_t radix, bool wantSigned) const { #ifndef NDEBUG void APInt::dump() const { - std::cerr << "APInt(" << BitWidth << ")=" << std::setbase(16); + cerr << "APInt(" << BitWidth << ")=" << std::setbase(16); if (isSingleWord()) - std::cerr << VAL; + cerr << VAL; else for (unsigned i = getNumWords(); i > 0; i--) { - std::cerr << pVal[i-1] << " "; + cerr << pVal[i-1] << " "; } - std::cerr << " (" << this->toString(10, false) << ")\n" << std::setbase(10); + cerr << " U(" << this->toString(10) << ") S(" << this->toStringSigned(10) + << ")\n" << std::setbase(10); } #endif