diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h index c475cf3f71c5..8c6034809f25 100644 --- a/llvm/include/llvm/ADT/APInt.h +++ b/llvm/include/llvm/ADT/APInt.h @@ -16,6 +16,7 @@ #define LLVM_APINT_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/MathExtras.h" #include #include #include @@ -67,7 +68,6 @@ namespace llvm { /// /// @brief Class for arbitrary precision integers. class APInt { - uint32_t BitWidth; ///< The number of bits in this APInt. /// This union is used to store the integer value. When the @@ -161,6 +161,42 @@ class APInt { const APInt &RHS, uint32_t rhsWords, APInt *Quotient, APInt *Remainder); + /// out-of-line slow case for inline constructor + void initSlowCase(uint32_t numBits, uint64_t val, bool isSigned); + + /// out-of-line slow case for inline copy constructor + void initSlowCase(const APInt& that); + + /// out-of-line slow case for shl + APInt shlSlowCase(uint32_t shiftAmt) const; + + /// out-of-line slow case for operator& + APInt AndSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator| + APInt OrSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator^ + APInt XorSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator= + APInt& AssignSlowCase(const APInt& RHS); + + /// out-of-line slow case for operator== + bool EqualSlowCase(const APInt& RHS) const; + + /// out-of-line slow case for operator== + bool EqualSlowCase(uint64_t Val) const; + + /// out-of-line slow case for countLeadingZeros + uint32_t countLeadingZerosSlowCase() const; + + /// out-of-line slow case for countTrailingOnes + uint32_t countTrailingOnesSlowCase() const; + + /// out-of-line slow case for countPopulation + uint32_t countPopulationSlowCase() const; + public: /// @name Constructors /// @{ @@ -172,7 +208,15 @@ public: /// @param val the initial value of the APInt /// @param isSigned how to treat signedness of val /// @brief Create a new APInt of numBits width, initialized as val. - APInt(uint32_t numBits, uint64_t val, bool isSigned = false); + APInt(uint32_t numBits, uint64_t val, bool isSigned = false) + : BitWidth(numBits), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = val; + else + initSlowCase(numBits, val, isSigned); + clearUnusedBits(); + } /// Note that numWords can be smaller or larger than the corresponding bit /// width but any extraneous bits will be dropped. @@ -196,11 +240,21 @@ public: /// Simply makes *this a copy of that. /// @brief Copy Constructor. - APInt(const APInt& that); + APInt(const APInt& that) + : BitWidth(that.BitWidth), VAL(0) { + assert(BitWidth && "bitwidth too small"); + if (isSingleWord()) + VAL = that.VAL; + else + initSlowCase(that); + } /// @brief Destructor. - ~APInt(); - + ~APInt() { + if (!isSingleWord()) + delete [] pVal; + } + /// Default constructor that creates an uninitialized APInt. This is useful /// for object deserialization (pair this with the static method Read). explicit APInt() : BitWidth(1) {} @@ -403,6 +457,7 @@ public: /// @param numBits the bitwidth of the result /// @param loBitsSet the number of low-order bits set in the result. /// @brief Get a value with low bits set + // XXX why isn't this inlining? static APInt getLowBitsSet(uint32_t numBits, uint32_t loBitsSet) { assert(loBitsSet <= numBits && "Too many bits to set!"); // Handle a degenerate case, to avoid shifting by word size @@ -460,7 +515,11 @@ public: /// Performs a bitwise complement operation on this APInt. /// @returns an APInt that is the bitwise complement of *this /// @brief Unary bitwise complement operator. - APInt operator~() const; + APInt operator~() const { + APInt Result(*this); + Result.flip(); + return Result; + } /// Negates *this using two's complement logic. /// @returns An APInt value representing the negation of *this. @@ -479,7 +538,16 @@ public: /// @{ /// @returns *this after assignment of RHS. /// @brief Copy assignment operator. - APInt& operator=(const APInt& RHS); + APInt& operator=(const APInt& RHS) { + // If the bitwidths are the same, we can avoid mucking with memory + if (isSingleWord() && RHS.isSingleWord()) { + VAL = RHS.VAL; + BitWidth = RHS.BitWidth; + return clearUnusedBits(); + } + + return AssignSlowCase(RHS); + } /// The RHS value is assigned to *this. If the significant bits in RHS exceed /// the bit width, the excess bits are truncated. If the bit width is larger @@ -535,7 +603,12 @@ public: /// Performs a bitwise AND operation on *this and RHS. /// @returns An APInt value representing the bitwise AND of *this and RHS. /// @brief Bitwise AND operator. - APInt operator&(const APInt& RHS) const; + APInt operator&(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL & RHS.VAL); + return AndSlowCase(RHS); + } APInt And(const APInt& RHS) const { return this->operator&(RHS); } @@ -543,7 +616,12 @@ public: /// Performs a bitwise OR operation on *this and RHS. /// @returns An APInt value representing the bitwise OR of *this and RHS. /// @brief Bitwise OR operator. - APInt operator|(const APInt& RHS) const; + APInt operator|(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(getBitWidth(), VAL | RHS.VAL); + return OrSlowCase(RHS); + } APInt Or(const APInt& RHS) const { return this->operator|(RHS); } @@ -551,7 +629,12 @@ public: /// Performs a bitwise XOR operation on *this and RHS. /// @returns An APInt value representing the bitwise XOR of *this and RHS. /// @brief Bitwise XOR operator. - APInt operator^(const APInt& RHS) const; + APInt operator^(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); + if (isSingleWord()) + return APInt(BitWidth, VAL ^ RHS.VAL); + return XorSlowCase(RHS); + } APInt Xor(const APInt& RHS) const { return this->operator^(RHS); } @@ -592,7 +675,15 @@ public: /// Left-shift this APInt by shiftAmt. /// @brief Left-shift function. - APInt shl(uint32_t shiftAmt) const; + APInt shl(uint32_t shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // avoid undefined shift results + return APInt(BitWidth, VAL << shiftAmt); + } + return shlSlowCase(shiftAmt); + } /// @brief Rotate left by rotateAmt. APInt rotl(uint32_t rotateAmt) const; @@ -696,13 +787,22 @@ public: /// Compares this APInt with RHS for the validity of the equality /// relationship. /// @brief Equality operator. - bool operator==(const APInt& RHS) const; + bool operator==(const APInt& RHS) const { + assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); + if (isSingleWord()) + return VAL == RHS.VAL; + return EqualSlowCase(RHS); + } /// Compares this APInt with a uint64_t for the validity of the equality /// relationship. /// @returns true if *this == Val /// @brief Equality operator. - bool operator==(uint64_t Val) const; + bool operator==(uint64_t Val) const { + if (isSingleWord()) + return VAL == Val; + return EqualSlowCase(Val); + } /// Compares this APInt with RHS for the validity of the equality /// relationship. @@ -837,21 +937,46 @@ public: /// @name Bit Manipulation Operators /// @{ /// @brief Set every bit to 1. - APInt& set(); + APInt& set() { + if (isSingleWord()) { + VAL = -1ULL; + return clearUnusedBits(); + } + + // Set all the bits in all the words. + for (uint32_t i = 0; i < getNumWords(); ++i) + pVal[i] = -1ULL; + // Clear the unused ones + return clearUnusedBits(); + } /// Set the given bit to 1 whose position is given as "bitPosition". /// @brief Set a given bit to 1. APInt& set(uint32_t bitPosition); /// @brief Set every bit to 0. - APInt& clear(); + APInt& clear() { + if (isSingleWord()) + VAL = 0; + else + memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); + return *this; + } /// Set the given bit to 0 whose position is given as "bitPosition". /// @brief Set a given bit to 0. APInt& clear(uint32_t bitPosition); /// @brief Toggle every bit to its opposite value. - APInt& flip(); + APInt& flip() { + if (isSingleWord()) { + VAL ^= -1ULL; + return clearUnusedBits(); + } + 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 /// as "bitPosition". @@ -936,7 +1061,13 @@ public: /// @returns BitWidth if the value is zero. /// @returns the number of zeros from the most significant bit to the first /// one bits. - uint32_t countLeadingZeros() const; + uint32_t countLeadingZeros() const { + if (isSingleWord()) { + uint32_t unusedBits = APINT_BITS_PER_WORD - BitWidth; + return CountLeadingZeros_64(VAL) - unusedBits; + } + return countLeadingZerosSlowCase(); + } /// countLeadingOnes - This function is an APInt version of the /// countLeadingOnes_{32,64} functions in MathExtras.h. It counts the number @@ -962,7 +1093,11 @@ public: /// @returns the number of ones from the least significant bit to the first /// zero bit. /// @brief Count the number of trailing one bits. - uint32_t countTrailingOnes() const; + uint32_t countTrailingOnes() const { + if (isSingleWord()) + return CountTrailingOnes_64(VAL); + return countTrailingOnesSlowCase(); + } /// countPopulation - This function is an APInt version of the /// countPopulation_{32,64} functions in MathExtras.h. It counts the number @@ -970,7 +1105,11 @@ public: /// @returns 0 if the value is zero. /// @returns the number of set bits. /// @brief Count the number of bits set. - uint32_t countPopulation() const; + uint32_t countPopulation() const { + if (isSingleWord()) + return CountPopulation_64(VAL); + return countPopulationSlowCase(); + } /// @} /// @name Conversion Functions @@ -1145,7 +1284,7 @@ public: /// of a number. If the input number has no bits set -1U is /// returned. static unsigned int tcLSB(const integerPart *, unsigned int); - static unsigned int tcMSB(const integerPart *, unsigned int); + static unsigned int tcMSB(const integerPart *parts, unsigned int n); /// Negate a bignum in-place. static void tcNegate(integerPart *, unsigned int); diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 3dcf84057bba..f41531306036 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -24,15 +24,6 @@ #include 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) { @@ -50,26 +41,18 @@ inline static uint64_t* getMemory(uint32_t numWords) { return result; } -APInt::APInt(uint32_t numBits, uint64_t val, bool isSigned) - : BitWidth(numBits), VAL(0) { - assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); - if (isSingleWord()) - VAL = val; - else { - pVal = getClearedMemory(getNumWords()); - pVal[0] = val; - if (isSigned && int64_t(val) < 0) - for (unsigned i = 1; i < getNumWords(); ++i) - pVal[i] = -1ULL; - } - clearUnusedBits(); +void APInt::initSlowCase(uint32_t numBits, uint64_t val, bool isSigned) +{ + pVal = getClearedMemory(getNumWords()); + pVal[0] = val; + if (isSigned && int64_t(val) < 0) + for (unsigned i = 1; i < getNumWords(); ++i) + pVal[i] = -1ULL; } APInt::APInt(uint32_t numBits, uint32_t numWords, const uint64_t bigVal[]) : BitWidth(numBits), VAL(0) { - assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth && "bitwidth too small"); assert(bigVal && "Null pointer detected!"); if (isSingleWord()) VAL = bigVal[0]; @@ -88,51 +71,35 @@ 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 >= MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); + assert(BitWidth && "bitwidth too small"); fromString(numbits, StrStart, slen, radix); } -APInt::APInt(const APInt& that) - : BitWidth(that.BitWidth), VAL(0) { - assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); - assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); - if (isSingleWord()) - VAL = that.VAL; - else { - pVal = getMemory(getNumWords()); - memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE); - } +void APInt::initSlowCase(const APInt& that) +{ + pVal = getMemory(getNumWords()); + memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE); } -APInt::~APInt() { - if (!isSingleWord()) - delete [] pVal; -} - -APInt& APInt::operator=(const APInt& RHS) { +APInt& APInt::AssignSlowCase(const APInt& RHS) { // 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); + // assume same bit-width single-word case is already handled + assert(!isSingleWord()); + 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()) + if (isSingleWord()) { + // assume case where both are single words is already handled + assert(!RHS.isSingleWord()); + 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; @@ -425,11 +392,7 @@ APInt& APInt::operator^=(const APInt& RHS) { return clearUnusedBits(); } -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 APInt::AndSlowCase(const APInt& RHS) const { uint32_t numWords = getNumWords(); uint64_t* val = getMemory(numWords); for (uint32_t i = 0; i < numWords; ++i) @@ -437,11 +400,7 @@ APInt APInt::operator&(const APInt& RHS) const { return APInt(val, getBitWidth()); } -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 APInt::OrSlowCase(const APInt& RHS) const { uint32_t numWords = getNumWords(); uint64_t *val = getMemory(numWords); for (uint32_t i = 0; i < numWords; ++i) @@ -449,11 +408,7 @@ APInt APInt::operator|(const APInt& RHS) const { return APInt(val, getBitWidth()); } -APInt APInt::operator^(const APInt& RHS) const { - assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); - if (isSingleWord()) - return APInt(BitWidth, VAL ^ RHS.VAL); - +APInt APInt::XorSlowCase(const APInt& RHS) const { uint32_t numWords = getNumWords(); uint64_t *val = getMemory(numWords); for (uint32_t i = 0; i < numWords; ++i) @@ -505,11 +460,7 @@ bool APInt::operator[](uint32_t bitPosition) const { (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0; } -bool APInt::operator==(const APInt& RHS) const { - assert(BitWidth == RHS.BitWidth && "Comparison requires equal bit widths"); - if (isSingleWord()) - return VAL == RHS.VAL; - +bool APInt::EqualSlowCase(const APInt& RHS) const { // Get some facts about the number of bits used in the two operands. uint32_t n1 = getActiveBits(); uint32_t n2 = RHS.getActiveBits(); @@ -529,10 +480,7 @@ bool APInt::operator==(const APInt& RHS) const { return true; } -bool APInt::operator==(uint64_t Val) const { - if (isSingleWord()) - return VAL == Val; - +bool APInt::EqualSlowCase(uint64_t Val) const { uint32_t n = getActiveBits(); if (n <= APINT_BITS_PER_WORD) return pVal[0] == Val; @@ -616,19 +564,6 @@ APInt& APInt::set(uint32_t bitPosition) { return *this; } -APInt& APInt::set() { - if (isSingleWord()) { - VAL = -1ULL; - return clearUnusedBits(); - } - - // Set all the bits in all the words. - for (uint32_t i = 0; i < getNumWords(); ++i) - pVal[i] = -1ULL; - // Clear the unused ones - return clearUnusedBits(); -} - /// Set the given bit to 0 whose position is given as "bitPosition". /// @brief Set a given bit to 0. APInt& APInt::clear(uint32_t bitPosition) { @@ -639,33 +574,7 @@ APInt& APInt::clear(uint32_t bitPosition) { return *this; } -/// @brief Set every bit to 0. -APInt& APInt::clear() { - if (isSingleWord()) - VAL = 0; - else - memset(pVal, 0, getNumWords() * APINT_WORD_SIZE); - return *this; -} - -/// @brief Bitwise NOT operator. Performs a bitwise logical NOT operation on -/// this APInt. -APInt APInt::operator~() const { - APInt Result(*this); - Result.flip(); - return Result; -} - /// @brief Toggle every bit to its opposite value. -APInt& APInt::flip() { - if (isSingleWord()) { - VAL ^= -1ULL; - return clearUnusedBits(); - } - 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 /// as "bitPosition". @@ -742,18 +651,14 @@ bool APInt::isPowerOf2() const { return (!!*this) && !(*this & (*this - APInt(BitWidth,1))); } -uint32_t APInt::countLeadingZeros() const { +uint32_t APInt::countLeadingZerosSlowCase() const { uint32_t Count = 0; - if (isSingleWord()) - Count = CountLeadingZeros_64(VAL); - else { - for (uint32_t i = getNumWords(); i > 0u; --i) { - if (pVal[i-1] == 0) - Count += APINT_BITS_PER_WORD; - else { - Count += CountLeadingZeros_64(pVal[i-1]); - break; - } + for (uint32_t i = getNumWords(); i > 0u; --i) { + if (pVal[i-1] == 0) + Count += APINT_BITS_PER_WORD; + else { + Count += CountLeadingZeros_64(pVal[i-1]); + break; } } uint32_t remainder = BitWidth % APINT_BITS_PER_WORD; @@ -806,9 +711,7 @@ uint32_t APInt::countTrailingZeros() const { return std::min(Count, BitWidth); } -uint32_t APInt::countTrailingOnes() const { - if (isSingleWord()) - return std::min(uint32_t(CountTrailingOnes_64(VAL)), BitWidth); +uint32_t APInt::countTrailingOnesSlowCase() const { uint32_t Count = 0; uint32_t i = 0; for (; i < getNumWords() && pVal[i] == -1ULL; ++i) @@ -818,9 +721,7 @@ uint32_t APInt::countTrailingOnes() const { return std::min(Count, BitWidth); } -uint32_t APInt::countPopulation() const { - if (isSingleWord()) - return CountPopulation_64(VAL); +uint32_t APInt::countPopulationSlowCase() const { uint32_t Count = 0; for (uint32_t i = 0; i < getNumWords(); ++i) Count += CountPopulation_64(pVal[i]); @@ -969,7 +870,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 >= MIN_INT_BITS && "Can't truncate to 0 bits"); + assert(width && "Can't truncate to 0 bits"); uint32_t wordsBefore = getNumWords(); BitWidth = width; uint32_t wordsAfter = getNumWords(); @@ -992,7 +893,6 @@ 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 <= MAX_INT_BITS && "Too many bits"); // If the sign bit isn't set, this is the same as zext. if (!isNegative()) { zext(width); @@ -1040,7 +940,6 @@ 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 <= MAX_INT_BITS && "Too many bits"); uint32_t wordsBefore = getNumWords(); BitWidth = width; uint32_t wordsAfter = getNumWords(); @@ -1238,16 +1137,7 @@ APInt APInt::shl(const APInt &shiftAmt) const { return shl((uint32_t)shiftAmt.getLimitedValue(BitWidth)); } -/// Left-shift this APInt by shiftAmt. -/// @brief Left-shift function. -APInt APInt::shl(uint32_t shiftAmt) const { - assert(shiftAmt <= BitWidth && "Invalid shift amount"); - if (isSingleWord()) { - if (shiftAmt == BitWidth) - return APInt(BitWidth, 0); // avoid undefined shift results - return APInt(BitWidth, VAL << shiftAmt); - } - +APInt APInt::shlSlowCase(uint32_t shiftAmt) const { // 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.