Skip to content

Added APInt::clearBits() method #136550 #136557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

a2p1k02
Copy link

@a2p1k02 a2p1k02 commented Apr 21, 2025

Set the bits from loBit (inclusive) to hiBit (exclusive) to 0.
This function handles "high" bits correctly (i.e. hiBit can be bigger than the bit width of the APInt - in which case all bits from loBit to the end of the APInt are zeroed).

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Apr 21, 2025

@llvm/pr-subscribers-llvm-support

Author: Alexander (a2p1k02)

Changes

Set the bits from loBit (inclusive) to hiBit (exclusive) to 0.
This function handles "high" bits correctly (i.e. hiBit can be bigger than the bit width of the APInt - in which case all bits from loBit to the end of the APInt are zeroed).


Patch is 77.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136557.diff

3 Files Affected:

  • (modified) llvm/include/llvm/ADT/APInt.h (+6)
  • (modified) llvm/lib/Support/APInt.cpp (+221-182)
  • (modified) llvm/unittests/ADT/APIntTest.cpp (+252-242)
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 02d58d8c3d31c..6ffade653ff4b 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -1815,6 +1815,12 @@ class [[nodiscard]] APInt {
   /// Clear the given bit of a bignum.  Zero-based.
   static void tcClearBit(WordType *, unsigned bit);
 
+  /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 0.
+  /// This function handles "high" bits correctly (i.e. hiBit can be bigger than
+  /// the bit width of the APInt - in which case all bits from loBit to the end
+  /// of the APInt are zeroed).
+  void clearBits(unsigned loBit, unsigned hiBit);
+
   /// Returns the bit number of the least or most significant set bit of a
   /// number.  If the input number has no bits set -1U is returned.
   static unsigned tcLSB(const WordType *, unsigned n);
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 4e45416b4598f..07af5407b8967 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -33,13 +33,13 @@ using namespace llvm;
 
 /// A utility function for allocating memory, checking for allocation failures,
 /// and ensuring the contents are zeroed.
-inline static uint64_t* getClearedMemory(unsigned numWords) {
+inline static uint64_t *getClearedMemory(unsigned numWords) {
   return new uint64_t[numWords]();
 }
 
 /// A utility function for allocating memory and checking for allocation
 /// failure.  The content is not zeroed.
-inline static uint64_t* getMemory(unsigned numWords) {
+inline static uint64_t *getMemory(unsigned numWords) {
   return new uint64_t[numWords];
 }
 
@@ -70,7 +70,6 @@ inline static unsigned getDigit(char cdigit, uint8_t radix) {
   return UINT_MAX;
 }
 
-
 void APInt::initSlowCase(uint64_t val, bool isSigned) {
   if (isSigned && int64_t(val) < 0) {
     U.pVal = getMemory(getNumWords());
@@ -83,7 +82,7 @@ void APInt::initSlowCase(uint64_t val, bool isSigned) {
   }
 }
 
-void APInt::initSlowCase(const APInt& that) {
+void APInt::initSlowCase(const APInt &that) {
   U.pVal = getMemory(getNumWords());
   memcpy(U.pVal, that.U.pVal, getNumWords() * APINT_WORD_SIZE);
 }
@@ -127,7 +126,7 @@ void APInt::reallocate(unsigned NewBitWidth) {
 
   // If we have an allocation, delete it.
   if (!isSingleWord())
-    delete [] U.pVal;
+    delete[] U.pVal;
 
   // Update BitWidth.
   BitWidth = NewBitWidth;
@@ -153,7 +152,7 @@ void APInt::assignSlowCase(const APInt &RHS) {
 }
 
 /// This method 'profiles' an APInt for use with FoldingSet.
-void APInt::Profile(FoldingSetNodeID& ID) const {
+void APInt::Profile(FoldingSetNodeID &ID) const {
   ID.AddInteger(BitWidth);
 
   if (isSingleWord()) {
@@ -175,7 +174,7 @@ bool APInt::isAligned(Align A) const {
 }
 
 /// Prefix increment operator. Increments the APInt by one.
-APInt& APInt::operator++() {
+APInt &APInt::operator++() {
   if (isSingleWord())
     ++U.VAL;
   else
@@ -184,7 +183,7 @@ APInt& APInt::operator++() {
 }
 
 /// Prefix decrement operator. Decrements the APInt by one.
-APInt& APInt::operator--() {
+APInt &APInt::operator--() {
   if (isSingleWord())
     --U.VAL;
   else
@@ -195,7 +194,7 @@ APInt& APInt::operator--() {
 /// Adds the RHS APInt to this APInt.
 /// @returns this, after addition of RHS.
 /// Addition assignment operator.
-APInt& APInt::operator+=(const APInt& RHS) {
+APInt &APInt::operator+=(const APInt &RHS) {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord())
     U.VAL += RHS.U.VAL;
@@ -204,7 +203,7 @@ APInt& APInt::operator+=(const APInt& RHS) {
   return clearUnusedBits();
 }
 
-APInt& APInt::operator+=(uint64_t RHS) {
+APInt &APInt::operator+=(uint64_t RHS) {
   if (isSingleWord())
     U.VAL += RHS;
   else
@@ -215,7 +214,7 @@ APInt& APInt::operator+=(uint64_t RHS) {
 /// Subtracts the RHS APInt from this APInt
 /// @returns this, after subtraction
 /// Subtraction assignment operator.
-APInt& APInt::operator-=(const APInt& RHS) {
+APInt &APInt::operator-=(const APInt &RHS) {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord())
     U.VAL -= RHS.U.VAL;
@@ -224,7 +223,7 @@ APInt& APInt::operator-=(const APInt& RHS) {
   return clearUnusedBits();
 }
 
-APInt& APInt::operator-=(uint64_t RHS) {
+APInt &APInt::operator-=(uint64_t RHS) {
   if (isSingleWord())
     U.VAL -= RHS;
   else
@@ -232,7 +231,7 @@ APInt& APInt::operator-=(uint64_t RHS) {
   return clearUnusedBits();
 }
 
-APInt APInt::operator*(const APInt& RHS) const {
+APInt APInt::operator*(const APInt &RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord())
     return APInt(BitWidth, U.VAL * RHS.U.VAL, /*isSigned=*/false,
@@ -267,7 +266,7 @@ APInt &APInt::operator*=(const APInt &RHS) {
   return *this;
 }
 
-APInt& APInt::operator*=(uint64_t RHS) {
+APInt &APInt::operator*=(uint64_t RHS) {
   if (isSingleWord()) {
     U.VAL *= RHS;
   } else {
@@ -281,7 +280,7 @@ bool APInt::equalSlowCase(const APInt &RHS) const {
   return std::equal(U.pVal, U.pVal + getNumWords(), RHS.U.pVal);
 }
 
-int APInt::compare(const APInt& RHS) const {
+int APInt::compare(const APInt &RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
   if (isSingleWord())
     return U.VAL < RHS.U.VAL ? -1 : U.VAL > RHS.U.VAL;
@@ -289,7 +288,7 @@ int APInt::compare(const APInt& RHS) const {
   return tcCompare(U.pVal, RHS.U.pVal, getNumWords());
 }
 
-int APInt::compareSigned(const APInt& RHS) const {
+int APInt::compareSigned(const APInt &RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
   if (isSingleWord()) {
     int64_t lhsSext = SignExtend64(U.VAL, BitWidth);
@@ -425,7 +424,8 @@ void APInt::insertBits(const APInt &subBits, unsigned bitPosition) {
     setBitVal(bitPosition + i, subBits[i]);
 }
 
-void APInt::insertBits(uint64_t subBits, unsigned bitPosition, unsigned numBits) {
+void APInt::insertBits(uint64_t subBits, unsigned bitPosition,
+                       unsigned numBits) {
   uint64_t maskBits = maskTrailingOnes<uint64_t>(numBits);
   subBits &= maskBits;
   if (isSingleWord()) {
@@ -443,7 +443,8 @@ void APInt::insertBits(uint64_t subBits, unsigned bitPosition, unsigned numBits)
     return;
   }
 
-  static_assert(8 * sizeof(WordType) <= 64, "This code assumes only two words affected");
+  static_assert(8 * sizeof(WordType) <= 64,
+                "This code assumes only two words affected");
   unsigned wordBits = 8 * sizeof(WordType);
   U.pVal[loWord] &= ~(maskBits << loBit);
   U.pVal[loWord] |= subBits << loBit;
@@ -570,7 +571,6 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
     assert(slen && "String is only a sign, needs a value.");
   }
 
-
   // Convert to the actual binary value.
   APInt tmp(sufficient, StringRef(p, slen), radix);
 
@@ -633,7 +633,7 @@ APInt APInt::getSplat(unsigned NewLen, const APInt &V) {
 
 unsigned APInt::countLeadingZerosSlowCase() const {
   unsigned Count = 0;
-  for (int i = getNumWords()-1; i >= 0; --i) {
+  for (int i = getNumWords() - 1; i >= 0; --i) {
     uint64_t V = U.pVal[i];
     if (V == 0)
       Count += APINT_BITS_PER_WORD;
@@ -770,11 +770,14 @@ APInt APInt::reverseBits() const {
 
 APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {
   // Fast-path a common case.
-  if (A == B) return A;
+  if (A == B)
+    return A;
 
   // Corner cases: if either operand is zero, the other is the gcd.
-  if (!A) return B;
-  if (!B) return A;
+  if (!A)
+    return B;
+  if (!B)
+    return A;
 
   // Count common powers of 2 and remove all other powers of 2.
   unsigned Pow2;
@@ -829,8 +832,8 @@ APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
 
   // If the exponent doesn't shift all bits out of the mantissa
   if (exp < 52)
-    return isNeg ? -APInt(width, mantissa >> (52 - exp)) :
-                    APInt(width, mantissa >> (52 - exp));
+    return isNeg ? -APInt(width, mantissa >> (52 - exp))
+                 : APInt(width, mantissa >> (52 - exp));
 
   // If the client didn't provide enough bits for us to shift the mantissa into
   // then the result is undefined, just return 0
@@ -853,7 +856,8 @@ APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
 double APInt::roundToDouble(bool isSigned) const {
 
   // Handle the simple case where the value is contained in one uint64_t.
-  // It is wrong to optimize getWord(0) to VAL; there might be more than one word.
+  // It is wrong to optimize getWord(0) to VAL; there might be more than one
+  // word.
   if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
     if (isSigned) {
       int64_t sext = SignExtend64(getWord(0), BitWidth);
@@ -863,7 +867,7 @@ double APInt::roundToDouble(bool isSigned) const {
   }
 
   // Determine if the value is negative.
-  bool isNeg = isSigned ? (*this)[BitWidth-1] : false;
+  bool isNeg = isSigned ? (*this)[BitWidth - 1] : false;
 
   // Construct the absolute value if we're negative.
   APInt Tmp(isNeg ? -(*this) : (*this));
@@ -888,7 +892,7 @@ double APInt::roundToDouble(bool isSigned) const {
   // Number of bits in mantissa is 52. To obtain the mantissa value, we must
   // extract the high 52 bits from the correct words in pVal.
   uint64_t mantissa;
-  unsigned hiWord = whichWord(n-1);
+  unsigned hiWord = whichWord(n - 1);
   if (hiWord == 0) {
     mantissa = Tmp.U.pVal[0];
     if (n > 52)
@@ -896,7 +900,7 @@ double APInt::roundToDouble(bool isSigned) const {
   } else {
     assert(hiWord > 0 && "huh?");
     uint64_t hibits = Tmp.U.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD);
-    uint64_t lobits = Tmp.U.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD);
+    uint64_t lobits = Tmp.U.pVal[hiWord - 1] >> (11 + n % APINT_BITS_PER_WORD);
     mantissa = hibits | lobits;
   }
 
@@ -1052,8 +1056,9 @@ void APInt::ashrSlowCase(unsigned ShiftAmt) {
     } else {
       // Move the words containing significant bits.
       for (unsigned i = 0; i != WordsToMove - 1; ++i)
-        U.pVal[i] = (U.pVal[i + WordShift] >> BitShift) |
-                    (U.pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift));
+        U.pVal[i] =
+            (U.pVal[i + WordShift] >> BitShift) |
+            (U.pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift));
 
       // Handle the last word which has no high bits to copy. Use an arithmetic
       // shift to preserve the sign bit.
@@ -1179,15 +1184,14 @@ APInt APInt::sqrt() const {
   // rounding errors in libc sqrt for small values.
   if (magnitude <= 5) {
     static const uint8_t results[32] = {
-      /*     0 */ 0,
-      /*  1- 2 */ 1, 1,
-      /*  3- 6 */ 2, 2, 2, 2,
-      /*  7-12 */ 3, 3, 3, 3, 3, 3,
-      /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
-      /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-      /*    31 */ 6
-    };
-    return APInt(BitWidth, results[ (isSingleWord() ? U.VAL : U.pVal[0]) ]);
+        /*     0 */ 0,
+        /*  1- 2 */ 1, 1,
+        /*  3- 6 */ 2, 2, 2, 2,
+        /*  7-12 */ 3, 3, 3, 3, 3, 3,
+        /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
+        /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+        /*    31 */ 6};
+    return APInt(BitWidth, results[(isSingleWord() ? U.VAL : U.pVal[0])]);
   }
 
   // If the magnitude of the value fits in less than 52 bits (the precision of
@@ -1195,9 +1199,9 @@ APInt APInt::sqrt() const {
   // libc sqrt function which will probably use a hardware sqrt computation.
   // This should be faster than the algorithm below.
   if (magnitude < 52) {
-    return APInt(BitWidth,
-                 uint64_t(::round(::sqrt(double(isSingleWord() ? U.VAL
-                                                               : U.pVal[0])))));
+    return APInt(
+        BitWidth,
+        uint64_t(::round(::sqrt(double(isSingleWord() ? U.VAL : U.pVal[0])))));
   }
 
   // Okay, all the short cuts are exhausted. We must compute it. The following
@@ -1233,7 +1237,7 @@ APInt APInt::sqrt() const {
   // floating point representation after 192 bits. There are no discrepancies
   // between this algorithm and pari/gp for bit widths < 192 bits.
   APInt square(x_old * x_old);
-  APInt nextSquare((x_old + 1) * (x_old +1));
+  APInt nextSquare((x_old + 1) * (x_old + 1));
   if (this->ult(square))
     return x_old;
   assert(this->ule(nextSquare) && "Error in APInt::sqrt computation");
@@ -1261,13 +1265,13 @@ APInt APInt::multiplicativeInverse() const {
 /// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The
 /// variables here have the same names as in the algorithm. Comments explain
 /// the algorithm and any deviation from it.
-static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
+static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t *r,
                      unsigned m, unsigned n) {
   assert(u && "Must provide dividend");
   assert(v && "Must provide divisor");
   assert(q && "Must provide quotient");
   assert(u != v && u != q && v != q && "Must use different memory");
-  assert(n>1 && "n must be > 1");
+  assert(n > 1 && "n must be > 1");
 
   // b denotes the base of the number system. In our case b is 2^32.
   const uint64_t b = uint64_t(1) << 32;
@@ -1277,7 +1281,9 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
 #ifdef KNUTH_DEBUG
 #define DEBUG_KNUTH(X) LLVM_DEBUG(X)
 #else
-#define DEBUG_KNUTH(X) do {} while(false)
+#define DEBUG_KNUTH(X)                                                         \
+  do {                                                                         \
+  } while (false)
 #endif
 
   DEBUG_KNUTH(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n');
@@ -1298,7 +1304,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
   uint32_t v_carry = 0;
   uint32_t u_carry = 0;
   if (shift) {
-    for (unsigned i = 0; i < m+n; ++i) {
+    for (unsigned i = 0; i < m + n; ++i) {
       uint32_t u_tmp = u[i] >> (32 - shift);
       u[i] = (u[i] << shift) | u_carry;
       u_carry = u_tmp;
@@ -1309,7 +1315,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
       v_carry = v_tmp;
     }
   }
-  u[m+n] = u_carry;
+  u[m + n] = u_carry;
 
   DEBUG_KNUTH(dbgs() << "KnuthDiv:   normal:");
   DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
@@ -1329,14 +1335,14 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
     // on v[n-2] determines at high speed most of the cases in which the trial
     // value qp is one too large, and it eliminates all cases where qp is two
     // too large.
-    uint64_t dividend = Make_64(u[j+n], u[j+n-1]);
+    uint64_t dividend = Make_64(u[j + n], u[j + n - 1]);
     DEBUG_KNUTH(dbgs() << "KnuthDiv: dividend == " << dividend << '\n');
-    uint64_t qp = dividend / v[n-1];
-    uint64_t rp = dividend % v[n-1];
-    if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) {
+    uint64_t qp = dividend / v[n - 1];
+    uint64_t rp = dividend % v[n - 1];
+    if (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]) {
       qp--;
-      rp += v[n-1];
-      if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2]))
+      rp += v[n - 1];
+      if (rp < b && (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]))
         qp--;
     }
     DEBUG_KNUTH(dbgs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n');
@@ -1352,14 +1358,14 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
     int64_t borrow = 0;
     for (unsigned i = 0; i < n; ++i) {
       uint64_t p = uint64_t(qp) * uint64_t(v[i]);
-      int64_t subres = int64_t(u[j+i]) - borrow - Lo_32(p);
-      u[j+i] = Lo_32(subres);
+      int64_t subres = int64_t(u[j + i]) - borrow - Lo_32(p);
+      u[j + i] = Lo_32(subres);
       borrow = Hi_32(p) - Hi_32(subres);
       DEBUG_KNUTH(dbgs() << "KnuthDiv: u[j+i] = " << u[j + i]
-                        << ", borrow = " << borrow << '\n');
+                         << ", borrow = " << borrow << '\n');
     }
-    bool isNeg = u[j+n] < borrow;
-    u[j+n] -= Lo_32(borrow);
+    bool isNeg = u[j + n] < borrow;
+    u[j + n] -= Lo_32(borrow);
 
     DEBUG_KNUTH(dbgs() << "KnuthDiv: after subtraction:");
     DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
@@ -1378,11 +1384,11 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
       // since it cancels with the borrow that occurred in D4.
       bool carry = false;
       for (unsigned i = 0; i < n; i++) {
-        uint32_t limit = std::min(u[j+i],v[i]);
-        u[j+i] += v[i] + carry;
-        carry = u[j+i] < limit || (carry && u[j+i] == limit);
+        uint32_t limit = std::min(u[j + i], v[i]);
+        u[j + i] += v[i] + carry;
+        carry = u[j + i] < limit || (carry && u[j + i] == limit);
       }
-      u[j+n] += carry;
+      u[j + n] += carry;
     }
     DEBUG_KNUTH(dbgs() << "KnuthDiv: after correction:");
     DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
@@ -1405,13 +1411,13 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
     if (shift) {
       uint32_t carry = 0;
       DEBUG_KNUTH(dbgs() << "KnuthDiv: remainder:");
-      for (int i = n-1; i >= 0; i--) {
+      for (int i = n - 1; i >= 0; i--) {
         r[i] = (u[i] >> shift) | carry;
         carry = u[i] << (32 - shift);
         DEBUG_KNUTH(dbgs() << " " << r[i]);
       }
     } else {
-      for (int i = n-1; i >= 0; i--) {
+      for (int i = n - 1; i >= 0; i--) {
         r[i] = u[i];
         DEBUG_KNUTH(dbgs() << " " << r[i]);
       }
@@ -1442,31 +1448,31 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   uint32_t *V = nullptr;
   uint32_t *Q = nullptr;
   uint32_t *R = nullptr;
-  if ((Remainder?4:3)*n+2*m+1 <= 128) {
+  if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
     U = &SPACE[0];
-    V = &SPACE[m+n+1];
-    Q = &SPACE[(m+n+1) + n];
+    V = &SPACE[m + n + 1];
+    Q = &SPACE[(m + n + 1) + n];
     if (Remainder)
-      R = &SPACE[(m+n+1) + n + (m+n)];
+      R = &SPACE[(m + n + 1) + n + (m + n)];
   } else {
     U = new uint32_t[m + n + 1];
     V = new uint32_t[n];
-    Q = new uint32_t[m+n];
+    Q = new uint32_t[m + n];
     if (Remainder)
       R = new uint32_t[n];
   }
 
   // Initialize the dividend
-  memset(U, 0, (m+n+1)*sizeof(uint32_t));
+  memset(U, 0, (m + n + 1) * sizeof(uint32_t));
   for (unsigned i = 0; i < lhsWords; ++i) {
     uint64_t tmp = LHS[i];
     U[i * 2] = Lo_32(tmp);
     U[i * 2 + 1] = Hi_32(tmp);
   }
-  U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm.
+  U[m + n] = 0; // this extra word is for "spill" in the Knuth algorithm.
 
   // Initialize the divisor
-  memset(V, 0, (n)*sizeof(uint32_t));
+  memset(V, 0, (n) * sizeof(uint32_t));
   for (unsigned i = 0; i < rhsWords; ++i) {
     uint64_t tmp = RHS[i];
     V[i * 2] = Lo_32(tmp);
@@ -1474,7 +1480,7 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   }
 
   // initialize the quotient and remainder
-  memset(Q, 0, (m+n) * sizeof(uint32_t));
+  memset(Q, 0, (m + n) * sizeof(uint32_t));
   if (Remainder)
     memset(R, 0, n * sizeof(uint32_t));
 
@@ -1482,11 +1488,11 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   // the divisor. m is the number of words by which the dividend exceeds the
   // divisor (i.e. m+n is the length of the dividend). These sizes must not
   // contain any zero words or the Knuth algorithm fails.
-  for (unsigned i = n; i > 0 && V[i-1] == 0; i--) {
+  for (unsigned i = n; i > 0 && V[i - 1] == 0; i--) {
     n--;
     m++;
   }
-  for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--)
+  for (unsigned i = m + n; i > 0 && U[i - 1] == 0; i--)
     m--;
 
   // If we're left with only a single word for the divisor, Knuth doesn't work
@@ -1526,21 +1532,21 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   // If the caller wants the quotient
   if (Quotient) {
     for (unsigned i = 0; i < lhsWords; ++i)
-      Quotient[i] = Make_64(Q[i*2+1], Q[i*2]);
+      Quotient[i] = Make_64(Q[i * 2 + 1], Q[i * 2]);
   }
 
   // If the caller wants the remainder
   if (Remainder) {
     for (unsigned i = 0; i < rhsWords; ++i)
-      Remainder[i] = Make_64(R[i*2+1], R[i*2]);
+      Remainder[i] = Make_64(R[i * 2 + 1], R[i * 2]);
   }
 
   // Clean up the memory we allocated.
   ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Apr 21, 2025

@llvm/pr-subscribers-llvm-adt

Author: Alexander (a2p1k02)

Changes

Set the bits from loBit (inclusive) to hiBit (exclusive) to 0.
This function handles "high" bits correctly (i.e. hiBit can be bigger than the bit width of the APInt - in which case all bits from loBit to the end of the APInt are zeroed).


Patch is 77.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/136557.diff

3 Files Affected:

  • (modified) llvm/include/llvm/ADT/APInt.h (+6)
  • (modified) llvm/lib/Support/APInt.cpp (+221-182)
  • (modified) llvm/unittests/ADT/APIntTest.cpp (+252-242)
diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 02d58d8c3d31c..6ffade653ff4b 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -1815,6 +1815,12 @@ class [[nodiscard]] APInt {
   /// Clear the given bit of a bignum.  Zero-based.
   static void tcClearBit(WordType *, unsigned bit);
 
+  /// Set the bits from loBit (inclusive) to hiBit (exclusive) to 0.
+  /// This function handles "high" bits correctly (i.e. hiBit can be bigger than
+  /// the bit width of the APInt - in which case all bits from loBit to the end
+  /// of the APInt are zeroed).
+  void clearBits(unsigned loBit, unsigned hiBit);
+
   /// Returns the bit number of the least or most significant set bit of a
   /// number.  If the input number has no bits set -1U is returned.
   static unsigned tcLSB(const WordType *, unsigned n);
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 4e45416b4598f..07af5407b8967 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -33,13 +33,13 @@ using namespace llvm;
 
 /// A utility function for allocating memory, checking for allocation failures,
 /// and ensuring the contents are zeroed.
-inline static uint64_t* getClearedMemory(unsigned numWords) {
+inline static uint64_t *getClearedMemory(unsigned numWords) {
   return new uint64_t[numWords]();
 }
 
 /// A utility function for allocating memory and checking for allocation
 /// failure.  The content is not zeroed.
-inline static uint64_t* getMemory(unsigned numWords) {
+inline static uint64_t *getMemory(unsigned numWords) {
   return new uint64_t[numWords];
 }
 
@@ -70,7 +70,6 @@ inline static unsigned getDigit(char cdigit, uint8_t radix) {
   return UINT_MAX;
 }
 
-
 void APInt::initSlowCase(uint64_t val, bool isSigned) {
   if (isSigned && int64_t(val) < 0) {
     U.pVal = getMemory(getNumWords());
@@ -83,7 +82,7 @@ void APInt::initSlowCase(uint64_t val, bool isSigned) {
   }
 }
 
-void APInt::initSlowCase(const APInt& that) {
+void APInt::initSlowCase(const APInt &that) {
   U.pVal = getMemory(getNumWords());
   memcpy(U.pVal, that.U.pVal, getNumWords() * APINT_WORD_SIZE);
 }
@@ -127,7 +126,7 @@ void APInt::reallocate(unsigned NewBitWidth) {
 
   // If we have an allocation, delete it.
   if (!isSingleWord())
-    delete [] U.pVal;
+    delete[] U.pVal;
 
   // Update BitWidth.
   BitWidth = NewBitWidth;
@@ -153,7 +152,7 @@ void APInt::assignSlowCase(const APInt &RHS) {
 }
 
 /// This method 'profiles' an APInt for use with FoldingSet.
-void APInt::Profile(FoldingSetNodeID& ID) const {
+void APInt::Profile(FoldingSetNodeID &ID) const {
   ID.AddInteger(BitWidth);
 
   if (isSingleWord()) {
@@ -175,7 +174,7 @@ bool APInt::isAligned(Align A) const {
 }
 
 /// Prefix increment operator. Increments the APInt by one.
-APInt& APInt::operator++() {
+APInt &APInt::operator++() {
   if (isSingleWord())
     ++U.VAL;
   else
@@ -184,7 +183,7 @@ APInt& APInt::operator++() {
 }
 
 /// Prefix decrement operator. Decrements the APInt by one.
-APInt& APInt::operator--() {
+APInt &APInt::operator--() {
   if (isSingleWord())
     --U.VAL;
   else
@@ -195,7 +194,7 @@ APInt& APInt::operator--() {
 /// Adds the RHS APInt to this APInt.
 /// @returns this, after addition of RHS.
 /// Addition assignment operator.
-APInt& APInt::operator+=(const APInt& RHS) {
+APInt &APInt::operator+=(const APInt &RHS) {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord())
     U.VAL += RHS.U.VAL;
@@ -204,7 +203,7 @@ APInt& APInt::operator+=(const APInt& RHS) {
   return clearUnusedBits();
 }
 
-APInt& APInt::operator+=(uint64_t RHS) {
+APInt &APInt::operator+=(uint64_t RHS) {
   if (isSingleWord())
     U.VAL += RHS;
   else
@@ -215,7 +214,7 @@ APInt& APInt::operator+=(uint64_t RHS) {
 /// Subtracts the RHS APInt from this APInt
 /// @returns this, after subtraction
 /// Subtraction assignment operator.
-APInt& APInt::operator-=(const APInt& RHS) {
+APInt &APInt::operator-=(const APInt &RHS) {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord())
     U.VAL -= RHS.U.VAL;
@@ -224,7 +223,7 @@ APInt& APInt::operator-=(const APInt& RHS) {
   return clearUnusedBits();
 }
 
-APInt& APInt::operator-=(uint64_t RHS) {
+APInt &APInt::operator-=(uint64_t RHS) {
   if (isSingleWord())
     U.VAL -= RHS;
   else
@@ -232,7 +231,7 @@ APInt& APInt::operator-=(uint64_t RHS) {
   return clearUnusedBits();
 }
 
-APInt APInt::operator*(const APInt& RHS) const {
+APInt APInt::operator*(const APInt &RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
   if (isSingleWord())
     return APInt(BitWidth, U.VAL * RHS.U.VAL, /*isSigned=*/false,
@@ -267,7 +266,7 @@ APInt &APInt::operator*=(const APInt &RHS) {
   return *this;
 }
 
-APInt& APInt::operator*=(uint64_t RHS) {
+APInt &APInt::operator*=(uint64_t RHS) {
   if (isSingleWord()) {
     U.VAL *= RHS;
   } else {
@@ -281,7 +280,7 @@ bool APInt::equalSlowCase(const APInt &RHS) const {
   return std::equal(U.pVal, U.pVal + getNumWords(), RHS.U.pVal);
 }
 
-int APInt::compare(const APInt& RHS) const {
+int APInt::compare(const APInt &RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
   if (isSingleWord())
     return U.VAL < RHS.U.VAL ? -1 : U.VAL > RHS.U.VAL;
@@ -289,7 +288,7 @@ int APInt::compare(const APInt& RHS) const {
   return tcCompare(U.pVal, RHS.U.pVal, getNumWords());
 }
 
-int APInt::compareSigned(const APInt& RHS) const {
+int APInt::compareSigned(const APInt &RHS) const {
   assert(BitWidth == RHS.BitWidth && "Bit widths must be same for comparison");
   if (isSingleWord()) {
     int64_t lhsSext = SignExtend64(U.VAL, BitWidth);
@@ -425,7 +424,8 @@ void APInt::insertBits(const APInt &subBits, unsigned bitPosition) {
     setBitVal(bitPosition + i, subBits[i]);
 }
 
-void APInt::insertBits(uint64_t subBits, unsigned bitPosition, unsigned numBits) {
+void APInt::insertBits(uint64_t subBits, unsigned bitPosition,
+                       unsigned numBits) {
   uint64_t maskBits = maskTrailingOnes<uint64_t>(numBits);
   subBits &= maskBits;
   if (isSingleWord()) {
@@ -443,7 +443,8 @@ void APInt::insertBits(uint64_t subBits, unsigned bitPosition, unsigned numBits)
     return;
   }
 
-  static_assert(8 * sizeof(WordType) <= 64, "This code assumes only two words affected");
+  static_assert(8 * sizeof(WordType) <= 64,
+                "This code assumes only two words affected");
   unsigned wordBits = 8 * sizeof(WordType);
   U.pVal[loWord] &= ~(maskBits << loBit);
   U.pVal[loWord] |= subBits << loBit;
@@ -570,7 +571,6 @@ unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
     assert(slen && "String is only a sign, needs a value.");
   }
 
-
   // Convert to the actual binary value.
   APInt tmp(sufficient, StringRef(p, slen), radix);
 
@@ -633,7 +633,7 @@ APInt APInt::getSplat(unsigned NewLen, const APInt &V) {
 
 unsigned APInt::countLeadingZerosSlowCase() const {
   unsigned Count = 0;
-  for (int i = getNumWords()-1; i >= 0; --i) {
+  for (int i = getNumWords() - 1; i >= 0; --i) {
     uint64_t V = U.pVal[i];
     if (V == 0)
       Count += APINT_BITS_PER_WORD;
@@ -770,11 +770,14 @@ APInt APInt::reverseBits() const {
 
 APInt llvm::APIntOps::GreatestCommonDivisor(APInt A, APInt B) {
   // Fast-path a common case.
-  if (A == B) return A;
+  if (A == B)
+    return A;
 
   // Corner cases: if either operand is zero, the other is the gcd.
-  if (!A) return B;
-  if (!B) return A;
+  if (!A)
+    return B;
+  if (!B)
+    return A;
 
   // Count common powers of 2 and remove all other powers of 2.
   unsigned Pow2;
@@ -829,8 +832,8 @@ APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
 
   // If the exponent doesn't shift all bits out of the mantissa
   if (exp < 52)
-    return isNeg ? -APInt(width, mantissa >> (52 - exp)) :
-                    APInt(width, mantissa >> (52 - exp));
+    return isNeg ? -APInt(width, mantissa >> (52 - exp))
+                 : APInt(width, mantissa >> (52 - exp));
 
   // If the client didn't provide enough bits for us to shift the mantissa into
   // then the result is undefined, just return 0
@@ -853,7 +856,8 @@ APInt llvm::APIntOps::RoundDoubleToAPInt(double Double, unsigned width) {
 double APInt::roundToDouble(bool isSigned) const {
 
   // Handle the simple case where the value is contained in one uint64_t.
-  // It is wrong to optimize getWord(0) to VAL; there might be more than one word.
+  // It is wrong to optimize getWord(0) to VAL; there might be more than one
+  // word.
   if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) {
     if (isSigned) {
       int64_t sext = SignExtend64(getWord(0), BitWidth);
@@ -863,7 +867,7 @@ double APInt::roundToDouble(bool isSigned) const {
   }
 
   // Determine if the value is negative.
-  bool isNeg = isSigned ? (*this)[BitWidth-1] : false;
+  bool isNeg = isSigned ? (*this)[BitWidth - 1] : false;
 
   // Construct the absolute value if we're negative.
   APInt Tmp(isNeg ? -(*this) : (*this));
@@ -888,7 +892,7 @@ double APInt::roundToDouble(bool isSigned) const {
   // Number of bits in mantissa is 52. To obtain the mantissa value, we must
   // extract the high 52 bits from the correct words in pVal.
   uint64_t mantissa;
-  unsigned hiWord = whichWord(n-1);
+  unsigned hiWord = whichWord(n - 1);
   if (hiWord == 0) {
     mantissa = Tmp.U.pVal[0];
     if (n > 52)
@@ -896,7 +900,7 @@ double APInt::roundToDouble(bool isSigned) const {
   } else {
     assert(hiWord > 0 && "huh?");
     uint64_t hibits = Tmp.U.pVal[hiWord] << (52 - n % APINT_BITS_PER_WORD);
-    uint64_t lobits = Tmp.U.pVal[hiWord-1] >> (11 + n % APINT_BITS_PER_WORD);
+    uint64_t lobits = Tmp.U.pVal[hiWord - 1] >> (11 + n % APINT_BITS_PER_WORD);
     mantissa = hibits | lobits;
   }
 
@@ -1052,8 +1056,9 @@ void APInt::ashrSlowCase(unsigned ShiftAmt) {
     } else {
       // Move the words containing significant bits.
       for (unsigned i = 0; i != WordsToMove - 1; ++i)
-        U.pVal[i] = (U.pVal[i + WordShift] >> BitShift) |
-                    (U.pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift));
+        U.pVal[i] =
+            (U.pVal[i + WordShift] >> BitShift) |
+            (U.pVal[i + WordShift + 1] << (APINT_BITS_PER_WORD - BitShift));
 
       // Handle the last word which has no high bits to copy. Use an arithmetic
       // shift to preserve the sign bit.
@@ -1179,15 +1184,14 @@ APInt APInt::sqrt() const {
   // rounding errors in libc sqrt for small values.
   if (magnitude <= 5) {
     static const uint8_t results[32] = {
-      /*     0 */ 0,
-      /*  1- 2 */ 1, 1,
-      /*  3- 6 */ 2, 2, 2, 2,
-      /*  7-12 */ 3, 3, 3, 3, 3, 3,
-      /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
-      /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-      /*    31 */ 6
-    };
-    return APInt(BitWidth, results[ (isSingleWord() ? U.VAL : U.pVal[0]) ]);
+        /*     0 */ 0,
+        /*  1- 2 */ 1, 1,
+        /*  3- 6 */ 2, 2, 2, 2,
+        /*  7-12 */ 3, 3, 3, 3, 3, 3,
+        /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4,
+        /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+        /*    31 */ 6};
+    return APInt(BitWidth, results[(isSingleWord() ? U.VAL : U.pVal[0])]);
   }
 
   // If the magnitude of the value fits in less than 52 bits (the precision of
@@ -1195,9 +1199,9 @@ APInt APInt::sqrt() const {
   // libc sqrt function which will probably use a hardware sqrt computation.
   // This should be faster than the algorithm below.
   if (magnitude < 52) {
-    return APInt(BitWidth,
-                 uint64_t(::round(::sqrt(double(isSingleWord() ? U.VAL
-                                                               : U.pVal[0])))));
+    return APInt(
+        BitWidth,
+        uint64_t(::round(::sqrt(double(isSingleWord() ? U.VAL : U.pVal[0])))));
   }
 
   // Okay, all the short cuts are exhausted. We must compute it. The following
@@ -1233,7 +1237,7 @@ APInt APInt::sqrt() const {
   // floating point representation after 192 bits. There are no discrepancies
   // between this algorithm and pari/gp for bit widths < 192 bits.
   APInt square(x_old * x_old);
-  APInt nextSquare((x_old + 1) * (x_old +1));
+  APInt nextSquare((x_old + 1) * (x_old + 1));
   if (this->ult(square))
     return x_old;
   assert(this->ule(nextSquare) && "Error in APInt::sqrt computation");
@@ -1261,13 +1265,13 @@ APInt APInt::multiplicativeInverse() const {
 /// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The
 /// variables here have the same names as in the algorithm. Comments explain
 /// the algorithm and any deviation from it.
-static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
+static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t *r,
                      unsigned m, unsigned n) {
   assert(u && "Must provide dividend");
   assert(v && "Must provide divisor");
   assert(q && "Must provide quotient");
   assert(u != v && u != q && v != q && "Must use different memory");
-  assert(n>1 && "n must be > 1");
+  assert(n > 1 && "n must be > 1");
 
   // b denotes the base of the number system. In our case b is 2^32.
   const uint64_t b = uint64_t(1) << 32;
@@ -1277,7 +1281,9 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
 #ifdef KNUTH_DEBUG
 #define DEBUG_KNUTH(X) LLVM_DEBUG(X)
 #else
-#define DEBUG_KNUTH(X) do {} while(false)
+#define DEBUG_KNUTH(X)                                                         \
+  do {                                                                         \
+  } while (false)
 #endif
 
   DEBUG_KNUTH(dbgs() << "KnuthDiv: m=" << m << " n=" << n << '\n');
@@ -1298,7 +1304,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
   uint32_t v_carry = 0;
   uint32_t u_carry = 0;
   if (shift) {
-    for (unsigned i = 0; i < m+n; ++i) {
+    for (unsigned i = 0; i < m + n; ++i) {
       uint32_t u_tmp = u[i] >> (32 - shift);
       u[i] = (u[i] << shift) | u_carry;
       u_carry = u_tmp;
@@ -1309,7 +1315,7 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
       v_carry = v_tmp;
     }
   }
-  u[m+n] = u_carry;
+  u[m + n] = u_carry;
 
   DEBUG_KNUTH(dbgs() << "KnuthDiv:   normal:");
   DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
@@ -1329,14 +1335,14 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
     // on v[n-2] determines at high speed most of the cases in which the trial
     // value qp is one too large, and it eliminates all cases where qp is two
     // too large.
-    uint64_t dividend = Make_64(u[j+n], u[j+n-1]);
+    uint64_t dividend = Make_64(u[j + n], u[j + n - 1]);
     DEBUG_KNUTH(dbgs() << "KnuthDiv: dividend == " << dividend << '\n');
-    uint64_t qp = dividend / v[n-1];
-    uint64_t rp = dividend % v[n-1];
-    if (qp == b || qp*v[n-2] > b*rp + u[j+n-2]) {
+    uint64_t qp = dividend / v[n - 1];
+    uint64_t rp = dividend % v[n - 1];
+    if (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]) {
       qp--;
-      rp += v[n-1];
-      if (rp < b && (qp == b || qp*v[n-2] > b*rp + u[j+n-2]))
+      rp += v[n - 1];
+      if (rp < b && (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]))
         qp--;
     }
     DEBUG_KNUTH(dbgs() << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n');
@@ -1352,14 +1358,14 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
     int64_t borrow = 0;
     for (unsigned i = 0; i < n; ++i) {
       uint64_t p = uint64_t(qp) * uint64_t(v[i]);
-      int64_t subres = int64_t(u[j+i]) - borrow - Lo_32(p);
-      u[j+i] = Lo_32(subres);
+      int64_t subres = int64_t(u[j + i]) - borrow - Lo_32(p);
+      u[j + i] = Lo_32(subres);
       borrow = Hi_32(p) - Hi_32(subres);
       DEBUG_KNUTH(dbgs() << "KnuthDiv: u[j+i] = " << u[j + i]
-                        << ", borrow = " << borrow << '\n');
+                         << ", borrow = " << borrow << '\n');
     }
-    bool isNeg = u[j+n] < borrow;
-    u[j+n] -= Lo_32(borrow);
+    bool isNeg = u[j + n] < borrow;
+    u[j + n] -= Lo_32(borrow);
 
     DEBUG_KNUTH(dbgs() << "KnuthDiv: after subtraction:");
     DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
@@ -1378,11 +1384,11 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
       // since it cancels with the borrow that occurred in D4.
       bool carry = false;
       for (unsigned i = 0; i < n; i++) {
-        uint32_t limit = std::min(u[j+i],v[i]);
-        u[j+i] += v[i] + carry;
-        carry = u[j+i] < limit || (carry && u[j+i] == limit);
+        uint32_t limit = std::min(u[j + i], v[i]);
+        u[j + i] += v[i] + carry;
+        carry = u[j + i] < limit || (carry && u[j + i] == limit);
       }
-      u[j+n] += carry;
+      u[j + n] += carry;
     }
     DEBUG_KNUTH(dbgs() << "KnuthDiv: after correction:");
     DEBUG_KNUTH(for (int i = m + n; i >= 0; i--) dbgs() << " " << u[i]);
@@ -1405,13 +1411,13 @@ static void KnuthDiv(uint32_t *u, uint32_t *v, uint32_t *q, uint32_t* r,
     if (shift) {
       uint32_t carry = 0;
       DEBUG_KNUTH(dbgs() << "KnuthDiv: remainder:");
-      for (int i = n-1; i >= 0; i--) {
+      for (int i = n - 1; i >= 0; i--) {
         r[i] = (u[i] >> shift) | carry;
         carry = u[i] << (32 - shift);
         DEBUG_KNUTH(dbgs() << " " << r[i]);
       }
     } else {
-      for (int i = n-1; i >= 0; i--) {
+      for (int i = n - 1; i >= 0; i--) {
         r[i] = u[i];
         DEBUG_KNUTH(dbgs() << " " << r[i]);
       }
@@ -1442,31 +1448,31 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   uint32_t *V = nullptr;
   uint32_t *Q = nullptr;
   uint32_t *R = nullptr;
-  if ((Remainder?4:3)*n+2*m+1 <= 128) {
+  if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) {
     U = &SPACE[0];
-    V = &SPACE[m+n+1];
-    Q = &SPACE[(m+n+1) + n];
+    V = &SPACE[m + n + 1];
+    Q = &SPACE[(m + n + 1) + n];
     if (Remainder)
-      R = &SPACE[(m+n+1) + n + (m+n)];
+      R = &SPACE[(m + n + 1) + n + (m + n)];
   } else {
     U = new uint32_t[m + n + 1];
     V = new uint32_t[n];
-    Q = new uint32_t[m+n];
+    Q = new uint32_t[m + n];
     if (Remainder)
       R = new uint32_t[n];
   }
 
   // Initialize the dividend
-  memset(U, 0, (m+n+1)*sizeof(uint32_t));
+  memset(U, 0, (m + n + 1) * sizeof(uint32_t));
   for (unsigned i = 0; i < lhsWords; ++i) {
     uint64_t tmp = LHS[i];
     U[i * 2] = Lo_32(tmp);
     U[i * 2 + 1] = Hi_32(tmp);
   }
-  U[m+n] = 0; // this extra word is for "spill" in the Knuth algorithm.
+  U[m + n] = 0; // this extra word is for "spill" in the Knuth algorithm.
 
   // Initialize the divisor
-  memset(V, 0, (n)*sizeof(uint32_t));
+  memset(V, 0, (n) * sizeof(uint32_t));
   for (unsigned i = 0; i < rhsWords; ++i) {
     uint64_t tmp = RHS[i];
     V[i * 2] = Lo_32(tmp);
@@ -1474,7 +1480,7 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   }
 
   // initialize the quotient and remainder
-  memset(Q, 0, (m+n) * sizeof(uint32_t));
+  memset(Q, 0, (m + n) * sizeof(uint32_t));
   if (Remainder)
     memset(R, 0, n * sizeof(uint32_t));
 
@@ -1482,11 +1488,11 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   // the divisor. m is the number of words by which the dividend exceeds the
   // divisor (i.e. m+n is the length of the dividend). These sizes must not
   // contain any zero words or the Knuth algorithm fails.
-  for (unsigned i = n; i > 0 && V[i-1] == 0; i--) {
+  for (unsigned i = n; i > 0 && V[i - 1] == 0; i--) {
     n--;
     m++;
   }
-  for (unsigned i = m+n; i > 0 && U[i-1] == 0; i--)
+  for (unsigned i = m + n; i > 0 && U[i - 1] == 0; i--)
     m--;
 
   // If we're left with only a single word for the divisor, Knuth doesn't work
@@ -1526,21 +1532,21 @@ void APInt::divide(const WordType *LHS, unsigned lhsWords, const WordType *RHS,
   // If the caller wants the quotient
   if (Quotient) {
     for (unsigned i = 0; i < lhsWords; ++i)
-      Quotient[i] = Make_64(Q[i*2+1], Q[i*2]);
+      Quotient[i] = Make_64(Q[i * 2 + 1], Q[i * 2]);
   }
 
   // If the caller wants the remainder
   if (Remainder) {
     for (unsigned i = 0; i < rhsWords; ++i)
-      Remainder[i] = Make_64(R[i*2+1], R[i*2]);
+      Remainder[i] = Make_64(R[i * 2 + 1], R[i * 2]);
   }
 
   // Clean up the memory we allocated.
   ...
[truncated]

return new uint64_t[numWords]();
}

/// A utility function for allocating memory and checking for allocation
/// failure. The content is not zeroed.
inline static uint64_t* getMemory(unsigned numWords) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you've reformatted this file (and the tests). It's best only to format your changes, which can be done by disabling options such as "format on save" in your editor and using git clang-format HEAD~1 format only your changes. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants