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
This commit is contained in:
Renato Golin
2017-04-23 12:02:07 +00:00
parent af17b264e1
commit ea7650c4ed
4 changed files with 76 additions and 76 deletions
+72 -25
View File
@@ -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;
APInt APInt::ashr(unsigned shiftAmt) const {
assert(shiftAmt <= BitWidth && "Invalid shift amount");
// Handle a degenerate case
if (shiftAmt == 0)
return *this;
bool Negative = isNegative();
// 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);
}
// 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;
// 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);
}
unsigned WordsToMove = Words - WordShift;
// Fastpath for moving by whole words.
if (BitShift == 0) {
std::memmove(pVal, pVal + WordShift, WordsToMove * APINT_WORD_SIZE);
// 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.