Move the fast-path (<=i64) cases of various APInt methods inline
authorChris Lattner <sabre@nondot.org>
Wed, 20 Aug 2008 17:02:31 +0000 (17:02 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 20 Aug 2008 17:02:31 +0000 (17:02 +0000)
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

include/llvm/ADT/APInt.h
lib/Support/APInt.cpp

index c475cf3f71c51f708241b9b948b2245538334252..8c6034809f256a6eba8911b997845a3a926670f4 100644 (file)
@@ -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);
index 3dcf84057bbabba5e88b0b5711dd058a5cf2e868..f415313060361b793a8a2209c602c479f1304f46 100644 (file)
 #include <cstdlib>
 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);
-  }
-}
-
-APInt::~APInt() {
-  if (!isSingleWord()) 
-    delete [] pVal;
+void APInt::initSlowCase(const APInt& that)
+{
+  pVal = getMemory(getNumWords());
+  memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE);
 }
 
-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.