[llvm-commits] CVS: llvm/lib/Support/APInt.cpp

Reid Spencer reid at x10sys.com
Sat Feb 24 16:57:01 PST 2007



Changes in directory llvm/lib/Support:

APInt.cpp updated: 1.36 -> 1.37
---
Log message:

Fix the > 64 bits case for left shift.


---
Diffs of the changes:  (+52 -27)

 APInt.cpp |   79 ++++++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 52 insertions(+), 27 deletions(-)


Index: llvm/lib/Support/APInt.cpp
diff -u llvm/lib/Support/APInt.cpp:1.36 llvm/lib/Support/APInt.cpp:1.37
--- llvm/lib/Support/APInt.cpp:1.36	Sat Feb 24 14:38:01 2007
+++ llvm/lib/Support/APInt.cpp	Sat Feb 24 18:56:44 2007
@@ -946,34 +946,59 @@
 /// @brief Left-shift function.
 APInt APInt::shl(uint32_t shiftAmt) const {
   assert(shiftAmt <= BitWidth && "Invalid shift amount");
-  APInt API(*this);
-  if (API.isSingleWord()) {
+  if (isSingleWord()) {
     if (shiftAmt == BitWidth)
-      API.VAL = 0;
-    else 
-      API.VAL <<= shiftAmt;
-    API.clearUnusedBits();
-    return API;
-  }
-
-  if (shiftAmt == BitWidth) {
-    memset(API.pVal, 0, getNumWords() * APINT_WORD_SIZE);
-    return API;
-  }
-
-  if (uint32_t offset = shiftAmt / APINT_BITS_PER_WORD) {
-    for (uint32_t i = API.getNumWords() - 1; i > offset - 1; --i)
-      API.pVal[i] = API.pVal[i-offset];
-    memset(API.pVal, 0, offset * APINT_WORD_SIZE);
-  }
-  shiftAmt %= APINT_BITS_PER_WORD;
-  uint32_t i;
-  for (i = API.getNumWords() - 1; i > 0; --i)
-    API.pVal[i] = (API.pVal[i] << shiftAmt) | 
-                  (API.pVal[i-1] >> (APINT_BITS_PER_WORD - shiftAmt));
-  API.pVal[i] <<= shiftAmt;
-  API.clearUnusedBits();
-  return API;
+      return APInt(BitWidth, 0); // avoid undefined shift results
+    return APInt(BitWidth, (VAL << shiftAmt) &  
+                           (~uint64_t(0ULL) >> 
+                            (APINT_BITS_PER_WORD - BitWidth)));
+  }
+
+  // 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);
+
+  // 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;
+    shiftAmt %= APINT_BITS_PER_WORD;
+    for (uint32_t i = 0; i < getNumWords(); i++) {
+      val[i] = pVal[i] << shiftAmt | carry;
+      carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt);
+    }
+    val[getNumWords()-1] &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth);
+    return APInt(val, BitWidth);
+  }
+
+  // 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;
+
+  // If we are shifting whole words, just move whole words
+  if (wordShift == 0) {
+    for (uint32_t i = 0; i < offset; i++) 
+      val[i] = 0;
+    for (uint32_t i = offset; i < getNumWords(); i++)
+      val[i] = pVal[i-offset];
+    val[getNumWords()-1] &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth);
+    return APInt(val,BitWidth);
+  }
+
+  // Copy whole words from this to Result.
+  uint32_t 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[offset-1] << wordShift;
+  for (i = 0; i < offset; ++i)
+    val[i] = 0;
+  val[getNumWords()-1] &= ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - BitWidth);
+  return APInt(val, BitWidth);
 }
 
 /// Implementation of Knuth's Algorithm D (Division of nonnegative integers)






More information about the llvm-commits mailing list