[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