[APInt] Make operator<<= shift in place. Improve the implementation of tcShiftLeft and use it to implement operator<<=.
llvm-svn: 300526
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 1d04f3b..1094a61 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -1161,60 +1161,9 @@
return shl((unsigned)shiftAmt.getLimitedValue(BitWidth));
}
-APInt APInt::shlSlowCase(unsigned 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.
- if (shiftAmt == BitWidth)
- return APInt(BitWidth, 0);
-
- // If none of the bits are shifted out, the result is *this. This avoids a
- // lshr by the words size in the loop below which can produce incorrect
- // results. It also avoids the expensive computation below for a common case.
- if (shiftAmt == 0)
- return *this;
-
- // Create some space for the result.
- uint64_t * val = new uint64_t[getNumWords()];
-
- // If we are shifting less than a word, do it the easy way
- if (shiftAmt < APINT_BITS_PER_WORD) {
- uint64_t carry = 0;
- for (unsigned i = 0; i < getNumWords(); i++) {
- val[i] = pVal[i] << shiftAmt | carry;
- carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt);
- }
- APInt Result(val, BitWidth);
- Result.clearUnusedBits();
- return Result;
- }
-
- // Compute some values needed by the remaining shift algorithms
- unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD;
- unsigned offset = shiftAmt / APINT_BITS_PER_WORD;
-
- // If we are shifting whole words, just move whole words
- if (wordShift == 0) {
- for (unsigned i = 0; i < offset; i++)
- val[i] = 0;
- for (unsigned i = offset; i < getNumWords(); i++)
- val[i] = pVal[i-offset];
- APInt Result(val, BitWidth);
- Result.clearUnusedBits();
- return Result;
- }
-
- // Copy whole words from this to Result.
- unsigned i = getNumWords() - 1;
- for (; i > offset; --i)
- val[i] = pVal[i-offset] << wordShift |
- pVal[i-offset-1] >> (APINT_BITS_PER_WORD - wordShift);
- val[offset] = pVal[0] << wordShift;
- for (i = 0; i < offset; ++i)
- val[i] = 0;
- APInt Result(val, BitWidth);
- Result.clearUnusedBits();
- return Result;
+void APInt::shlSlowCase(unsigned ShiftAmt) {
+ tcShiftLeft(pVal, getNumWords(), ShiftAmt);
+ clearUnusedBits();
}
// Calculate the rotate amount modulo the bit width.
@@ -2657,34 +2606,31 @@
return false;
}
-/* Shift a bignum left COUNT bits in-place. Shifted in bits are zero.
- There are no restrictions on COUNT. */
-void APInt::tcShiftLeft(WordType *dst, unsigned parts, unsigned count) {
- if (count) {
- /* Jump is the inter-part jump; shift is is intra-part shift. */
- unsigned jump = count / APINT_BITS_PER_WORD;
- unsigned shift = count % APINT_BITS_PER_WORD;
+/// Shift a bignum left Cound bits in-place. Shifted in bits are zero. There are
+/// no restrictions on Count.
+void APInt::tcShiftLeft(WordType *Dst, unsigned Words, unsigned Count) {
+ // Don't bother performing a no-op shift.
+ if (!Count)
+ return;
- while (parts > jump) {
- WordType part;
+ /* WordShift is the inter-part shift; BitShift is is intra-part shift. */
+ unsigned WordShift = std::min(Count / APINT_BITS_PER_WORD, Words);
+ unsigned BitShift = Count % APINT_BITS_PER_WORD;
- parts--;
-
- /* dst[i] comes from the two parts src[i - jump] and, if we have
- an intra-part shift, src[i - jump - 1]. */
- part = dst[parts - jump];
- if (shift) {
- part <<= shift;
- if (parts >= jump + 1)
- part |= dst[parts - jump - 1] >> (APINT_BITS_PER_WORD - shift);
- }
-
- dst[parts] = part;
+ // Fastpath for moving by whole words.
+ if (BitShift == 0) {
+ std::memmove(Dst + WordShift, Dst, (Words - WordShift) * APINT_WORD_SIZE);
+ } else {
+ while (Words-- > WordShift) {
+ Dst[Words] = Dst[Words - WordShift] << BitShift;
+ if (Words > WordShift)
+ Dst[Words] |=
+ Dst[Words - WordShift - 1] >> (APINT_BITS_PER_WORD - BitShift);
}
-
- while (parts > 0)
- dst[--parts] = 0;
}
+
+ // Fill in the remainder with 0s.
+ std::memset(Dst, 0, WordShift * APINT_WORD_SIZE);
}
/// Shift a bignum right Count bits in-place. Shifted in bits are zero. There