]> granicus.if.org Git - llvm/commitdiff
[APInt] Simplify the zext and sext methods
authorCraig Topper <craig.topper@gmail.com>
Mon, 24 Apr 2017 17:37:10 +0000 (17:37 +0000)
committerCraig Topper <craig.topper@gmail.com>
Mon, 24 Apr 2017 17:37:10 +0000 (17:37 +0000)
This replaces a hand written copy loop with a call to memcpy for both zext and sext.

For sext, it replaces multiple if/else blocks propagating sign information forward. Now we just do a copy, a sign extension on the last copied word, a memset, and clearUnusedBits.

Differential Revision: https://reviews.llvm.org/D32417

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301201 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/APInt.cpp

index 9c668468ff95787a5c0801a715fccf6cb0f2ee65..1227d7528c8f92a53cda29fabbf2bcc31fc5e5f4 100644 (file)
@@ -939,40 +939,26 @@ APInt APInt::trunc(unsigned width) const {
 }
 
 // Sign extend to a new width.
-APInt APInt::sext(unsigned width) const {
-  assert(width > BitWidth && "Invalid APInt SignExtend request");
+APInt APInt::sext(unsigned Width) const {
+  assert(Width > BitWidth && "Invalid APInt SignExtend request");
 
-  if (width <= APINT_BITS_PER_WORD)
-    return APInt(width, SignExtend64(VAL, BitWidth));
+  if (Width <= APINT_BITS_PER_WORD)
+    return APInt(Width, SignExtend64(VAL, BitWidth));
 
-  APInt Result(getMemory(getNumWords(width)), width);
+  APInt Result(getMemory(getNumWords(Width)), Width);
 
-  // Copy full words.
-  unsigned i;
-  uint64_t word = 0;
-  for (i = 0; i != BitWidth / APINT_BITS_PER_WORD; i++) {
-    word = getRawData()[i];
-    Result.pVal[i] = word;
-  }
-
-  // Read and sign-extend any partial word.
-  unsigned bits = (0 - BitWidth) % APINT_BITS_PER_WORD;
-  if (bits != 0)
-    word = (int64_t)getRawData()[i] << bits >> bits;
-  else
-    word = (int64_t)word >> (APINT_BITS_PER_WORD - 1);
-
-  // Write remaining full words.
-  for (; i != width / APINT_BITS_PER_WORD; i++) {
-    Result.pVal[i] = word;
-    word = (int64_t)word >> (APINT_BITS_PER_WORD - 1);
-  }
+  // Copy words.
+  std::memcpy(Result.pVal, getRawData(), getNumWords() * APINT_WORD_SIZE);
 
-  // Write any partial word.
-  bits = (0 - width) % APINT_BITS_PER_WORD;
-  if (bits != 0)
-    Result.pVal[i] = word << bits >> bits;
+  // Sign extend the last word since there may be unused bits in the input.
+  Result.pVal[getNumWords() - 1] =
+      SignExtend64(Result.pVal[getNumWords() - 1],
+                   ((BitWidth - 1) % APINT_BITS_PER_WORD) + 1);
 
+  // Fill with sign bits.
+  std::memset(Result.pVal + getNumWords(), isNegative() ? -1 : 0,
+              (Result.getNumWords() - getNumWords()) * APINT_WORD_SIZE);
+  Result.clearUnusedBits();
   return Result;
 }
 
@@ -986,12 +972,11 @@ APInt APInt::zext(unsigned width) const {
   APInt Result(getMemory(getNumWords(width)), width);
 
   // Copy words.
-  unsigned i;
-  for (i = 0; i != getNumWords(); i++)
-    Result.pVal[i] = getRawData()[i];
+  std::memcpy(Result.pVal, getRawData(), getNumWords() * APINT_WORD_SIZE);
 
   // Zero remaining words.
-  memset(&Result.pVal[i], 0, (Result.getNumWords() - i) * APINT_WORD_SIZE);
+  std::memset(Result.pVal + getNumWords(), 0,
+              (Result.getNumWords() - getNumWords()) * APINT_WORD_SIZE);
 
   return Result;
 }