summaryrefslogtreecommitdiff
path: root/include/llvm/ADT/APInt.h
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-08-20 17:02:31 +0000
committerChris Lattner <sabre@nondot.org>2008-08-20 17:02:31 +0000
commit98f8ccfad06c8928d899f506731987f951b2ebe4 (patch)
treefba48082d5e82c236465577a14c1bd6cfbddea2a /include/llvm/ADT/APInt.h
parenta267651b7ec4f96e01b31f541d446758bf8da8a9 (diff)
downloadllvm-98f8ccfad06c8928d899f506731987f951b2ebe4.tar.gz
llvm-98f8ccfad06c8928d899f506731987f951b2ebe4.tar.bz2
llvm-98f8ccfad06c8928d899f506731987f951b2ebe4.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55063 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/ADT/APInt.h')
-rw-r--r--include/llvm/ADT/APInt.h179
1 files changed, 159 insertions, 20 deletions
diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h
index c475cf3f71..8c6034809f 100644
--- a/include/llvm/ADT/APInt.h
+++ b/include/llvm/ADT/APInt.h
@@ -16,6 +16,7 @@
#define LLVM_APINT_H
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <iosfwd>
#include <string>
@@ -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);