summaryrefslogtreecommitdiff
path: root/lib/Support/APInt.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-08 17:12:57 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-08 17:12:57 +0000
commitc46e6a5940c50058e00c0c5f9123fd82e338d29a (patch)
tree89a719d723035c54a190b1f81d329834f1f93336 /lib/Support/APInt.cpp
parent148779df305667b6942fee7e758fdf81a6498f38 (diff)
Notes
Diffstat (limited to 'lib/Support/APInt.cpp')
-rw-r--r--lib/Support/APInt.cpp194
1 files changed, 49 insertions, 145 deletions
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index fa81b28cd083b..caa0691f92050 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -225,114 +225,17 @@ APInt& APInt::operator-=(uint64_t RHS) {
return clearUnusedBits();
}
-/// Multiplies an integer array, x, by a uint64_t integer and places the result
-/// into dest.
-/// @returns the carry out of the multiplication.
-/// @brief Multiply a multi-digit APInt by a single digit (64-bit) integer.
-static uint64_t mul_1(uint64_t dest[], uint64_t x[], unsigned len, uint64_t y) {
- // Split y into high 32-bit part (hy) and low 32-bit part (ly)
- uint64_t ly = y & 0xffffffffULL, hy = y >> 32;
- uint64_t carry = 0;
-
- // For each digit of x.
- for (unsigned i = 0; i < len; ++i) {
- // Split x into high and low words
- uint64_t lx = x[i] & 0xffffffffULL;
- uint64_t hx = x[i] >> 32;
- // hasCarry - A flag to indicate if there is a carry to the next digit.
- // hasCarry == 0, no carry
- // hasCarry == 1, has carry
- // hasCarry == 2, no carry and the calculation result == 0.
- uint8_t hasCarry = 0;
- dest[i] = carry + lx * ly;
- // Determine if the add above introduces carry.
- hasCarry = (dest[i] < carry) ? 1 : 0;
- carry = hx * ly + (dest[i] >> 32) + (hasCarry ? (1ULL << 32) : 0);
- // The upper limit of carry can be (2^32 - 1)(2^32 - 1) +
- // (2^32 - 1) + 2^32 = 2^64.
- hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
-
- carry += (lx * hy) & 0xffffffffULL;
- dest[i] = (carry << 32) | (dest[i] & 0xffffffffULL);
- carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) +
- (carry >> 32) + ((lx * hy) >> 32) + hx * hy;
- }
- return carry;
-}
-
-/// Multiplies integer array x by integer array y and stores the result into
-/// the integer array dest. Note that dest's size must be >= xlen + ylen.
-/// @brief Generalized multiplication of integer arrays.
-static void mul(uint64_t dest[], uint64_t x[], unsigned xlen, uint64_t y[],
- unsigned ylen) {
- dest[xlen] = mul_1(dest, x, xlen, y[0]);
- for (unsigned i = 1; i < ylen; ++i) {
- uint64_t ly = y[i] & 0xffffffffULL, hy = y[i] >> 32;
- uint64_t carry = 0, lx = 0, hx = 0;
- for (unsigned j = 0; j < xlen; ++j) {
- lx = x[j] & 0xffffffffULL;
- hx = x[j] >> 32;
- // hasCarry - A flag to indicate if has carry.
- // hasCarry == 0, no carry
- // hasCarry == 1, has carry
- // hasCarry == 2, no carry and the calculation result == 0.
- uint8_t hasCarry = 0;
- uint64_t resul = carry + lx * ly;
- hasCarry = (resul < carry) ? 1 : 0;
- carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + (resul >> 32);
- hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0);
-
- carry += (lx * hy) & 0xffffffffULL;
- resul = (carry << 32) | (resul & 0xffffffffULL);
- dest[i+j] += resul;
- carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0)+
- (carry >> 32) + (dest[i+j] < resul ? 1 : 0) +
- ((lx * hy) >> 32) + hx * hy;
- }
- dest[i+xlen] = carry;
- }
-}
-
-APInt& APInt::operator*=(const APInt& RHS) {
+APInt APInt::operator*(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord()) {
- U.VAL *= RHS.U.VAL;
- clearUnusedBits();
- return *this;
- }
-
- // Get some bit facts about LHS and check for zero
- unsigned lhsBits = getActiveBits();
- unsigned lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1;
- if (!lhsWords)
- // 0 * X ===> 0
- return *this;
-
- // Get some bit facts about RHS and check for zero
- unsigned rhsBits = RHS.getActiveBits();
- unsigned rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1;
- if (!rhsWords) {
- // X * 0 ===> 0
- clearAllBits();
- return *this;
- }
-
- // Allocate space for the result
- unsigned destWords = rhsWords + lhsWords;
- uint64_t *dest = getMemory(destWords);
+ if (isSingleWord())
+ return APInt(BitWidth, U.VAL * RHS.U.VAL);
- // Perform the long multiply
- mul(dest, U.pVal, lhsWords, RHS.U.pVal, rhsWords);
+ APInt Result(getMemory(getNumWords()), getBitWidth());
- // Copy result back into *this
- clearAllBits();
- unsigned wordsToCopy = destWords >= getNumWords() ? getNumWords() : destWords;
- memcpy(U.pVal, dest, wordsToCopy * APINT_WORD_SIZE);
- clearUnusedBits();
+ tcMultiply(Result.U.pVal, U.pVal, RHS.U.pVal, getNumWords());
- // delete dest array and return
- delete[] dest;
- return *this;
+ Result.clearUnusedBits();
+ return Result;
}
void APInt::AndAssignSlowCase(const APInt& RHS) {
@@ -347,13 +250,20 @@ void APInt::XorAssignSlowCase(const APInt& RHS) {
tcXor(U.pVal, RHS.U.pVal, getNumWords());
}
-APInt APInt::operator*(const APInt& RHS) const {
+APInt& APInt::operator*=(const APInt& RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- if (isSingleWord())
- return APInt(BitWidth, U.VAL * RHS.U.VAL);
- APInt Result(*this);
- Result *= RHS;
- return Result;
+ *this = *this * RHS;
+ return *this;
+}
+
+APInt& APInt::operator*=(uint64_t RHS) {
+ if (isSingleWord()) {
+ U.VAL *= RHS;
+ } else {
+ unsigned NumWords = getNumWords();
+ tcMultiplyPart(U.pVal, U.pVal, RHS, 0, NumWords, NumWords, false);
+ }
+ return clearUnusedBits();
}
bool APInt::EqualSlowCase(const APInt& RHS) const {
@@ -1932,10 +1842,6 @@ void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
// Figure out if we can shift instead of multiply
unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0);
- // Set up an APInt for the radix multiplier outside the loop so we don't
- // constantly construct/destruct it.
- APInt apradix(getBitWidth(), radix);
-
// Enter digit traversal loop
for (StringRef::iterator e = str.end(); p != e; ++p) {
unsigned digit = getDigit(*p, radix);
@@ -1946,7 +1852,7 @@ void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
if (shift)
*this <<= shift;
else
- *this *= apradix;
+ *this *= radix;
}
// Add in the digit we just interpreted
@@ -2346,10 +2252,9 @@ int APInt::tcMultiplyPart(WordType *dst, const WordType *src,
assert(dstParts <= srcParts + 1);
/* N loops; minimum of dstParts and srcParts. */
- unsigned n = dstParts < srcParts ? dstParts: srcParts;
+ unsigned n = std::min(dstParts, srcParts);
- unsigned i;
- for (i = 0; i < n; i++) {
+ for (unsigned i = 0; i < n; i++) {
WordType low, mid, high, srcPart;
/* [ LOW, HIGH ] = MULTIPLIER * SRC[i] + DST[i] + CARRY.
@@ -2400,27 +2305,27 @@ int APInt::tcMultiplyPart(WordType *dst, const WordType *src,
carry = high;
}
- if (i < dstParts) {
+ if (srcParts < dstParts) {
/* Full multiplication, there is no overflow. */
- assert(i + 1 == dstParts);
- dst[i] = carry;
- return 0;
- } else {
- /* We overflowed if there is carry. */
- if (carry)
- return 1;
-
- /* We would overflow if any significant unwritten parts would be
- non-zero. This is true if any remaining src parts are non-zero
- and the multiplier is non-zero. */
- if (multiplier)
- for (; i < srcParts; i++)
- if (src[i])
- return 1;
-
- /* We fitted in the narrow destination. */
+ assert(srcParts + 1 == dstParts);
+ dst[srcParts] = carry;
return 0;
}
+
+ /* We overflowed if there is carry. */
+ if (carry)
+ return 1;
+
+ /* We would overflow if any significant unwritten parts would be
+ non-zero. This is true if any remaining src parts are non-zero
+ and the multiplier is non-zero. */
+ if (multiplier)
+ for (unsigned i = dstParts; i < srcParts; i++)
+ if (src[i])
+ return 1;
+
+ /* We fitted in the narrow destination. */
+ return 0;
}
/* DST = LHS * RHS, where DST has the same width as the operands and
@@ -2449,20 +2354,19 @@ unsigned APInt::tcFullMultiply(WordType *dst, const WordType *lhs,
const WordType *rhs, unsigned lhsParts,
unsigned rhsParts) {
/* Put the narrower number on the LHS for less loops below. */
- if (lhsParts > rhsParts) {
+ if (lhsParts > rhsParts)
return tcFullMultiply (dst, rhs, lhs, rhsParts, lhsParts);
- } else {
- assert(dst != lhs && dst != rhs);
- tcSet(dst, 0, rhsParts);
+ assert(dst != lhs && dst != rhs);
- for (unsigned i = 0; i < lhsParts; i++)
- tcMultiplyPart(&dst[i], rhs, lhs[i], 0, rhsParts, rhsParts + 1, true);
+ tcSet(dst, 0, rhsParts);
- unsigned n = lhsParts + rhsParts;
+ for (unsigned i = 0; i < lhsParts; i++)
+ tcMultiplyPart(&dst[i], rhs, lhs[i], 0, rhsParts, rhsParts + 1, true);
- return n - (dst[n - 1] == 0);
- }
+ unsigned n = lhsParts + rhsParts;
+
+ return n - (dst[n - 1] == 0);
}
/* If RHS is zero LHS and REMAINDER are left unchanged, return one.