Move the fast-path (<=i64) cases of various APInt methods inline

and the slow-path cases out of line.  This speeds up instcombine
a bit in real world cases.  Patch contributed by m-s.

llvm-svn: 55063
This commit is contained in:
Chris Lattner 2008-08-20 17:02:31 +00:00
parent 00ddda96c9
commit c9fdd97035
2 changed files with 199 additions and 170 deletions

View File

@ -16,6 +16,7 @@
#define LLVM_APINT_H #define LLVM_APINT_H
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include <cassert> #include <cassert>
#include <iosfwd> #include <iosfwd>
#include <string> #include <string>
@ -67,7 +68,6 @@ namespace llvm {
/// ///
/// @brief Class for arbitrary precision integers. /// @brief Class for arbitrary precision integers.
class APInt { class APInt {
uint32_t BitWidth; ///< The number of bits in this APInt. uint32_t BitWidth; ///< The number of bits in this APInt.
/// This union is used to store the integer value. When the /// This union is used to store the integer value. When the
@ -161,6 +161,42 @@ class APInt {
const APInt &RHS, uint32_t rhsWords, const APInt &RHS, uint32_t rhsWords,
APInt *Quotient, APInt *Remainder); 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: public:
/// @name Constructors /// @name Constructors
/// @{ /// @{
@ -172,7 +208,15 @@ public:
/// @param val the initial value of the APInt /// @param val the initial value of the APInt
/// @param isSigned how to treat signedness of val /// @param isSigned how to treat signedness of val
/// @brief Create a new APInt of numBits width, initialized as 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 /// Note that numWords can be smaller or larger than the corresponding bit
/// width but any extraneous bits will be dropped. /// width but any extraneous bits will be dropped.
@ -196,11 +240,21 @@ public:
/// Simply makes *this a copy of that. /// Simply makes *this a copy of that.
/// @brief Copy Constructor. /// @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. /// @brief Destructor.
~APInt(); ~APInt() {
if (!isSingleWord())
delete [] pVal;
}
/// Default constructor that creates an uninitialized APInt. This is useful /// Default constructor that creates an uninitialized APInt. This is useful
/// for object deserialization (pair this with the static method Read). /// for object deserialization (pair this with the static method Read).
explicit APInt() : BitWidth(1) {} explicit APInt() : BitWidth(1) {}
@ -403,6 +457,7 @@ public:
/// @param numBits the bitwidth of the result /// @param numBits the bitwidth of the result
/// @param loBitsSet the number of low-order bits set in the result. /// @param loBitsSet the number of low-order bits set in the result.
/// @brief Get a value with low bits set /// @brief Get a value with low bits set
// XXX why isn't this inlining?
static APInt getLowBitsSet(uint32_t numBits, uint32_t loBitsSet) { static APInt getLowBitsSet(uint32_t numBits, uint32_t loBitsSet) {
assert(loBitsSet <= numBits && "Too many bits to set!"); assert(loBitsSet <= numBits && "Too many bits to set!");
// Handle a degenerate case, to avoid shifting by word size // Handle a degenerate case, to avoid shifting by word size
@ -460,7 +515,11 @@ public:
/// Performs a bitwise complement operation on this APInt. /// Performs a bitwise complement operation on this APInt.
/// @returns an APInt that is the bitwise complement of *this /// @returns an APInt that is the bitwise complement of *this
/// @brief Unary bitwise complement operator. /// @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. /// Negates *this using two's complement logic.
/// @returns An APInt value representing the negation of *this. /// @returns An APInt value representing the negation of *this.
@ -479,7 +538,16 @@ public:
/// @{ /// @{
/// @returns *this after assignment of RHS. /// @returns *this after assignment of RHS.
/// @brief Copy assignment operator. /// @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 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 /// 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. /// Performs a bitwise AND operation on *this and RHS.
/// @returns An APInt value representing the bitwise AND of *this and RHS. /// @returns An APInt value representing the bitwise AND of *this and RHS.
/// @brief Bitwise AND operator. /// @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 { APInt And(const APInt& RHS) const {
return this->operator&(RHS); return this->operator&(RHS);
} }
@ -543,7 +616,12 @@ public:
/// Performs a bitwise OR operation on *this and RHS. /// Performs a bitwise OR operation on *this and RHS.
/// @returns An APInt value representing the bitwise OR of *this and RHS. /// @returns An APInt value representing the bitwise OR of *this and RHS.
/// @brief Bitwise OR operator. /// @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 { APInt Or(const APInt& RHS) const {
return this->operator|(RHS); return this->operator|(RHS);
} }
@ -551,7 +629,12 @@ public:
/// Performs a bitwise XOR operation on *this and RHS. /// Performs a bitwise XOR operation on *this and RHS.
/// @returns An APInt value representing the bitwise XOR of *this and RHS. /// @returns An APInt value representing the bitwise XOR of *this and RHS.
/// @brief Bitwise XOR operator. /// @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 { APInt Xor(const APInt& RHS) const {
return this->operator^(RHS); return this->operator^(RHS);
} }
@ -592,7 +675,15 @@ public:
/// Left-shift this APInt by shiftAmt. /// Left-shift this APInt by shiftAmt.
/// @brief Left-shift function. /// @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. /// @brief Rotate left by rotateAmt.
APInt rotl(uint32_t rotateAmt) const; APInt rotl(uint32_t rotateAmt) const;
@ -696,13 +787,22 @@ public:
/// Compares this APInt with RHS for the validity of the equality /// Compares this APInt with RHS for the validity of the equality
/// relationship. /// relationship.
/// @brief Equality operator. /// @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 /// Compares this APInt with a uint64_t for the validity of the equality
/// relationship. /// relationship.
/// @returns true if *this == Val /// @returns true if *this == Val
/// @brief Equality operator. /// @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 /// Compares this APInt with RHS for the validity of the equality
/// relationship. /// relationship.
@ -837,21 +937,46 @@ public:
/// @name Bit Manipulation Operators /// @name Bit Manipulation Operators
/// @{ /// @{
/// @brief Set every bit to 1. /// @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". /// Set the given bit to 1 whose position is given as "bitPosition".
/// @brief Set a given bit to 1. /// @brief Set a given bit to 1.
APInt& set(uint32_t bitPosition); APInt& set(uint32_t bitPosition);
/// @brief Set every bit to 0. /// @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". /// Set the given bit to 0 whose position is given as "bitPosition".
/// @brief Set a given bit to 0. /// @brief Set a given bit to 0.
APInt& clear(uint32_t bitPosition); APInt& clear(uint32_t bitPosition);
/// @brief Toggle every bit to its opposite value. /// @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 /// Toggle a given bit to its opposite value whose position is given
/// as "bitPosition". /// as "bitPosition".
@ -936,7 +1061,13 @@ public:
/// @returns BitWidth if the value is zero. /// @returns BitWidth if the value is zero.
/// @returns the number of zeros from the most significant bit to the first /// @returns the number of zeros from the most significant bit to the first
/// one bits. /// 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 - This function is an APInt version of the
/// countLeadingOnes_{32,64} functions in MathExtras.h. It counts the number /// 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 /// @returns the number of ones from the least significant bit to the first
/// zero bit. /// zero bit.
/// @brief Count the number of trailing one bits. /// @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 - This function is an APInt version of the
/// countPopulation_{32,64} functions in MathExtras.h. It counts the number /// countPopulation_{32,64} functions in MathExtras.h. It counts the number
@ -970,7 +1105,11 @@ public:
/// @returns 0 if the value is zero. /// @returns 0 if the value is zero.
/// @returns the number of set bits. /// @returns the number of set bits.
/// @brief Count the number of bits set. /// @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 /// @name Conversion Functions
@ -1145,7 +1284,7 @@ public:
/// of a number. If the input number has no bits set -1U is /// of a number. If the input number has no bits set -1U is
/// returned. /// returned.
static unsigned int tcLSB(const integerPart *, unsigned int); 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. /// Negate a bignum in-place.
static void tcNegate(integerPart *, unsigned int); static void tcNegate(integerPart *, unsigned int);

View File

@ -24,15 +24,6 @@
#include <cstdlib> #include <cstdlib>
using namespace llvm; 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, /// A utility function for allocating memory, checking for allocation failures,
/// and ensuring the contents are zeroed. /// and ensuring the contents are zeroed.
inline static uint64_t* getClearedMemory(uint32_t numWords) { inline static uint64_t* getClearedMemory(uint32_t numWords) {
@ -50,26 +41,18 @@ inline static uint64_t* getMemory(uint32_t numWords) {
return result; return result;
} }
APInt::APInt(uint32_t numBits, uint64_t val, bool isSigned) void APInt::initSlowCase(uint32_t numBits, uint64_t val, bool isSigned)
: BitWidth(numBits), VAL(0) { {
assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); pVal = getClearedMemory(getNumWords());
assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); pVal[0] = val;
if (isSingleWord()) if (isSigned && int64_t(val) < 0)
VAL = val; for (unsigned i = 1; i < getNumWords(); ++i)
else { pVal[i] = -1ULL;
pVal = getClearedMemory(getNumWords());
pVal[0] = val;
if (isSigned && int64_t(val) < 0)
for (unsigned i = 1; i < getNumWords(); ++i)
pVal[i] = -1ULL;
}
clearUnusedBits();
} }
APInt::APInt(uint32_t numBits, uint32_t numWords, const uint64_t bigVal[]) APInt::APInt(uint32_t numBits, uint32_t numWords, const uint64_t bigVal[])
: BitWidth(numBits), VAL(0) { : BitWidth(numBits), VAL(0) {
assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); assert(BitWidth && "bitwidth too small");
assert(BitWidth <= MAX_INT_BITS && "bitwidth too large");
assert(bigVal && "Null pointer detected!"); assert(bigVal && "Null pointer detected!");
if (isSingleWord()) if (isSingleWord())
VAL = bigVal[0]; 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, APInt::APInt(uint32_t numbits, const char StrStart[], uint32_t slen,
uint8_t radix) uint8_t radix)
: BitWidth(numbits), VAL(0) { : BitWidth(numbits), VAL(0) {
assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); assert(BitWidth && "bitwidth too small");
assert(BitWidth <= MAX_INT_BITS && "bitwidth too large");
fromString(numbits, StrStart, slen, radix); fromString(numbits, StrStart, slen, radix);
} }
APInt::APInt(const APInt& that) void APInt::initSlowCase(const APInt& that)
: BitWidth(that.BitWidth), VAL(0) { {
assert(BitWidth >= MIN_INT_BITS && "bitwidth too small"); pVal = getMemory(getNumWords());
assert(BitWidth <= MAX_INT_BITS && "bitwidth too large"); memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE);
if (isSingleWord())
VAL = that.VAL;
else {
pVal = getMemory(getNumWords());
memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE);
}
} }
APInt::~APInt() { APInt& APInt::AssignSlowCase(const APInt& RHS) {
if (!isSingleWord())
delete [] pVal;
}
APInt& APInt::operator=(const APInt& RHS) {
// Don't do anything for X = X // Don't do anything for X = X
if (this == &RHS) if (this == &RHS)
return *this; return *this;
// If the bitwidths are the same, we can avoid mucking with memory
if (BitWidth == RHS.getBitWidth()) { if (BitWidth == RHS.getBitWidth()) {
if (isSingleWord()) // assume same bit-width single-word case is already handled
VAL = RHS.VAL; assert(!isSingleWord());
else memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE);
memcpy(pVal, RHS.pVal, getNumWords() * APINT_WORD_SIZE);
return *this; return *this;
} }
if (isSingleWord()) if (isSingleWord()) {
if (RHS.isSingleWord()) // assume case where both are single words is already handled
VAL = RHS.VAL; assert(!RHS.isSingleWord());
else { VAL = 0;
VAL = 0; pVal = getMemory(RHS.getNumWords());
pVal = getMemory(RHS.getNumWords()); memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); } else if (getNumWords() == RHS.getNumWords())
}
else if (getNumWords() == RHS.getNumWords())
memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE); memcpy(pVal, RHS.pVal, RHS.getNumWords() * APINT_WORD_SIZE);
else if (RHS.isSingleWord()) { else if (RHS.isSingleWord()) {
delete [] pVal; delete [] pVal;
@ -425,11 +392,7 @@ APInt& APInt::operator^=(const APInt& RHS) {
return clearUnusedBits(); return clearUnusedBits();
} }
APInt APInt::operator&(const APInt& RHS) const { APInt APInt::AndSlowCase(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return APInt(getBitWidth(), VAL & RHS.VAL);
uint32_t numWords = getNumWords(); uint32_t numWords = getNumWords();
uint64_t* val = getMemory(numWords); uint64_t* val = getMemory(numWords);
for (uint32_t i = 0; i < numWords; ++i) for (uint32_t i = 0; i < numWords; ++i)
@ -437,11 +400,7 @@ APInt APInt::operator&(const APInt& RHS) const {
return APInt(val, getBitWidth()); return APInt(val, getBitWidth());
} }
APInt APInt::operator|(const APInt& RHS) const { APInt APInt::OrSlowCase(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return APInt(getBitWidth(), VAL | RHS.VAL);
uint32_t numWords = getNumWords(); uint32_t numWords = getNumWords();
uint64_t *val = getMemory(numWords); uint64_t *val = getMemory(numWords);
for (uint32_t i = 0; i < numWords; ++i) for (uint32_t i = 0; i < numWords; ++i)
@ -449,11 +408,7 @@ APInt APInt::operator|(const APInt& RHS) const {
return APInt(val, getBitWidth()); return APInt(val, getBitWidth());
} }
APInt APInt::operator^(const APInt& RHS) const { APInt APInt::XorSlowCase(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord())
return APInt(BitWidth, VAL ^ RHS.VAL);
uint32_t numWords = getNumWords(); uint32_t numWords = getNumWords();
uint64_t *val = getMemory(numWords); uint64_t *val = getMemory(numWords);
for (uint32_t i = 0; i < numWords; ++i) 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; (isSingleWord() ? VAL : pVal[whichWord(bitPosition)])) != 0;
} }
bool APInt::operator==(const APInt& RHS) const { bool APInt::EqualSlowCase(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. // Get some facts about the number of bits used in the two operands.
uint32_t n1 = getActiveBits(); uint32_t n1 = getActiveBits();
uint32_t n2 = RHS.getActiveBits(); uint32_t n2 = RHS.getActiveBits();
@ -529,10 +480,7 @@ bool APInt::operator==(const APInt& RHS) const {
return true; return true;
} }
bool APInt::operator==(uint64_t Val) const { bool APInt::EqualSlowCase(uint64_t Val) const {
if (isSingleWord())
return VAL == Val;
uint32_t n = getActiveBits(); uint32_t n = getActiveBits();
if (n <= APINT_BITS_PER_WORD) if (n <= APINT_BITS_PER_WORD)
return pVal[0] == Val; return pVal[0] == Val;
@ -616,19 +564,6 @@ APInt& APInt::set(uint32_t bitPosition) {
return *this; 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". /// Set the given bit to 0 whose position is given as "bitPosition".
/// @brief Set a given bit to 0. /// @brief Set a given bit to 0.
APInt& APInt::clear(uint32_t bitPosition) { APInt& APInt::clear(uint32_t bitPosition) {
@ -639,33 +574,7 @@ APInt& APInt::clear(uint32_t bitPosition) {
return *this; 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. /// @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 /// Toggle a given bit to its opposite value whose position is given
/// as "bitPosition". /// as "bitPosition".
@ -742,18 +651,14 @@ bool APInt::isPowerOf2() const {
return (!!*this) && !(*this & (*this - APInt(BitWidth,1))); return (!!*this) && !(*this & (*this - APInt(BitWidth,1)));
} }
uint32_t APInt::countLeadingZeros() const { uint32_t APInt::countLeadingZerosSlowCase() const {
uint32_t Count = 0; uint32_t Count = 0;
if (isSingleWord()) for (uint32_t i = getNumWords(); i > 0u; --i) {
Count = CountLeadingZeros_64(VAL); if (pVal[i-1] == 0)
else { Count += APINT_BITS_PER_WORD;
for (uint32_t i = getNumWords(); i > 0u; --i) { else {
if (pVal[i-1] == 0) Count += CountLeadingZeros_64(pVal[i-1]);
Count += APINT_BITS_PER_WORD; break;
else {
Count += CountLeadingZeros_64(pVal[i-1]);
break;
}
} }
} }
uint32_t remainder = BitWidth % APINT_BITS_PER_WORD; uint32_t remainder = BitWidth % APINT_BITS_PER_WORD;
@ -806,9 +711,7 @@ uint32_t APInt::countTrailingZeros() const {
return std::min(Count, BitWidth); return std::min(Count, BitWidth);
} }
uint32_t APInt::countTrailingOnes() const { uint32_t APInt::countTrailingOnesSlowCase() const {
if (isSingleWord())
return std::min(uint32_t(CountTrailingOnes_64(VAL)), BitWidth);
uint32_t Count = 0; uint32_t Count = 0;
uint32_t i = 0; uint32_t i = 0;
for (; i < getNumWords() && pVal[i] == -1ULL; ++i) for (; i < getNumWords() && pVal[i] == -1ULL; ++i)
@ -818,9 +721,7 @@ uint32_t APInt::countTrailingOnes() const {
return std::min(Count, BitWidth); return std::min(Count, BitWidth);
} }
uint32_t APInt::countPopulation() const { uint32_t APInt::countPopulationSlowCase() const {
if (isSingleWord())
return CountPopulation_64(VAL);
uint32_t Count = 0; uint32_t Count = 0;
for (uint32_t i = 0; i < getNumWords(); ++i) for (uint32_t i = 0; i < getNumWords(); ++i)
Count += CountPopulation_64(pVal[i]); Count += CountPopulation_64(pVal[i]);
@ -969,7 +870,7 @@ double APInt::roundToDouble(bool isSigned) const {
// Truncate to new width. // Truncate to new width.
APInt &APInt::trunc(uint32_t width) { APInt &APInt::trunc(uint32_t width) {
assert(width < BitWidth && "Invalid APInt Truncate request"); 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(); uint32_t wordsBefore = getNumWords();
BitWidth = width; BitWidth = width;
uint32_t wordsAfter = getNumWords(); uint32_t wordsAfter = getNumWords();
@ -992,7 +893,6 @@ APInt &APInt::trunc(uint32_t width) {
// Sign extend to a new width. // Sign extend to a new width.
APInt &APInt::sext(uint32_t width) { APInt &APInt::sext(uint32_t width) {
assert(width > BitWidth && "Invalid APInt SignExtend request"); 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 the sign bit isn't set, this is the same as zext.
if (!isNegative()) { if (!isNegative()) {
zext(width); zext(width);
@ -1040,7 +940,6 @@ APInt &APInt::sext(uint32_t width) {
// Zero extend to a new width. // Zero extend to a new width.
APInt &APInt::zext(uint32_t width) { APInt &APInt::zext(uint32_t width) {
assert(width > BitWidth && "Invalid APInt ZeroExtend request"); assert(width > BitWidth && "Invalid APInt ZeroExtend request");
assert(width <= MAX_INT_BITS && "Too many bits");
uint32_t wordsBefore = getNumWords(); uint32_t wordsBefore = getNumWords();
BitWidth = width; BitWidth = width;
uint32_t wordsAfter = getNumWords(); uint32_t wordsAfter = getNumWords();
@ -1238,16 +1137,7 @@ APInt APInt::shl(const APInt &shiftAmt) const {
return shl((uint32_t)shiftAmt.getLimitedValue(BitWidth)); return shl((uint32_t)shiftAmt.getLimitedValue(BitWidth));
} }
/// Left-shift this APInt by shiftAmt. APInt APInt::shlSlowCase(uint32_t shiftAmt) const {
/// @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);
}
// If all the bits were shifted out, the result is 0. This avoids issues // 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 // with shifting by the size of the integer type, which produces undefined
// results. We define these "undefined results" to always be 0. // results. We define these "undefined results" to always be 0.