From ea7650c4edc5df20bceb67568e1a3a65e88cc818 Mon Sep 17 00:00:00 2001 From: Renato Golin Date: Sun, 23 Apr 2017 12:02:07 +0000 Subject: [PATCH] Revert "[APInt] Add ashrInPlace method and implement ashr using it. Also fix a bug in the shift by BitWidth handling." This reverts commit r301094, as it broke all ARM self-hosting bots. PR32754. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301110 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APInt.h | 33 +------------ include/llvm/ADT/APSInt.h | 2 +- lib/Support/APInt.cpp | 99 +++++++++++++++++++++++++++---------- unittests/ADT/APIntTest.cpp | 20 +------- 4 files changed, 77 insertions(+), 77 deletions(-) diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 0e6d2c97d13..7a76a5ba009 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -198,9 +198,6 @@ private: /// out-of-line slow case for lshr. void lshrSlowCase(unsigned ShiftAmt); - /// out-of-line slow case for ashr. - void ashrSlowCase(unsigned ShiftAmt); - /// out-of-line slow case for operator= void AssignSlowCase(const APInt &RHS); @@ -908,26 +905,7 @@ public: /// \brief Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. - APInt ashr(unsigned ShiftAmt) const { - APInt R(*this); - R.ashrInPlace(ShiftAmt); - return R; - } - - /// Arithmetic right-shift this APInt by ShiftAmt in place. - void ashrInPlace(unsigned ShiftAmt) { - assert(ShiftAmt <= BitWidth && "Invalid shift amount"); - if (isSingleWord()) { - int64_t SExtVAL = SignExtend64(VAL, BitWidth); - if (ShiftAmt == BitWidth) - VAL = SExtVAL >> (APINT_BITS_PER_WORD - 1); // undefined - else - VAL = SExtVAL >> ShiftAmt; - clearUnusedBits(); - return; - } - ashrSlowCase(ShiftAmt); - } + APInt ashr(unsigned shiftAmt) const; /// \brief Logical right-shift function. /// @@ -969,14 +947,7 @@ public: /// \brief Arithmetic right-shift function. /// /// Arithmetic right-shift this APInt by shiftAmt. - APInt ashr(const APInt &ShiftAmt) const { - APInt R(*this); - R.ashrInPlace(ShiftAmt); - return R; - } - - /// Arithmetic right-shift this APInt by shiftAmt in place. - void ashrInPlace(const APInt &shiftAmt); + APInt ashr(const APInt &shiftAmt) const; /// \brief Logical right-shift function. /// diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index dabbf3314bd..650d276fdb5 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -128,7 +128,7 @@ public: if (IsUnsigned) lshrInPlace(Amt); else - ashrInPlace(Amt); + *this = *this >> Amt; return *this; } diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 5f3358d1dcf..1c697d301a7 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -1029,42 +1029,89 @@ APInt APInt::sextOrSelf(unsigned width) const { /// Arithmetic right-shift this APInt by shiftAmt. /// @brief Arithmetic right-shift function. -void APInt::ashrInPlace(const APInt &shiftAmt) { - ashrInPlace((unsigned)shiftAmt.getLimitedValue(BitWidth)); +APInt APInt::ashr(const APInt &shiftAmt) const { + return ashr((unsigned)shiftAmt.getLimitedValue(BitWidth)); } /// Arithmetic right-shift this APInt by shiftAmt. /// @brief Arithmetic right-shift function. -void APInt::ashrSlowCase(unsigned ShiftAmt) { - // Don't bother performing a no-op shift. - if (!ShiftAmt) - return; - - bool Negative = isNegative(); +APInt APInt::ashr(unsigned shiftAmt) const { + assert(shiftAmt <= BitWidth && "Invalid shift amount"); + // Handle a degenerate case + if (shiftAmt == 0) + return *this; - // WordShift is the inter-part shift; BitShift is is intra-part shift. - unsigned Words = getNumWords(); - unsigned WordShift = std::min(ShiftAmt / APINT_BITS_PER_WORD, Words); - unsigned BitShift = ShiftAmt % APINT_BITS_PER_WORD; + // Handle single word shifts with built-in ashr + if (isSingleWord()) { + if (shiftAmt == BitWidth) + return APInt(BitWidth, 0); // undefined + return APInt(BitWidth, SignExtend64(VAL, BitWidth) >> shiftAmt); + } - unsigned WordsToMove = Words - WordShift; - // Fastpath for moving by whole words. - if (BitShift == 0) { - std::memmove(pVal, pVal + WordShift, WordsToMove * APINT_WORD_SIZE); + // If all the bits were shifted out, the result is, technically, undefined. + // We return -1 if it was negative, 0 otherwise. We check this early to avoid + // issues in the algorithm below. + if (shiftAmt == BitWidth) { + if (isNegative()) + return APInt(BitWidth, WORD_MAX, true); + else + return APInt(BitWidth, 0); + } + + // Create some space for the result. + uint64_t * val = new uint64_t[getNumWords()]; + + // Compute some values needed by the following shift algorithms + unsigned wordShift = shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word + unsigned offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift + unsigned breakWord = getNumWords() - 1 - offset; // last word affected + unsigned bitsInWord = whichBit(BitWidth); // how many bits in last word? + if (bitsInWord == 0) + bitsInWord = APINT_BITS_PER_WORD; + + // If we are shifting whole words, just move whole words + if (wordShift == 0) { + // Move the words containing significant bits + for (unsigned i = 0; i <= breakWord; ++i) + val[i] = pVal[i+offset]; // move whole word + + // Adjust the top significant word for sign bit fill, if negative + if (isNegative()) + if (bitsInWord < APINT_BITS_PER_WORD) + val[breakWord] |= WORD_MAX << bitsInWord; // set high bits } else { - for (unsigned i = 0; i != WordsToMove; ++i) { - pVal[i] = pVal[i + WordShift] >> BitShift; - if (i + 1 != WordsToMove) - pVal[i] |= pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift); - else if (Negative) - pVal[i] |= WORD_MAX << (APINT_BITS_PER_WORD - BitShift); + // Shift the low order words + for (unsigned i = 0; i < breakWord; ++i) { + // This combines the shifted corresponding word with the low bits from + // the next word (shifted into this word's high bits). + val[i] = (pVal[i+offset] >> wordShift) | + (pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift)); + } + + // Shift the break word. In this case there are no bits from the next word + // to include in this word. + val[breakWord] = pVal[breakWord+offset] >> wordShift; + + // Deal with sign extension in the break word, and possibly the word before + // it. + if (isNegative()) { + if (wordShift > bitsInWord) { + if (breakWord > 0) + val[breakWord-1] |= + WORD_MAX << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); + val[breakWord] |= WORD_MAX; + } else + val[breakWord] |= WORD_MAX << (bitsInWord - wordShift); } } - // Fill in the remainder based on the original sign. - std::memset(pVal + WordsToMove, Negative ? -1 : 0, - WordShift * APINT_WORD_SIZE); - clearUnusedBits(); + // Remaining words are 0 or -1, just assign them. + uint64_t fillValue = (isNegative() ? WORD_MAX : 0); + for (unsigned i = breakWord+1; i < getNumWords(); ++i) + val[i] = fillValue; + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } /// Logical right-shift this APInt by shiftAmt. diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 6b889bf2dfd..5d3afe9a159 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -288,7 +288,7 @@ TEST(APIntTest, i1) { EXPECT_EQ(zero, one.shl(1)); EXPECT_EQ(one, one.shl(0)); EXPECT_EQ(zero, one.lshr(1)); - EXPECT_EQ(one, one.ashr(1)); + EXPECT_EQ(zero, one.ashr(1)); // Rotates. EXPECT_EQ(one, one.rotl(0)); @@ -2024,24 +2024,6 @@ TEST(APIntTest, LogicalRightShift) { EXPECT_EQ(0, neg_one.lshr(128)); } -TEST(APIntTest, ArithmeticRightShift) { - // Ensure we handle large shifts of multi-word. - const APInt signmin32(APInt::getSignedMinValue(32)); - EXPECT_TRUE(signmin32.ashr(32).isAllOnesValue()); - - // Ensure we handle large shifts of multi-word. - const APInt umax32(APInt::getSignedMaxValue(32)); - EXPECT_EQ(0, umax32.ashr(32)); - - // Ensure we handle large shifts of multi-word. - const APInt signmin128(APInt::getSignedMinValue(128)); - EXPECT_TRUE(signmin128.ashr(128).isAllOnesValue()); - - // Ensure we handle large shifts of multi-word. - const APInt umax128(APInt::getSignedMaxValue(128)); - EXPECT_EQ(0, umax128.ashr(128)); -} - TEST(APIntTest, LeftShift) { APInt i256(APInt::getLowBitsSet(256, 2)); -- 2.40.0