Review changes:

1. Function style changes.
2. 80-col violations.
3. Better names for things.
4. Arrange constructors so they all take bit width first.
5. Add named signed and unsigned comparison functions and remove the
   corresponding operators.
6. Remove operator&& and operator|| but provide a getBoolValue function which
   converts to bool as comparison against 0. This allows the normal && and
   || operators to be used as if (X.getBoolValue() && Y.getBoolValue())

Note: this still doesn't function 100% yet. I'm working on the bugs now.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34353 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2007-02-16 22:36:51 +00:00
parent ae6f1fa36b
commit e81d2dad2c
2 changed files with 430 additions and 354 deletions

View File

@ -24,8 +24,8 @@ namespace llvm {
/// Forward declaration.
class APInt;
namespace APIntOps {
APInt UDiv(const APInt& LHS, const APInt& RHS);
APInt URem(const APInt& LHS, const APInt& RHS);
APInt udiv(const APInt& LHS, const APInt& RHS);
APInt urem(const APInt& LHS, const APInt& RHS);
}
//===----------------------------------------------------------------------===//
@ -35,17 +35,31 @@ namespace APIntOps {
/// APInt - This class represents arbitrary precision constant integral values.
/// It is a functional replacement for common case unsigned integer type like
/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width
/// integer type and large integer value types such as 3-bits, 15-bits, or more
/// integer sizes and large integer value types such as 3-bits, 15-bits, or more
/// than 64-bits of precision. APInt provides a variety of arithmetic operators
/// and methods to manipulate integer values of any bit-width. It supports not
/// only all the operations of uint64_t but also bitwise manipulation.
/// and methods to manipulate integer values of any bit-width. It supports both
/// the typical integer arithmetic and comparison operations as well as bitwise
/// manipulation.
///
/// The class has several invariants worth noting:
/// * All bit, byte, and word positions are zero-based.
/// * Once the bit width is set, it doesn't change except by the Truncate,
/// SignExtend, or ZeroExtend operations.
/// * All binary operators must be on APInt instances of the same bit width.
/// Attempting to use these operators on instances with different bit
/// widths will yield an assertion.
/// * The value is stored canonically as an unsigned value. For operations
/// where it makes a difference, there are both signed and unsigned variants
/// of the operation. For example, sdiv and udiv. However, because the bit
/// widths must be the same, operations such as Mul and Add produce the same
/// results regardless of whether the values are interpreted as signed or
/// not.
/// * In general, the class tries to follow the style of computation that LLVM
/// uses in its IR. This simplifies its use for LLVM.
///
/// @brief Class for arbitrary precision integers.
///
/// Note: In this class, all bit/byte/word positions are zero-based.
///
class APInt {
unsigned BitsNum; ///< The number of bits.
unsigned BitWidth; ///< The number of bits in this APInt.
/// This union is used to store the integer value. When the
/// integer bit-width <= 64, it uses VAL;
@ -64,67 +78,79 @@ class APInt {
/// @returns the number of words to hold the integer value of this APInt.
/// @brief Get the number of words.
inline unsigned getNumWords() const {
return (BitsNum + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD;
}
/// @returns true if the number of bits <= 64, false otherwise.
/// @brief Determine if this APInt just has one word to store value.
inline bool isSingleWord() const
{ return BitsNum <= APINT_BITS_PER_WORD; }
inline bool isSingleWord() const {
return BitWidth <= APINT_BITS_PER_WORD;
}
/// @returns the word position for the specified bit position.
static inline unsigned whichWord(unsigned bitPosition)
{ return bitPosition / APINT_BITS_PER_WORD; }
static inline unsigned whichWord(unsigned bitPosition) {
return bitPosition / APINT_BITS_PER_WORD;
}
/// @returns the byte position for the specified bit position.
static inline unsigned whichByte(unsigned bitPosition)
{ return (bitPosition % APINT_BITS_PER_WORD) / 8; }
static inline unsigned whichByte(unsigned bitPosition) {
return (bitPosition % APINT_BITS_PER_WORD) / 8;
}
/// @returns the bit position in a word for the specified bit position
/// in APInt.
static inline unsigned whichBit(unsigned bitPosition)
{ return bitPosition % APINT_BITS_PER_WORD; }
static inline unsigned whichBit(unsigned bitPosition) {
return bitPosition % APINT_BITS_PER_WORD;
}
/// @returns a uint64_t type integer with just bit position at
/// "whichBit(bitPosition)" setting, others zero.
static inline uint64_t maskBit(unsigned bitPosition)
{ return (static_cast<uint64_t>(1)) << whichBit(bitPosition); }
static inline uint64_t maskBit(unsigned bitPosition) {
return (static_cast<uint64_t>(1)) << whichBit(bitPosition);
}
inline void TruncToBits() {
/// This method is used internally to clear the to "N" bits that are not used
/// by the APInt. This is needed after a word is assigned a value to ensure
/// that those bits are zero'd out.
/// @brief Clear high order bits
inline void clearUnusedBits() {
if (isSingleWord())
VAL &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitsNum);
VAL &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth);
else
pVal[getNumWords() - 1] &= ~uint64_t(0ULL) >>
(APINT_BITS_PER_WORD - (whichBit(BitsNum - 1) + 1));
(APINT_BITS_PER_WORD - (whichBit(BitWidth - 1) + 1));
}
/// @returns the corresponding word for the specified bit position.
inline uint64_t& getWord(unsigned bitPosition)
{ return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; }
inline uint64_t& getWord(unsigned bitPosition) {
return isSingleWord() ? VAL : pVal[whichWord(bitPosition)];
}
/// @returns the corresponding word for the specified bit position.
/// This is a constant version.
inline uint64_t getWord(unsigned bitPosition) const
{ return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; }
inline uint64_t getWord(unsigned bitPosition) const {
return isSingleWord() ? VAL : pVal[whichWord(bitPosition)];
}
/// @brief Converts a char array into an integer.
void StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix);
void fromString(unsigned numBits, const char *StrStart, unsigned slen,
uint8_t radix);
public:
/// @brief Create a new APInt of numBits bit-width, and initialized as val.
APInt(uint64_t val = 0, unsigned numBits = APINT_BITS_PER_WORD);
APInt(unsigned numBits, uint64_t val);
/// @brief Create a new APInt of numBits bit-width, and initialized as
/// bigVal[].
APInt(unsigned numBits, uint64_t bigVal[]);
APInt(unsigned numBits, unsigned numWords, uint64_t bigVal[]);
/// @brief Create a new APInt by translating the string represented
/// integer value.
APInt(const std::string& Val, uint8_t radix = 10);
APInt(unsigned numBits, const std::string& Val, uint8_t radix);
/// @brief Create a new APInt by translating the char array represented
/// integer value.
APInt(const char StrStart[], unsigned slen, uint8_t radix);
APInt(unsigned numBits, const char StrStart[], unsigned slen, uint8_t radix);
/// @brief Copy Constructor.
APInt(const APInt& API);
@ -210,14 +236,6 @@ public:
/// @brief Bitwise XOR operator.
APInt operator^(const APInt& RHS) const;
/// Performs logical AND operation on this APInt and the given APInt& RHS.
/// @brief Logical AND operator.
bool operator&&(const APInt& RHS) const;
/// Performs logical OR operation on this APInt and the given APInt& RHS.
/// @brief Logical OR operator.
bool operator||(const APInt& RHS) const;
/// Performs logical negation operation on this APInt.
/// @brief Logical negation operator.
bool operator !() const;
@ -234,9 +252,9 @@ public:
/// @brief Subtraction operator.
APInt operator-(const APInt& RHS) const;
///
/// @brief Unary negation operator
inline APInt operator-() const {
return APInt(0, BitsNum) - (*this);
return APInt(0, BitWidth) - (*this);
}
/// @brief Array-indexing support.
@ -266,32 +284,147 @@ public:
return !((*this) == Val);
}
/// Compare this APInt with the given APInt& RHS for
/// the validity of the less-than relationship.
/// @brief Less-than operator.
bool operator <(const APInt& RHS) const;
/// @brief Equality comparison
bool eq(const APInt &RHS) const {
return (*this) == RHS;
}
/// Compare this APInt with the given APInt& RHS for the validity
/// of the less-than-or-equal relationship.
/// @brief Less-than-or-equal operator.
bool operator<=(const APInt& RHS) const;
/// @brief Inequality comparison
bool ne(const APInt &RHS) const {
return !((*this) == RHS);
}
/// Compare this APInt with the given APInt& RHS for the validity
/// of the greater-than relationship.
/// @brief Greater-than operator.
bool operator> (const APInt& RHS) const;
/// @brief Unsigned less than comparison
bool ult(const APInt& RHS) const;
/// @brief Greater-than-or-equal operator.
/// Compare this APInt with the given APInt& RHS for the validity
/// of the greater-than-or-equal relationship.
bool operator>=(const APInt& RHS) const;
/// @brief Signed less than comparison
bool slt(const APInt& RHS) const;
/// @brief Unsigned less or equal comparison
bool ule(const APInt& RHS) const {
return ult(RHS) || eq(RHS);
}
/// @brief Signed less or equal comparison
bool sle(const APInt& RHS) const {
return slt(RHS) || eq(RHS);
}
/// @brief Unsigned greather than comparison
bool ugt(const APInt& RHS) const {
return !ult(RHS) && !eq(RHS);
}
/// @brief Signed greather than comparison
bool sgt(const APInt& RHS) const {
return !slt(RHS) && !eq(RHS);
}
/// @brief Unsigned greater or equal comparison
bool uge(const APInt& RHS) const {
return !ult(RHS);
}
/// @brief Signed greather or equal comparison
bool sge(const APInt& RHS) const {
return !slt(RHS);
}
/// Arithmetic right-shift this APInt by shiftAmt.
/// @brief Arithmetic right-shift function.
APInt ashr(unsigned shiftAmt) const;
/// Logical right-shift this APInt by shiftAmt.
/// @brief Logical right-shift function.
APInt lshr(unsigned shiftAmt) const;
/// Left-shift this APInt by shiftAmt.
/// @brief Left-shift function.
APInt shl(unsigned shiftAmt) const;
/// Signed divide this APInt by APInt RHS.
/// @brief Signed division function for APInt.
inline APInt sdiv(const APInt& RHS) const {
bool isNegativeLHS = (*this)[BitWidth - 1];
bool isNegativeRHS = RHS[RHS.BitWidth - 1];
APInt API = APIntOps::udiv(
isNegativeLHS ? -(*this) : (*this), isNegativeRHS ? -RHS : RHS);
return isNegativeLHS != isNegativeRHS ? -API : API;;
}
/// Unsigned divide this APInt by APInt RHS.
/// @brief Unsigned division function for APInt.
APInt udiv(const APInt& RHS) const;
/// Signed remainder operation on APInt.
/// @brief Function for signed remainder operation.
inline APInt srem(const APInt& RHS) const {
bool isNegativeLHS = (*this)[BitWidth - 1];
bool isNegativeRHS = RHS[RHS.BitWidth - 1];
APInt API = APIntOps::urem(
isNegativeLHS ? -(*this) : (*this), isNegativeRHS ? -RHS : RHS);
return isNegativeLHS ? -API : API;
}
/// Unsigned remainder operation on APInt.
/// @brief Function for unsigned remainder operation.
APInt urem(const APInt& RHS) const;
/// Truncate the APInt to a specified width. It is an error to specify a width
/// that is greater than or equal to the current width.
/// @brief Truncate to new width.
void trunc(unsigned width);
/// This operation sign extends the APInt to a new width. If the high order
/// bit is set, the fill on the left will be done with 1 bits, otherwise zero.
/// It is an error to specify a width that is less than or equal to the
/// current width.
/// @brief Sign extend to a new width.
void sext(unsigned width);
/// This operation zero extends the APInt to a new width. Thie high order bits
/// are filled with 0 bits. It is an error to specify a width that is less
/// than or equal to the current width.
/// @brief Zero extend to a new width.
void zext(unsigned width);
/// @brief Set every bit to 1.
APInt& set();
/// Set the given bit to 1 whose position is given as "bitPosition".
/// @brief Set a given bit to 1.
APInt& set(unsigned bitPosition);
/// @brief Set every bit to 0.
APInt& clear();
/// Set the given bit to 0 whose position is given as "bitPosition".
/// @brief Set a given bit to 0.
APInt& clear(unsigned bitPosition);
/// @brief Toggle every bit to its opposite value.
APInt& flip();
/// Toggle a given bit to its opposite value whose position is given
/// as "bitPosition".
/// @brief Toggles a given bit to its opposite value.
APInt& flip(unsigned bitPosition);
/// This function returns the number of active bits which is defined as the
/// bit width minus the number of leading zeros. This is used in several
/// computations to see how "wide" the value is.
/// @brief Compute the number of active bits in the value
inline unsigned getActiveBits() const {
return getNumWords() * APINT_BITS_PER_WORD - countLeadingZeros();
}
/// @returns a uint64_t value from this APInt. If this APInt contains a single
/// word, just returns VAL, otherwise pVal[0].
inline uint64_t getValue(bool isSigned = false) const {
if (isSingleWord())
return isSigned ? int64_t(VAL << (64 - BitsNum)) >> (64 - BitsNum) : VAL;
unsigned n = getNumWords() * 64 - CountLeadingZeros();
return isSigned ? int64_t(VAL << (64 - BitWidth)) >>
(64 - BitWidth) : VAL;
unsigned n = getActiveBits();
if (n <= 64)
return pVal[0];
assert(0 && "This APInt's bitwidth > 64");
@ -316,119 +449,65 @@ public:
/// @brief Get the '0' value.
static APInt getNullValue(unsigned numBits);
/// @brief Set every bit to 1.
APInt& set();
/// Set the given bit to 1 whose position is given as "bitPosition".
/// @brief Set a given bit to 1.
APInt& set(unsigned bitPosition);
/// @brief Set every bit to 0.
APInt& clear();
/// Set the given bit to 0 whose position is given as "bitPosition".
/// @brief Set a given bit to 0.
APInt& clear(unsigned bitPosition);
/// @brief Toggle every bit to its opposite value.
APInt& flip();
/// Toggle a given bit to its opposite value whose position is given
/// as "bitPosition".
/// @brief Toggles a given bit to its opposite value.
APInt& flip(unsigned bitPosition);
/// This converts the APInt to a boolean valy as a test against zero.
/// @brief Boolean conversion function.
inline bool getBoolValue() const {
return countLeadingZeros() != BitWidth;
}
/// @returns a character interpretation of the APInt.
std::string to_string(uint8_t radix = 10) const;
std::string toString(uint8_t radix = 10) const;
/// Get an APInt with the same BitsNum as this APInt, just zero mask
/// Get an APInt with the same BitWidth as this APInt, just zero mask
/// the low bits and right shift to the least significant bit.
/// @returns the high "numBits" bits of this APInt.
APInt HiBits(unsigned numBits) const;
APInt getHiBits(unsigned numBits) const;
/// Get an APInt with the same BitsNum as this APInt, just zero mask
/// Get an APInt with the same BitWidth as this APInt, just zero mask
/// the high bits.
/// @returns the low "numBits" bits of this APInt.
APInt LoBits(unsigned numBits) const;
APInt getLoBits(unsigned numBits) const;
/// @returns true if the argument APInt value is a power of two > 0.
inline const bool isPowerOf2() const {
return (!!*this) && !(*this & (*this - 1));
}
inline bool isPowerOf2() const;
/// @returns the number of zeros from the most significant bit to the first
/// one bits.
unsigned CountLeadingZeros() const;
unsigned countLeadingZeros() const;
/// @returns the number of zeros from the least significant bit to the first
/// one bit.
unsigned CountTrailingZeros() const;
unsigned countTrailingZeros() const;
/// @returns the number of set bits.
unsigned CountPopulation() const;
unsigned countPopulation() const;
/// @returns the total number of bits.
inline unsigned getNumBits() const
{ return BitsNum; }
inline unsigned getNumBits() const {
return BitWidth;
}
/// @brief Check if this APInt has a N-bits integer value.
inline bool IsIntN(unsigned N) const {
inline bool isIntN(unsigned N) const {
assert(N && "N == 0 ???");
if (isSingleWord()) {
return VAL == (VAL & (~0ULL >> (64 - N)));
} else {
APInt Tmp(N, pVal);
APInt Tmp(N, getNumWords(), pVal);
return Tmp == (*this);
}
}
/// @returns a byte-swapped representation of this APInt Value.
APInt ByteSwap() const;
APInt byteSwap() const;
/// @returns the floor log base 2 of this APInt.
inline unsigned LogBase2() const {
return getNumWords() * APINT_BITS_PER_WORD - 1 -
CountLeadingZeros();
inline unsigned logBase2() const {
return getNumWords() * APINT_BITS_PER_WORD - 1 - countLeadingZeros();
}
/// @brief Converts this APInt to a double value.
double RoundToDouble(bool isSigned = false) const;
/// Arithmetic right-shift this APInt by shiftAmt.
/// @brief Arithmetic right-shift function.
APInt AShr(unsigned shiftAmt) const;
/// Logical right-shift this APInt by shiftAmt.
/// @brief Logical right-shift function.
APInt LShr(unsigned shiftAmt) const;
/// Left-shift this APInt by shiftAmt.
/// @brief Left-shift function.
APInt Shl(unsigned shiftAmt) const;
/// Signed divide this APInt by APInt RHS.
/// @brief Signed division function for APInt.
inline APInt SDiv(const APInt& RHS) const {
bool isSignedLHS = (*this)[BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1];
APInt API = APIntOps::UDiv(isSignedLHS ? -(*this) : (*this), isSignedRHS ? -RHS : RHS);
return isSignedLHS != isSignedRHS ? -API : API;;
}
/// Unsigned divide this APInt by APInt RHS.
/// @brief Unsigned division function for APInt.
APInt UDiv(const APInt& RHS) const;
/// Signed remainder operation on APInt.
/// @brief Function for signed remainder operation.
inline APInt SRem(const APInt& RHS) const {
bool isSignedLHS = (*this)[BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1];
APInt API = APIntOps::URem(isSignedLHS ? -(*this) : (*this), isSignedRHS ? -RHS : RHS);
return isSignedLHS ? -API : API;
}
/// Unsigned remainder operation on APInt.
/// @brief Function for unsigned remainder operation.
APInt URem(const APInt& RHS) const;
double roundToDouble(bool isSigned = false) const;
};
@ -436,29 +515,29 @@ namespace APIntOps {
/// @brief Check if the specified APInt has a N-bits integer value.
inline bool isIntN(unsigned N, const APInt& APIVal) {
return APIVal.IsIntN(N);
return APIVal.isIntN(N);
}
/// @returns true if the argument APInt value is a sequence of ones
/// starting at the least significant bit with the remainder zero.
inline const bool isMask(unsigned numBits, const APInt& APIVal) {
return APIVal && ((APIVal + 1) & APIVal) == 0;
return APIVal.getBoolValue() && ((APIVal + APInt(numBits,1)) & APIVal) == 0;
}
/// @returns true if the argument APInt value contains a sequence of ones
/// with the remainder zero.
inline const bool isShiftedMask(unsigned numBits, const APInt& APIVal) {
return isMask(numBits, (APIVal - 1) | APIVal);
return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal);
}
/// @returns a byte-swapped representation of the specified APInt Value.
inline APInt ByteSwap(const APInt& APIVal) {
return APIVal.ByteSwap();
inline APInt byteSwap(const APInt& APIVal) {
return APIVal.byteSwap();
}
/// @returns the floor log base 2 of the specified APInt value.
inline unsigned LogBase2(const APInt& APIVal) {
return APIVal.LogBase2();
inline unsigned logBase2(const APInt& APIVal) {
return APIVal.logBase2();
}
/// @returns the greatest common divisor of the two values
@ -466,80 +545,80 @@ inline unsigned LogBase2(const APInt& APIVal) {
APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2);
/// @brief Converts the given APInt to a double value.
inline double APIntRoundToDouble(const APInt& APIVal, bool isSigned = false) {
return APIVal.RoundToDouble(isSigned);
inline double RoundAPIntToDouble(const APInt& APIVal, bool isSigned = false) {
return APIVal.roundToDouble(isSigned);
}
/// @brief Converts the given APInt to a float vlalue.
inline float APIntRoundToFloat(const APInt& APIVal) {
return float(APIntRoundToDouble(APIVal));
inline float RoundAPIntToFloat(const APInt& APIVal) {
return float(RoundAPIntToDouble(APIVal));
}
/// @brief Converts the given double value into a APInt.
APInt DoubleRoundToAPInt(double Double);
APInt RoundDoubleToAPInt(double Double);
/// @brief Converts the given float value into a APInt.
inline APInt FloatRoundToAPInt(float Float) {
return DoubleRoundToAPInt(double(Float));
inline APInt RoundFloatToAPInt(float Float) {
return RoundDoubleToAPInt(double(Float));
}
/// Arithmetic right-shift the APInt by shiftAmt.
/// @brief Arithmetic right-shift function.
inline APInt AShr(const APInt& LHS, unsigned shiftAmt) {
return LHS.AShr(shiftAmt);
inline APInt ashr(const APInt& LHS, unsigned shiftAmt) {
return LHS.ashr(shiftAmt);
}
/// Logical right-shift the APInt by shiftAmt.
/// @brief Logical right-shift function.
inline APInt LShr(const APInt& LHS, unsigned shiftAmt) {
return LHS.LShr(shiftAmt);
inline APInt lshr(const APInt& LHS, unsigned shiftAmt) {
return LHS.lshr(shiftAmt);
}
/// Left-shift the APInt by shiftAmt.
/// @brief Left-shift function.
inline APInt Shl(const APInt& LHS, unsigned shiftAmt) {
return LHS.Shl(shiftAmt);
inline APInt shl(const APInt& LHS, unsigned shiftAmt) {
return LHS.shl(shiftAmt);
}
/// Signed divide APInt LHS by APInt RHS.
/// @brief Signed division function for APInt.
inline APInt SDiv(const APInt& LHS, const APInt& RHS) {
return LHS.SDiv(RHS);
inline APInt sdiv(const APInt& LHS, const APInt& RHS) {
return LHS.sdiv(RHS);
}
/// Unsigned divide APInt LHS by APInt RHS.
/// @brief Unsigned division function for APInt.
inline APInt UDiv(const APInt& LHS, const APInt& RHS) {
return LHS.UDiv(RHS);
inline APInt udiv(const APInt& LHS, const APInt& RHS) {
return LHS.udiv(RHS);
}
/// Signed remainder operation on APInt.
/// @brief Function for signed remainder operation.
inline APInt SRem(const APInt& LHS, const APInt& RHS) {
return LHS.SRem(RHS);
inline APInt srem(const APInt& LHS, const APInt& RHS) {
return LHS.srem(RHS);
}
/// Unsigned remainder operation on APInt.
/// @brief Function for unsigned remainder operation.
inline APInt URem(const APInt& LHS, const APInt& RHS) {
return LHS.URem(RHS);
inline APInt urem(const APInt& LHS, const APInt& RHS) {
return LHS.urem(RHS);
}
/// Performs multiplication on APInt values.
/// @brief Function for multiplication operation.
inline APInt Mul(const APInt& LHS, const APInt& RHS) {
inline APInt mul(const APInt& LHS, const APInt& RHS) {
return LHS * RHS;
}
/// Performs addition on APInt values.
/// @brief Function for addition operation.
inline APInt Add(const APInt& LHS, const APInt& RHS) {
inline APInt add(const APInt& LHS, const APInt& RHS) {
return LHS + RHS;
}
/// Performs subtraction on APInt values.
/// @brief Function for subtraction operation.
inline APInt Sub(const APInt& LHS, const APInt& RHS) {
inline APInt sub(const APInt& LHS, const APInt& RHS) {
return LHS - RHS;
}

View File

@ -241,6 +241,7 @@ static void div(unsigned zds[], unsigned nx, unsigned y[], unsigned ny) {
} while (--j >= ny);
}
#if 0
/// lshift - This function shift x[0:len-1] left by shiftAmt bits, and
/// store the len least significant words of the result in
/// dest[d_offset:d_offset+len-1]. It returns the bits shifted out from
@ -259,13 +260,14 @@ static uint64_t lshift(uint64_t dest[], unsigned d_offset,
dest[d_offset+i] = high_word << shiftAmt;
return retVal;
}
#endif
APInt::APInt(uint64_t val, unsigned numBits)
: BitsNum(numBits) {
assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small");
assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large");
APInt::APInt(unsigned numBits, uint64_t val)
: BitWidth(numBits) {
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 - BitsNum));
VAL = val & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth));
else {
// Memory allocation and check if successful.
assert((pVal = new uint64_t[getNumWords()]) &&
@ -275,53 +277,54 @@ APInt::APInt(uint64_t val, unsigned numBits)
}
}
APInt::APInt(unsigned numBits, uint64_t bigVal[])
: BitsNum(numBits) {
assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small");
assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large");
APInt::APInt(unsigned numBits, unsigned numWords, uint64_t bigVal[])
: BitWidth(numBits) {
assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small");
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 - BitsNum));
VAL = bigVal[0] & (~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth));
else {
// Memory allocation and check if successful.
assert((pVal = new uint64_t[getNumWords()]) &&
"APInt memory allocation fails!");
// Calculate the actual length of bigVal[].
unsigned n = sizeof(*bigVal) / sizeof(bigVal[0]);
unsigned maxN = std::max<unsigned>(n, getNumWords());
unsigned minN = std::min<unsigned>(n, getNumWords());
unsigned maxN = std::max<unsigned>(numWords, getNumWords());
unsigned minN = std::min<unsigned>(numWords, getNumWords());
memcpy(pVal, bigVal, (minN - 1) * 8);
pVal[minN-1] = bigVal[minN-1] & (~uint64_t(0ULL) >> (64 - BitsNum % 64));
pVal[minN-1] = bigVal[minN-1] & (~uint64_t(0ULL) >> (64 - BitWidth % 64));
if (maxN == getNumWords())
memset(pVal+n, 0, (getNumWords() - n) * 8);
memset(pVal+numWords, 0, (getNumWords() - numWords) * 8);
}
}
/// @brief Create a new APInt by translating the char array represented
/// integer value.
APInt::APInt(const char StrStart[], unsigned slen, uint8_t radix) {
StrToAPInt(StrStart, slen, radix);
APInt::APInt(unsigned numbits, const char StrStart[], unsigned slen,
uint8_t radix) {
fromString(numbits, StrStart, slen, radix);
}
/// @brief Create a new APInt by translating the string represented
/// integer value.
APInt::APInt(const std::string& Val, uint8_t radix) {
APInt::APInt(unsigned numbits, const std::string& Val, uint8_t radix) {
assert(!Val.empty() && "String empty?");
StrToAPInt(Val.c_str(), Val.size(), radix);
fromString(numbits, Val.c_str(), Val.size(), radix);
}
/// @brief Converts a char array into an integer.
void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
void APInt::fromString(unsigned numbits, const char *StrStart, unsigned slen,
uint8_t radix) {
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
"Radix should be 2, 8, 10, or 16!");
assert(StrStart && "String empty?");
assert(StrStart && "String is null?");
unsigned size = 0;
// If the radix is a power of 2, read the input
// from most significant to least significant.
if ((radix & (radix - 1)) == 0) {
unsigned nextBitPos = 0, bits_per_digit = radix / 8 + 2;
uint64_t resDigit = 0;
BitsNum = slen * bits_per_digit;
BitWidth = slen * bits_per_digit;
if (getNumWords() > 1)
assert((pVal = new uint64_t[getNumWords()]) &&
"APInt memory allocation fails!");
@ -348,10 +351,10 @@ void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
if (slen < chars_per_word ||
(slen == chars_per_word && // In case the value <= 2^64 - 1
strcmp(StrStart, "18446744073709551615") <= 0)) {
BitsNum = 64;
BitWidth = 64;
VAL = strtoull(StrStart, 0, 10);
} else { // In case the value > 2^64 - 1
BitsNum = (slen / chars_per_word + 1) * 64;
BitWidth = (slen / chars_per_word + 1) * 64;
assert((pVal = new uint64_t[getNumWords()]) &&
"APInt memory allocation fails!");
memset(pVal, 0, getNumWords() * 8);
@ -382,7 +385,7 @@ void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) {
}
APInt::APInt(const APInt& APIVal)
: BitsNum(APIVal.BitsNum) {
: BitWidth(APIVal.BitWidth) {
if (isSingleWord()) VAL = APIVal.VAL;
else {
// Memory allocation and check if successful.
@ -399,7 +402,9 @@ APInt::~APInt() {
/// @brief Copy assignment operator. Create a new object from the given
/// APInt one by initialization.
APInt& APInt::operator=(const APInt& RHS) {
if (isSingleWord()) VAL = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
VAL = RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
else {
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
memcpy(pVal, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, minN * 8);
@ -412,21 +417,23 @@ APInt& APInt::operator=(const APInt& RHS) {
/// @brief Assignment operator. Assigns a common case integer value to
/// the APInt.
APInt& APInt::operator=(uint64_t RHS) {
if (isSingleWord()) VAL = RHS;
if (isSingleWord())
VAL = RHS;
else {
pVal[0] = RHS;
memset(pVal, 0, (getNumWords() - 1) * 8);
}
TruncToBits();
clearUnusedBits();
return *this;
}
/// @brief Prefix increment operator. Increments the APInt by one.
APInt& APInt::operator++() {
if (isSingleWord()) ++VAL;
if (isSingleWord())
++VAL;
else
add_1(pVal, pVal, getNumWords(), 1);
TruncToBits();
clearUnusedBits();
return *this;
}
@ -435,7 +442,7 @@ APInt& APInt::operator--() {
if (isSingleWord()) --VAL;
else
sub_1(pVal, getNumWords(), 1);
TruncToBits();
clearUnusedBits();
return *this;
}
@ -455,7 +462,7 @@ APInt& APInt::operator+=(const APInt& RHS) {
}
}
}
TruncToBits();
clearUnusedBits();
return *this;
}
@ -476,7 +483,7 @@ APInt& APInt::operator-=(const APInt& RHS) {
sub(pVal, pVal, RHS.pVal, getNumWords());
}
}
TruncToBits();
clearUnusedBits();
return *this;
}
@ -486,14 +493,14 @@ APInt& APInt::operator*=(const APInt& RHS) {
if (isSingleWord()) VAL *= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
else {
// one-based first non-zero bit position.
unsigned first = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros();
unsigned first = getActiveBits();
unsigned xlen = !first ? 0 : whichWord(first - 1) + 1;
if (!xlen)
return *this;
else if (RHS.isSingleWord())
mul_1(pVal, pVal, xlen, RHS.VAL);
else {
first = RHS.getNumWords() * APINT_BITS_PER_WORD - RHS.CountLeadingZeros();
first = RHS.getActiveBits();
unsigned ylen = !first ? 0 : whichWord(first - 1) + 1;
if (!ylen) {
memset(pVal, 0, getNumWords() * 8);
@ -507,7 +514,7 @@ APInt& APInt::operator*=(const APInt& RHS) {
delete[] dest;
}
}
TruncToBits();
clearUnusedBits();
return *this;
}
@ -549,7 +556,7 @@ APInt& APInt::operator|=(const APInt& RHS) {
pVal[i] |= RHS.pVal[i];
}
}
TruncToBits();
clearUnusedBits();
return *this;
}
@ -573,7 +580,7 @@ APInt& APInt::operator^=(const APInt& RHS) {
pVal[i] ^= 0;
}
}
TruncToBits();
clearUnusedBits();
return *this;
}
@ -589,7 +596,7 @@ APInt APInt::operator&(const APInt& RHS) const {
APInt APInt::operator|(const APInt& RHS) const {
APInt API(RHS);
API |= *this;
API.TruncToBits();
API.clearUnusedBits();
return API;
}
@ -598,41 +605,10 @@ APInt APInt::operator|(const APInt& RHS) const {
APInt APInt::operator^(const APInt& RHS) const {
APInt API(RHS);
API ^= *this;
API.TruncToBits();
API.clearUnusedBits();
return API;
}
/// @brief Logical AND operator. Performs logical AND operation on this APInt
/// and the given APInt& RHS.
bool APInt::operator&&(const APInt& RHS) const {
if (isSingleWord())
return RHS.isSingleWord() ? VAL && RHS.VAL : VAL && RHS.pVal[0];
else if (RHS.isSingleWord())
return RHS.VAL && pVal[0];
else {
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
for (unsigned i = 0; i < minN; ++i)
if (pVal[i] && RHS.pVal[i])
return true;
}
return false;
}
/// @brief Logical OR operator. Performs logical OR operation on this APInt
/// and the given APInt& RHS.
bool APInt::operator||(const APInt& RHS) const {
if (isSingleWord())
return RHS.isSingleWord() ? VAL || RHS.VAL : VAL || RHS.pVal[0];
else if (RHS.isSingleWord())
return RHS.VAL || pVal[0];
else {
unsigned minN = std::min(getNumWords(), RHS.getNumWords());
for (unsigned i = 0; i < minN; ++i)
if (pVal[i] || RHS.pVal[i])
return true;
}
return false;
}
/// @brief Logical negation operator. Performs logical negation operation on
/// this APInt.
@ -651,7 +627,7 @@ bool APInt::operator !() const {
APInt APInt::operator*(const APInt& RHS) const {
APInt API(RHS);
API *= *this;
API.TruncToBits();
API.clearUnusedBits();
return API;
}
@ -659,7 +635,7 @@ APInt APInt::operator*(const APInt& RHS) const {
APInt APInt::operator+(const APInt& RHS) const {
APInt API(*this);
API += RHS;
API.TruncToBits();
API.clearUnusedBits();
return API;
}
@ -679,8 +655,8 @@ bool APInt::operator[](unsigned bitPosition) const {
/// @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 {
unsigned n1 = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros(),
n2 = RHS.getNumWords() * APINT_BITS_PER_WORD - RHS.CountLeadingZeros();
unsigned n1 = getActiveBits();
unsigned n2 = RHS.getActiveBits();
if (n1 != n2) return false;
else if (isSingleWord())
return VAL == (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
@ -699,7 +675,7 @@ bool APInt::operator==(uint64_t Val) const {
if (isSingleWord())
return VAL == Val;
else {
unsigned n = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros();
unsigned n = getActiveBits();
if (n <= 64)
return pVal[0] == Val;
else
@ -707,18 +683,20 @@ bool APInt::operator==(uint64_t Val) const {
}
}
/// @brief Less-than operator. Compare this APInt with the given APInt& RHS
/// for the validity of the less-than relationship.
bool APInt::operator <(const APInt& RHS) const {
unsigned n1 = getNumWords() * 64 - CountLeadingZeros(),
n2 = RHS.getNumWords() * 64 - RHS.CountLeadingZeros();
if (n1 < n2) return true;
else if (n1 > n2) return false;
else if (isSingleWord())
return VAL < (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
/// @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 {
if (n1 <= 64)
return pVal[0] < (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
unsigned n1 = getActiveBits();
unsigned n2 = RHS.getActiveBits();
if (n1 < n2)
return true;
else if (n2 < n1)
return false;
else if (n1 <= 64 && n2 <= 64)
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;
@ -727,24 +705,28 @@ bool APInt::operator <(const APInt& RHS) const {
return false;
}
/// @brief Less-than-or-equal operator. Compare this APInt with the given
/// APInt& RHS for the validity of the less-than-or-equal relationship.
bool APInt::operator<=(const APInt& RHS) const {
return (*this) == RHS || (*this) < RHS;
/// @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())
return VAL < RHS.VAL;
else {
unsigned n1 = getActiveBits();
unsigned n2 = RHS.getActiveBits();
if (n1 < n2)
return true;
else if (n2 < n1)
return false;
else if (n1 <= 64 && n2 <= 64)
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;
}
}
return false;
}
/// @brief Greater-than operator. Compare this APInt with the given APInt& RHS
/// for the validity of the greater-than relationship.
bool APInt::operator >(const APInt& RHS) const {
return !((*this) <= RHS);
}
/// @brief Greater-than-or-equal operator. Compare this APInt with the given
/// APInt& RHS for the validity of the greater-than-or-equal relationship.
bool APInt::operator>=(const APInt& RHS) const {
return !((*this) < RHS);
}
/// Set the given bit to 1 whose poition is given as "bitPosition".
/// @brief Set a given bit to 1.
APInt& APInt::set(unsigned bitPosition) {
@ -755,11 +737,11 @@ APInt& APInt::set(unsigned bitPosition) {
/// @brief Set every bit to 1.
APInt& APInt::set() {
if (isSingleWord()) VAL = ~0ULL >> (64 - BitsNum);
if (isSingleWord()) VAL = ~0ULL >> (64 - BitWidth);
else {
for (unsigned i = 0; i < getNumWords() - 1; ++i)
pVal[i] = -1ULL;
pVal[getNumWords() - 1] = ~0ULL >> (64 - BitsNum % 64);
pVal[getNumWords() - 1] = ~0ULL >> (64 - BitWidth % 64);
}
return *this;
}
@ -790,12 +772,12 @@ APInt APInt::operator~() const {
/// @brief Toggle every bit to its opposite value.
APInt& APInt::flip() {
if (isSingleWord()) VAL = (~(VAL << (64 - BitsNum))) >> (64 - BitsNum);
if (isSingleWord()) VAL = (~(VAL << (64 - BitWidth))) >> (64 - BitWidth);
else {
unsigned i = 0;
for (; i < getNumWords() - 1; ++i)
pVal[i] = ~pVal[i];
unsigned offset = 64 - (BitsNum - 64 * (i - 1));
unsigned offset = 64 - (BitWidth - 64 * (i - 1));
pVal[i] = (~(pVal[i] << offset)) >> offset;
}
return *this;
@ -805,21 +787,21 @@ APInt& APInt::flip() {
/// as "bitPosition".
/// @brief Toggles a given bit to its opposite value.
APInt& APInt::flip(unsigned bitPosition) {
assert(bitPosition < BitsNum && "Out of the bit-width range!");
assert(bitPosition < BitWidth && "Out of the bit-width range!");
if ((*this)[bitPosition]) clear(bitPosition);
else set(bitPosition);
return *this;
}
/// to_string - This function translates the APInt into a string.
std::string APInt::to_string(uint8_t radix) const {
std::string APInt::toString(uint8_t radix) const {
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
"Radix should be 2, 8, 10, or 16!");
static const char *digits[] = {
"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"
};
std::string result;
unsigned bits_used = getNumWords() * 64 - CountLeadingZeros();
unsigned bits_used = getActiveBits();
if (isSingleWord()) {
char buf[65];
const char *format = (radix == 10 ? "%llu" :
@ -845,11 +827,11 @@ std::string APInt::to_string(uint8_t radix) const {
if (tmp == 0)
result = "0";
else while (tmp != 0) {
APInt APdigit = APIntOps::URem(tmp,divisor);
APInt APdigit = APIntOps::urem(tmp,divisor);
unsigned digit = APdigit.getValue();
assert(digit < radix && "URem failed");
assert(digit < radix && "urem failed");
result.insert(0,digits[digit]);
tmp = APIntOps::UDiv(tmp, divisor);
tmp = APIntOps::udiv(tmp, divisor);
}
return result;
@ -887,22 +869,26 @@ APInt APInt::getNullValue(unsigned numBits) {
}
/// HiBits - This function returns the high "numBits" bits of this APInt.
APInt APInt::HiBits(unsigned numBits) const {
return APIntOps::LShr(*this, BitsNum - numBits);
APInt APInt::getHiBits(unsigned numBits) const {
return APIntOps::lshr(*this, BitWidth - numBits);
}
/// LoBits - This function returns the low "numBits" bits of this APInt.
APInt APInt::LoBits(unsigned numBits) const {
return APIntOps::LShr(APIntOps::Shl(*this, BitsNum - numBits),
BitsNum - numBits);
APInt APInt::getLoBits(unsigned numBits) const {
return APIntOps::lshr(APIntOps::shl(*this, BitWidth - numBits),
BitWidth - numBits);
}
/// CountLeadingZeros - This function is a APInt version corresponding to
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
/// 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.
unsigned APInt::CountLeadingZeros() const {
unsigned APInt::countLeadingZeros() const {
if (isSingleWord())
return CountLeadingZeros_64(VAL);
unsigned Count = 0;
@ -915,23 +901,23 @@ unsigned APInt::CountLeadingZeros() const {
return Count;
}
/// CountTrailingZero - This function is a APInt version corresponding to
/// 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
/// 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.
unsigned APInt::CountTrailingZeros() const {
unsigned APInt::countTrailingZeros() const {
if (isSingleWord())
return CountTrailingZeros_64(~VAL & (VAL - 1));
APInt Tmp = ~(*this) & ((*this) - 1);
return getNumWords() * 64 - Tmp.CountLeadingZeros();
APInt Tmp = ~(*this) & ((*this) - APInt(BitWidth,1));
return getNumWords() * APINT_BITS_PER_WORD - Tmp.countLeadingZeros();
}
/// CountPopulation - This function is a APInt version corresponding to
/// 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.
/// countPopulation_{32, 64}. It counts the number of set bits in a value.
/// @returns 0 if the value is zero.
unsigned APInt::CountPopulation() const {
unsigned APInt::countPopulation() const {
if (isSingleWord())
return CountPopulation_64(VAL);
unsigned Count = 0;
@ -941,31 +927,31 @@ unsigned APInt::CountPopulation() const {
}
/// ByteSwap - This function returns a byte-swapped representation of the
/// byteSwap - This function returns a byte-swapped representation of the
/// this APInt.
APInt APInt::ByteSwap() const {
assert(BitsNum >= 16 && BitsNum % 16 == 0 && "Cannot byteswap!");
if (BitsNum == 16)
return APInt(ByteSwap_16(VAL), BitsNum);
else if (BitsNum == 32)
return APInt(ByteSwap_32(VAL), BitsNum);
else if (BitsNum == 48) {
APInt APInt::byteSwap() const {
assert(BitWidth >= 16 && BitWidth % 16 == 0 && "Cannot byteswap!");
if (BitWidth == 16)
return APInt(ByteSwap_16(VAL), BitWidth);
else if (BitWidth == 32)
return APInt(ByteSwap_32(VAL), BitWidth);
else if (BitWidth == 48) {
uint64_t Tmp1 = ((VAL >> 32) << 16) | (VAL & 0xFFFF);
Tmp1 = ByteSwap_32(Tmp1);
uint64_t Tmp2 = (VAL >> 16) & 0xFFFF;
Tmp2 = ByteSwap_16(Tmp2);
return
APInt((Tmp1 & 0xff) | ((Tmp1<<16) & 0xffff00000000ULL) | (Tmp2 << 16),
BitsNum);
} else if (BitsNum == 64)
return APInt(ByteSwap_64(VAL), BitsNum);
BitWidth);
} else if (BitWidth == 64)
return APInt(ByteSwap_64(VAL), BitWidth);
else {
APInt Result(0, BitsNum);
APInt Result(0, BitWidth);
char *pByte = (char*)Result.pVal;
for (unsigned i = 0; i < BitsNum / 8 / 2; ++i) {
for (unsigned i = 0; i < BitWidth / 8 / 2; ++i) {
char Tmp = pByte[i];
pByte[i] = pByte[BitsNum / 8 - 1 - i];
pByte[BitsNum / 8 - i - 1] = Tmp;
pByte[i] = pByte[BitWidth / 8 - 1 - i];
pByte[BitWidth / 8 - i - 1] = Tmp;
}
return Result;
}
@ -978,7 +964,7 @@ APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
APInt A = API1, B = API2;
while (!!B) {
APInt T = B;
B = APIntOps::URem(A, B);
B = APIntOps::urem(A, B);
A = T;
}
return A;
@ -986,7 +972,7 @@ APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
/// DoubleRoundToAPInt - This function convert a double value to
/// a APInt value.
APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
APInt llvm::APIntOps::RoundDoubleToAPInt(double Double) {
union {
double D;
uint64_t I;
@ -995,13 +981,13 @@ APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
bool isNeg = T.I >> 63;
int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
if (exp < 0)
return APInt(0);
return APInt(64ull, 0u);
uint64_t mantissa = ((T.I << 12) >> 12) | (1ULL << 52);
if (exp < 52)
return isNeg ? -APInt(mantissa >> (52 - exp)) :
APInt(mantissa >> (52 - exp));
APInt Tmp(mantissa, exp + 1);
Tmp = Tmp.Shl(exp - 52);
return isNeg ? -APInt(64u, mantissa >> (52 - exp)) :
APInt(64u, mantissa >> (52 - exp));
APInt Tmp(exp + 1, mantissa);
Tmp = Tmp.shl(exp - 52);
return isNeg ? -Tmp : Tmp;
}
@ -1012,12 +998,12 @@ APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
/// |-------------------------------------- |
/// | 1[63] 11[62-52] 52[51-00] 1023 |
/// --------------------------------------
double APInt::RoundToDouble(bool isSigned) const {
bool isNeg = isSigned ? (*this)[BitsNum-1] : false;
double APInt::roundToDouble(bool isSigned) const {
bool isNeg = isSigned ? (*this)[BitWidth-1] : false;
APInt Tmp(isNeg ? -(*this) : (*this));
if (Tmp.isSingleWord())
return isSigned ? double(int64_t(Tmp.VAL)) : double(Tmp.VAL);
unsigned n = Tmp.getNumWords() * 64 - Tmp.CountLeadingZeros();
unsigned n = Tmp.getActiveBits();
if (n <= 64)
return isSigned ? double(int64_t(Tmp.pVal[0])) : double(Tmp.pVal[0]);
// Exponent when normalized to have decimal point directly after
@ -1047,27 +1033,42 @@ double APInt::RoundToDouble(bool isSigned) const {
return T.D;
}
// Truncate to new width.
void APInt::trunc(unsigned width) {
assert(width < BitWidth && "Invalid APInt Truncate request");
}
// Sign extend to a new width.
void APInt::sext(unsigned width) {
assert(width > BitWidth && "Invalid APInt SignExtend request");
}
// Zero extend to a new width.
void APInt::zext(unsigned width) {
assert(width > BitWidth && "Invalid APInt ZeroExtend request");
}
/// Arithmetic right-shift this APInt by shiftAmt.
/// @brief Arithmetic right-shift function.
APInt APInt::AShr(unsigned shiftAmt) const {
APInt APInt::ashr(unsigned shiftAmt) const {
APInt API(*this);
if (API.isSingleWord())
API.VAL = (((int64_t(API.VAL) << (64 - API.BitsNum)) >> (64 - API.BitsNum))
>> shiftAmt) & (~uint64_t(0UL) >> (64 - API.BitsNum));
API.VAL = (((int64_t(API.VAL) << (64 - API.BitWidth)) >> (64 - API.BitWidth))
>> shiftAmt) & (~uint64_t(0UL) >> (64 - API.BitWidth));
else {
if (shiftAmt >= API.BitsNum) {
memset(API.pVal, API[API.BitsNum-1] ? 1 : 0, (API.getNumWords()-1) * 8);
if (shiftAmt >= API.BitWidth) {
memset(API.pVal, API[API.BitWidth-1] ? 1 : 0, (API.getNumWords()-1) * 8);
API.pVal[API.getNumWords() - 1] = ~uint64_t(0UL) >>
(64 - API.BitsNum % 64);
(64 - API.BitWidth % 64);
} else {
unsigned i = 0;
for (; i < API.BitsNum - shiftAmt; ++i)
for (; i < API.BitWidth - shiftAmt; ++i)
if (API[i+shiftAmt])
API.set(i);
else
API.clear(i);
for (; i < API.BitsNum; ++i)
if (API[API.BitsNum-1])
for (; i < API.BitWidth; ++i)
if (API[API.BitWidth-1])
API.set(i);
else API.clear(i);
}
@ -1077,18 +1078,18 @@ APInt APInt::AShr(unsigned shiftAmt) const {
/// Logical right-shift this APInt by shiftAmt.
/// @brief Logical right-shift function.
APInt APInt::LShr(unsigned shiftAmt) const {
APInt APInt::lshr(unsigned shiftAmt) const {
APInt API(*this);
if (API.isSingleWord())
API.VAL >>= shiftAmt;
else {
if (shiftAmt >= API.BitsNum)
if (shiftAmt >= API.BitWidth)
memset(API.pVal, 0, API.getNumWords() * 8);
unsigned i = 0;
for (i = 0; i < API.BitsNum - shiftAmt; ++i)
for (i = 0; i < API.BitWidth - shiftAmt; ++i)
if (API[i+shiftAmt]) API.set(i);
else API.clear(i);
for (; i < API.BitsNum; ++i)
for (; i < API.BitWidth; ++i)
API.clear(i);
}
return API;
@ -1096,11 +1097,11 @@ APInt APInt::LShr(unsigned shiftAmt) const {
/// Left-shift this APInt by shiftAmt.
/// @brief Left-shift function.
APInt APInt::Shl(unsigned shiftAmt) const {
APInt APInt::shl(unsigned shiftAmt) const {
APInt API(*this);
if (API.isSingleWord())
API.VAL <<= shiftAmt;
else if (shiftAmt >= API.BitsNum)
else if (shiftAmt >= API.BitWidth)
memset(API.pVal, 0, API.getNumWords() * 8);
else {
if (unsigned offset = shiftAmt / 64) {
@ -1115,28 +1116,26 @@ APInt APInt::Shl(unsigned shiftAmt) const {
(API.pVal[i-1] >> (64-shiftAmt));
API.pVal[i] <<= shiftAmt;
}
API.TruncToBits();
API.clearUnusedBits();
return API;
}
/// Unsigned divide this APInt by APInt RHS.
/// @brief Unsigned division function for APInt.
APInt APInt::UDiv(const APInt& RHS) const {
APInt APInt::udiv(const APInt& RHS) const {
APInt API(*this);
unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD -
RHS.CountLeadingZeros();
unsigned first = RHS.getActiveBits();
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
assert(ylen && "Divided by zero???");
if (API.isSingleWord()) {
API.VAL = RHS.isSingleWord() ? (API.VAL / RHS.VAL) :
(ylen > 1 ? 0 : API.VAL / RHS.pVal[0]);
} else {
unsigned first2 = API.getNumWords() * APInt::APINT_BITS_PER_WORD -
API.CountLeadingZeros();
unsigned first2 = API.getActiveBits();
unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1;
if (!xlen)
return API;
else if (xlen < ylen || API < RHS)
else if (xlen < ylen || API.ult(RHS))
memset(API.pVal, 0, API.getNumWords() * 8);
else if (API == RHS) {
memset(API.pVal, 0, API.getNumWords() * 8);
@ -1146,8 +1145,8 @@ APInt APInt::UDiv(const APInt& RHS) const {
else {
APInt X(0, (xlen+1)*64), Y(0, ylen*64);
if (unsigned nshift = 63 - (first - 1) % 64) {
Y = APIntOps::Shl(RHS, nshift);
X = APIntOps::Shl(API, nshift);
Y = APIntOps::shl(RHS, nshift);
X = APIntOps::shl(API, nshift);
++xlen;
}
div((unsigned*)X.pVal, xlen*2-1,
@ -1161,20 +1160,18 @@ APInt APInt::UDiv(const APInt& RHS) const {
/// Unsigned remainder operation on APInt.
/// @brief Function for unsigned remainder operation.
APInt APInt::URem(const APInt& RHS) const {
APInt APInt::urem(const APInt& RHS) const {
APInt API(*this);
unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD -
RHS.CountLeadingZeros();
unsigned first = RHS.getActiveBits();
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
assert(ylen && "Performing remainder operation by zero ???");
if (API.isSingleWord()) {
API.VAL = RHS.isSingleWord() ? (API.VAL % RHS.VAL) :
(ylen > 1 ? API.VAL : API.VAL % RHS.pVal[0]);
} else {
unsigned first2 = API.getNumWords() * APInt::APINT_BITS_PER_WORD -
API.CountLeadingZeros();
unsigned first2 = API.getActiveBits();
unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1;
if (!xlen || xlen < ylen || API < RHS)
if (!xlen || xlen < ylen || API.ult(RHS))
return API;
else if (API == RHS)
memset(API.pVal, 0, API.getNumWords() * 8);
@ -1184,8 +1181,8 @@ APInt APInt::URem(const APInt& RHS) const {
APInt X(0, (xlen+1)*64), Y(0, ylen*64);
unsigned nshift = 63 - (first - 1) % 64;
if (nshift) {
APIntOps::Shl(Y, nshift);
APIntOps::Shl(X, nshift);
APIntOps::shl(Y, nshift);
APIntOps::shl(X, nshift);
}
div((unsigned*)X.pVal, xlen*2-1,
(unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);