Clean up the divide and remainder logic a bit (exit early). Use more
meaningful variable names. Add comments to document the flow. llvm-svn: 34362
This commit is contained in:
parent
3ae936ce69
commit
3986776fbd
|
@ -213,7 +213,8 @@ static void div(unsigned zds[], unsigned nx, unsigned y[], unsigned ny) {
|
||||||
// Knuth's j == our nx-j.
|
// Knuth's j == our nx-j.
|
||||||
// Knuth's u[j:j+n] == our zds[j:j-ny].
|
// Knuth's u[j:j+n] == our zds[j:j-ny].
|
||||||
unsigned qhat; // treated as unsigned
|
unsigned qhat; // treated as unsigned
|
||||||
if (zds[j] == y[ny-1]) qhat = -1U; // 0xffffffff
|
if (zds[j] == y[ny-1])
|
||||||
|
qhat = -1U; // 0xffffffff
|
||||||
else {
|
else {
|
||||||
uint64_t w = (((uint64_t)(zds[j])) << 32) +
|
uint64_t w = (((uint64_t)(zds[j])) << 32) +
|
||||||
((uint64_t)zds[j-1] & 0xffffffffL);
|
((uint64_t)zds[j-1] & 0xffffffffL);
|
||||||
|
@ -1137,76 +1138,100 @@ APInt APInt::shl(unsigned shiftAmt) const {
|
||||||
/// @brief Unsigned division function for APInt.
|
/// @brief Unsigned division function for APInt.
|
||||||
APInt APInt::udiv(const APInt& RHS) const {
|
APInt APInt::udiv(const APInt& RHS) const {
|
||||||
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
|
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
|
||||||
APInt API(*this);
|
|
||||||
unsigned first = RHS.getActiveBits();
|
// First, deal with the easy case
|
||||||
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
if (isSingleWord()) {
|
||||||
assert(ylen && "Divided by zero???");
|
assert(RHS.VAL != 0 && "Divide by zero?");
|
||||||
if (API.isSingleWord()) {
|
return APInt(BitWidth, VAL / RHS.VAL);
|
||||||
API.VAL = RHS.isSingleWord() ? (API.VAL / RHS.VAL) :
|
}
|
||||||
(ylen > 1 ? 0 : API.VAL / RHS.pVal[0]);
|
|
||||||
} else {
|
// Make a temporary to hold the result
|
||||||
unsigned first2 = API.getActiveBits();
|
APInt Result(*this);
|
||||||
unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1;
|
|
||||||
if (!xlen)
|
// Get some facts about the LHS and RHS number of bits and words
|
||||||
return API;
|
unsigned rhsBits = RHS.getActiveBits();
|
||||||
else if (xlen < ylen || API.ult(RHS))
|
unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
assert(rhsWords && "Divided by zero???");
|
||||||
else if (API == RHS) {
|
unsigned lhsBits = Result.getActiveBits();
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1);
|
||||||
API.pVal[0] = 1;
|
|
||||||
} else if (xlen == 1)
|
// Deal with some degenerate cases
|
||||||
API.pVal[0] /= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
if (!lhsWords)
|
||||||
|
return Result; // 0 / X == 0
|
||||||
|
else if (lhsWords < rhsWords || Result.ult(RHS))
|
||||||
|
// X / Y with X < Y == 0
|
||||||
|
memset(Result.pVal, 0, Result.getNumWords() * 8);
|
||||||
|
else if (Result == RHS) {
|
||||||
|
// X / X == 1
|
||||||
|
memset(Result.pVal, 0, Result.getNumWords() * 8);
|
||||||
|
Result.pVal[0] = 1;
|
||||||
|
} else if (lhsWords == 1)
|
||||||
|
// All high words are zero, just use native divide
|
||||||
|
Result.pVal[0] /= RHS.pVal[0];
|
||||||
else {
|
else {
|
||||||
|
// Compute it the hard way ..
|
||||||
APInt X(BitWidth, 0);
|
APInt X(BitWidth, 0);
|
||||||
APInt Y(BitWidth, 0);
|
APInt Y(BitWidth, 0);
|
||||||
if (unsigned nshift = 63 - (first - 1) % 64) {
|
if (unsigned nshift = 63 - ((rhsBits - 1) % 64 )) {
|
||||||
Y = APIntOps::shl(RHS, nshift);
|
Y = APIntOps::shl(RHS, nshift);
|
||||||
X = APIntOps::shl(API, nshift);
|
X = APIntOps::shl(Result, nshift);
|
||||||
++xlen;
|
++lhsWords;
|
||||||
}
|
}
|
||||||
div((unsigned*)X.pVal, xlen*2-1,
|
div((unsigned*)X.pVal, lhsWords * 2 - 1, (unsigned*)Y.pVal, rhsWords*2);
|
||||||
(unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);
|
memset(Result.pVal, 0, Result.getNumWords() * 8);
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
memcpy(Result.pVal, X.pVal + rhsWords, (lhsWords - rhsWords) * 8);
|
||||||
memcpy(API.pVal, X.pVal + ylen, (xlen - ylen) * 8);
|
|
||||||
}
|
}
|
||||||
}
|
return Result;
|
||||||
return API;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsigned remainder operation on APInt.
|
/// Unsigned remainder operation on APInt.
|
||||||
/// @brief Function for unsigned remainder operation.
|
/// @brief Function for unsigned remainder operation.
|
||||||
APInt APInt::urem(const APInt& RHS) const {
|
APInt APInt::urem(const APInt& RHS) const {
|
||||||
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
|
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
|
||||||
APInt API(*this);
|
if (isSingleWord()) {
|
||||||
unsigned first = RHS.getActiveBits();
|
assert(RHS.VAL != 0 && "Remainder by zero?");
|
||||||
unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
|
return APInt(BitWidth, VAL % RHS.VAL);
|
||||||
assert(ylen && "Performing remainder operation by zero ???");
|
}
|
||||||
if (API.isSingleWord()) {
|
|
||||||
API.VAL = RHS.isSingleWord() ? (API.VAL % RHS.VAL) :
|
// Make a temporary to hold the result
|
||||||
(ylen > 1 ? API.VAL : API.VAL % RHS.pVal[0]);
|
APInt Result(*this);
|
||||||
} else {
|
|
||||||
unsigned first2 = API.getActiveBits();
|
// Get some facts about the RHS
|
||||||
unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1;
|
unsigned rhsBits = RHS.getActiveBits();
|
||||||
if (!xlen || xlen < ylen || API.ult(RHS))
|
unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
|
||||||
return API;
|
assert(rhsWords && "Performing remainder operation by zero ???");
|
||||||
else if (API == RHS)
|
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
// Get some facts about the LHS
|
||||||
else if (xlen == 1)
|
unsigned lhsBits = Result.getActiveBits();
|
||||||
API.pVal[0] %= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
|
unsigned lhsWords = !lhsBits ? 0 : (Result.whichWord(lhsBits - 1) + 1);
|
||||||
|
|
||||||
|
// Check the degenerate cases
|
||||||
|
if (lhsWords == 0)
|
||||||
|
// 0 % Y == 0
|
||||||
|
memset(Result.pVal, 0, Result.getNumWords() * 8);
|
||||||
|
else if (lhsWords < rhsWords || Result.ult(RHS))
|
||||||
|
// X % Y == X iff X < Y
|
||||||
|
return Result;
|
||||||
|
else if (Result == RHS)
|
||||||
|
// X % X == 0;
|
||||||
|
memset(Result.pVal, 0, Result.getNumWords() * 8);
|
||||||
|
else if (lhsWords == 1)
|
||||||
|
// All high words are zero, just use native remainder
|
||||||
|
Result.pVal[0] %= RHS.pVal[0];
|
||||||
else {
|
else {
|
||||||
APInt X((xlen+1)*64, 0), Y(ylen*64, 0);
|
// Do it the hard way
|
||||||
unsigned nshift = 63 - (first - 1) % 64;
|
APInt X((lhsWords+1)*64, 0);
|
||||||
|
APInt Y(rhsWords*64, 0);
|
||||||
|
unsigned nshift = 63 - (rhsBits - 1) % 64;
|
||||||
if (nshift) {
|
if (nshift) {
|
||||||
APIntOps::shl(Y, nshift);
|
APIntOps::shl(Y, nshift);
|
||||||
APIntOps::shl(X, nshift);
|
APIntOps::shl(X, nshift);
|
||||||
}
|
}
|
||||||
div((unsigned*)X.pVal, xlen*2-1,
|
div((unsigned*)X.pVal, rhsWords*2-1, (unsigned*)Y.pVal, rhsWords*2);
|
||||||
(unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);
|
memset(Result.pVal, 0, Result.getNumWords() * 8);
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
for (unsigned i = 0; i < rhsWords-1; ++i)
|
||||||
for (unsigned i = 0; i < ylen-1; ++i)
|
Result.pVal[i] = (X.pVal[i] >> nshift) | (X.pVal[i+1] << (64 - nshift));
|
||||||
API.pVal[i] = (X.pVal[i] >> nshift) | (X.pVal[i+1] << (64 - nshift));
|
Result.pVal[rhsWords-1] = X.pVal[rhsWords-1] >> nshift;
|
||||||
API.pVal[ylen-1] = X.pVal[ylen-1] >> nshift;
|
|
||||||
}
|
}
|
||||||
}
|
return Result;
|
||||||
return API;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue