[llvm-commits] CVS: llvm/lib/Support/APInt.cpp
Reid Spencer
reid at x10sys.com
Sun Feb 25 23:44:55 PST 2007
Changes in directory llvm/lib/Support:
APInt.cpp updated: 1.45 -> 1.46
---
Log message:
1. Remove redundant calls to clearUsedBits().
2. Fix countTrailingZeros to use a faster algorithm.
3. Simplify sext() slightly by using isNegative().
4. Implement ashr using word-at-a-time logic instead of bit-at-a-time
5. Rename locals named isNegative so they don't clash with method name.
6. Fix fromString to compute negated value correctly.
---
Diffs of the changes: (+79 -44)
APInt.cpp | 123 +++++++++++++++++++++++++++++++++++++++-----------------------
1 files changed, 79 insertions(+), 44 deletions(-)
Index: llvm/lib/Support/APInt.cpp
diff -u llvm/lib/Support/APInt.cpp:1.45 llvm/lib/Support/APInt.cpp:1.46
--- llvm/lib/Support/APInt.cpp:1.45 Sun Feb 25 19:19:48 2007
+++ llvm/lib/Support/APInt.cpp Mon Feb 26 01:44:38 2007
@@ -403,7 +403,7 @@
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).clearUnusedBits();
+ return APInt(BitWidth, VAL ^ RHS.VAL);
uint32_t numWords = getNumWords();
uint64_t *val = getMemory(numWords);
@@ -427,7 +427,7 @@
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).clearUnusedBits();
+ return APInt(BitWidth, VAL * RHS.VAL);
APInt Result(*this);
Result *= RHS;
return Result.clearUnusedBits();
@@ -436,7 +436,7 @@
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).clearUnusedBits();
+ return APInt(BitWidth, VAL + RHS.VAL);
APInt Result(BitWidth, 0);
add(Result.pVal, this->pVal, RHS.pVal, getNumWords());
return Result.clearUnusedBits();
@@ -445,7 +445,7 @@
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).clearUnusedBits();
+ return APInt(BitWidth, VAL - RHS.VAL);
APInt Result(BitWidth, 0);
sub(Result.pVal, this->pVal, RHS.pVal, getNumWords());
return Result.clearUnusedBits();
@@ -602,19 +602,19 @@
/// @brief Bitwise NOT operator. Performs a bitwise logical NOT operation on
/// this APInt.
APInt APInt::operator~() const {
- APInt API(*this);
- API.flip();
- return API;
+ APInt Result(*this);
+ Result.flip();
+ return Result;
}
/// @brief Toggle every bit to its opposite value.
APInt& APInt::flip() {
if (isSingleWord()) {
- VAL = ~VAL;
+ VAL ^= -1ULL;
return clearUnusedBits();
}
for (uint32_t i = 0; i < getNumWords(); ++i)
- pVal[i] = ~pVal[i];
+ pVal[i] ^= -1ULL;
return clearUnusedBits();
}
@@ -699,8 +699,13 @@
uint32_t APInt::countTrailingZeros() const {
if (isSingleWord())
return CountTrailingZeros_64(VAL);
- APInt Tmp( ~(*this) & ((*this) - APInt(BitWidth,1)) );
- return getNumWords() * APINT_BITS_PER_WORD - Tmp.countLeadingZeros();
+ uint32_t Count = 0;
+ uint32_t i = 0;
+ for (; i < getNumWords() && pVal[i] == 0; ++i)
+ Count += APINT_BITS_PER_WORD;
+ if (i < getNumWords())
+ Count += CountTrailingZeros_64(pVal[i]);
+ return Count;
}
uint32_t APInt::countPopulation() const {
@@ -863,9 +868,8 @@
void APInt::sext(uint32_t width) {
assert(width > BitWidth && "Invalid APInt SignExtend request");
assert(width <= IntegerType::MAX_INT_BITS && "Too many bits");
- bool isNegative = (*this)[BitWidth-1];
// If the sign bit isn't set, this is the same as zext.
- if (!isNegative) {
+ if (!isNegative()) {
zext(width);
return;
}
@@ -929,35 +933,66 @@
/// Arithmetic right-shift this APInt by shiftAmt.
/// @brief Arithmetic right-shift function.
APInt APInt::ashr(uint32_t shiftAmt) const {
+ assert(shiftAmt <= BitWidth && "Invalid shift amount");
if (isSingleWord()) {
if (shiftAmt == BitWidth)
+ return APInt(BitWidth, 0); // undefined
+ else {
+ uint32_t SignBit = APINT_BITS_PER_WORD - BitWidth;
+ return APInt(BitWidth,
+ (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt));
+ }
+ }
+
+ // If all the bits were shifted out, the result is 0 or -1. This avoids issues
+ // with shifting by the size of the integer type, which produces undefined
+ // results.
+ if (shiftAmt == BitWidth)
+ if (isNegative())
return APInt(BitWidth, -1ULL);
else
- return APInt(BitWidth,
- (((int64_t(VAL) << (APINT_BITS_PER_WORD - BitWidth)) >>
- (APINT_BITS_PER_WORD - BitWidth)) >> shiftAmt)).clearUnusedBits();
+ return APInt(BitWidth, 0);
+
+ // Create some space for the result.
+ uint64_t * val = new uint64_t[getNumWords()];
+
+ // If we are shifting less than a word, compute the shift with a simple carry
+ if (shiftAmt < APINT_BITS_PER_WORD) {
+ uint64_t carry = 0;
+ for (int i = getNumWords()-1; i >= 0; --i) {
+ val[i] = pVal[i] >> shiftAmt | carry;
+ carry = pVal[i] << (APINT_BITS_PER_WORD - shiftAmt);
+ }
+ return APInt(val, BitWidth).clearUnusedBits();
}
- APInt Result(*this);
- if (shiftAmt >= BitWidth) {
- memset(Result.pVal, Result[BitWidth-1] ? 1 : 0,
- (getNumWords()-1) * APINT_WORD_SIZE);
- return Result.clearUnusedBits();
- }
+ // Compute some values needed by the remaining shift algorithms
+ uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD;
+ uint32_t offset = shiftAmt / APINT_BITS_PER_WORD;
- // FIXME: bit-at-a-time shift is really slow.
- uint32_t i = 0;
- for (; i < BitWidth - shiftAmt; ++i)
- if (Result[i+shiftAmt])
- Result.set(i);
- else
- Result.clear(i);
- for (; i < BitWidth; ++i)
- if (Result[BitWidth-1])
- Result.set(i);
- else
- Result.clear(i);
- return Result;
+ // If we are shifting whole words, just move whole words
+ if (wordShift == 0) {
+ for (uint32_t i = 0; i < getNumWords() - offset; ++i)
+ val[i] = pVal[i+offset];
+ for (uint32_t i = getNumWords()-offset; i < getNumWords(); i++)
+ val[i] = (isNegative() ? -1ULL : 0);
+ return APInt(val,BitWidth).clearUnusedBits();
+ }
+
+ // Shift the low order words
+ uint32_t breakWord = getNumWords() - offset -1;
+ for (uint32_t i = 0; i < breakWord; ++i)
+ val[i] = pVal[i+offset] >> wordShift |
+ pVal[i+offset+1] << (APINT_BITS_PER_WORD - wordShift);
+ // Shift the break word.
+ uint32_t SignBit = APINT_BITS_PER_WORD - (BitWidth % APINT_BITS_PER_WORD);
+ val[breakWord] = uint64_t(
+ (((int64_t(pVal[breakWord+offset]) << SignBit) >> SignBit) >> wordShift));
+
+ // Remaining words are 0 or -1
+ for (uint32_t i = breakWord+1; i < getNumWords(); ++i)
+ val[i] = (isNegative() ? -1ULL : 0);
+ return APInt(val, BitWidth).clearUnusedBits();
}
/// Logical right-shift this APInt by shiftAmt.
@@ -1022,7 +1057,7 @@
if (isSingleWord()) {
if (shiftAmt == BitWidth)
return APInt(BitWidth, 0); // avoid undefined shift results
- return APInt(BitWidth, VAL << shiftAmt).clearUnusedBits();
+ return APInt(BitWidth, VAL << shiftAmt);
}
// If all the bits were shifted out, the result is 0. This avoids issues
@@ -1148,7 +1183,7 @@
// (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation
// consists of a simple multiplication by a one-place number, combined with
// a subtraction.
- bool isNegative = false;
+ bool isNeg = false;
for (uint32_t i = 0; i < n; ++i) {
uint64_t u_tmp = uint64_t(u[j+i]) | (uint64_t(u[j+i+1]) << 32);
uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]);
@@ -1166,7 +1201,7 @@
u[k]--;
k++;
}
- isNegative |= borrow;
+ isNeg |= borrow;
DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " <<
u[j+i+1] << '\n');
}
@@ -1178,7 +1213,7 @@
// true value plus b**(n+1), namely as the b's complement of
// the true value, and a "borrow" to the left should be remembered.
//
- if (isNegative) {
+ if (isNeg) {
bool carry = true; // true because b's complement is "complement + 1"
for (uint32_t i = 0; i <= m+n; ++i) {
u[i] = ~u[i] + carry; // b's complement
@@ -1192,7 +1227,7 @@
// D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was
// negative, go to step D6; otherwise go on to step D7.
q[j] = qp;
- if (isNegative) {
+ if (isNeg) {
// D6. [Add back]. The probability that this step is necessary is very
// small, on the order of only 2/b. Make sure that test data accounts for
// this possibility. Decrease q[j] by 1
@@ -1501,8 +1536,8 @@
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
"Radix should be 2, 8, 10, or 16!");
assert(str && "String is null?");
- bool isNegative = str[0] == '-';
- if (isNegative)
+ bool isNeg = str[0] == '-';
+ if (isNeg)
str++, slen--;
assert(slen <= numbits || radix != 2 && "Insufficient bit width");
assert(slen*3 <= numbits || radix != 8 && "Insufficient bit width");
@@ -1552,9 +1587,9 @@
*this += apdigit;
}
// If its negative, put it in two's complement form
- if (isNegative) {
+ if (isNeg) {
+ (*this)--;
this->flip();
- (*this)++;
}
}
More information about the llvm-commits
mailing list