[llvm-commits] CVS: llvm/lib/Support/APInt.cpp
Reid Spencer
reid at x10sys.com
Fri Feb 16 18:07:24 PST 2007
Changes in directory llvm/lib/Support:
APInt.cpp updated: 1.13 -> 1.14
---
Log message:
Clean up the divide and remainder logic a bit (exit early). Use more
meaningful variable names. Add comments to document the flow.
---
Diffs of the changes: (+90 -65)
APInt.cpp | 155 ++++++++++++++++++++++++++++++++++++--------------------------
1 files changed, 90 insertions(+), 65 deletions(-)
Index: llvm/lib/Support/APInt.cpp
diff -u llvm/lib/Support/APInt.cpp:1.13 llvm/lib/Support/APInt.cpp:1.14
--- llvm/lib/Support/APInt.cpp:1.13 Fri Feb 16 18:18:01 2007
+++ llvm/lib/Support/APInt.cpp Fri Feb 16 20:07:07 2007
@@ -213,7 +213,8 @@
// Knuth's j == our nx-j.
// Knuth's u[j:j+n] == our zds[j:j-ny].
unsigned qhat; // treated as unsigned
- if (zds[j] == y[ny-1]) qhat = -1U; // 0xffffffff
+ if (zds[j] == y[ny-1])
+ qhat = -1U; // 0xffffffff
else {
uint64_t w = (((uint64_t)(zds[j])) << 32) +
((uint64_t)zds[j-1] & 0xffffffffL);
@@ -1137,76 +1138,100 @@
/// @brief Unsigned division function for APInt.
APInt APInt::udiv(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- APInt API(*this);
- unsigned first = RHS.getActiveBits();
- unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
- assert(ylen && "Divided by zero???");
- if (API.isSingleWord()) {
- API.VAL = RHS.isSingleWord() ? (API.VAL / RHS.VAL) :
- (ylen > 1 ? 0 : API.VAL / RHS.pVal[0]);
- } else {
- unsigned first2 = API.getActiveBits();
- unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1;
- if (!xlen)
- return API;
- else if (xlen < ylen || API.ult(RHS))
- memset(API.pVal, 0, API.getNumWords() * 8);
- else if (API == RHS) {
- memset(API.pVal, 0, API.getNumWords() * 8);
- API.pVal[0] = 1;
- } else if (xlen == 1)
- API.pVal[0] /= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
- else {
- APInt X(BitWidth, 0);
- APInt Y(BitWidth, 0);
- if (unsigned nshift = 63 - (first - 1) % 64) {
- Y = APIntOps::shl(RHS, nshift);
- X = APIntOps::shl(API, nshift);
- ++xlen;
- }
- div((unsigned*)X.pVal, xlen*2-1,
- (unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);
- memset(API.pVal, 0, API.getNumWords() * 8);
- memcpy(API.pVal, X.pVal + ylen, (xlen - ylen) * 8);
- }
+
+ // First, deal with the easy case
+ if (isSingleWord()) {
+ assert(RHS.VAL != 0 && "Divide by zero?");
+ return APInt(BitWidth, VAL / RHS.VAL);
}
- return API;
+
+ // Make a temporary to hold the result
+ APInt Result(*this);
+
+ // Get some facts about the LHS and RHS number of bits and words
+ unsigned rhsBits = RHS.getActiveBits();
+ unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
+ assert(rhsWords && "Divided by zero???");
+ unsigned lhsBits = Result.getActiveBits();
+ unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1);
+
+ // Deal with some degenerate cases
+ 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 {
+ // Compute it the hard way ..
+ APInt X(BitWidth, 0);
+ APInt Y(BitWidth, 0);
+ if (unsigned nshift = 63 - ((rhsBits - 1) % 64 )) {
+ Y = APIntOps::shl(RHS, nshift);
+ X = APIntOps::shl(Result, nshift);
+ ++lhsWords;
+ }
+ div((unsigned*)X.pVal, lhsWords * 2 - 1, (unsigned*)Y.pVal, rhsWords*2);
+ memset(Result.pVal, 0, Result.getNumWords() * 8);
+ memcpy(Result.pVal, X.pVal + rhsWords, (lhsWords - rhsWords) * 8);
+ }
+ return Result;
}
/// Unsigned remainder operation on APInt.
/// @brief Function for unsigned remainder operation.
APInt APInt::urem(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
- APInt API(*this);
- unsigned first = RHS.getActiveBits();
- unsigned ylen = !first ? 0 : APInt::whichWord(first - 1) + 1;
- assert(ylen && "Performing remainder operation by zero ???");
- if (API.isSingleWord()) {
- API.VAL = RHS.isSingleWord() ? (API.VAL % RHS.VAL) :
- (ylen > 1 ? API.VAL : API.VAL % RHS.pVal[0]);
- } else {
- unsigned first2 = API.getActiveBits();
- unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1;
- if (!xlen || xlen < ylen || API.ult(RHS))
- return API;
- else if (API == RHS)
- memset(API.pVal, 0, API.getNumWords() * 8);
- else if (xlen == 1)
- API.pVal[0] %= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0];
- else {
- APInt X((xlen+1)*64, 0), Y(ylen*64, 0);
- unsigned nshift = 63 - (first - 1) % 64;
- if (nshift) {
- APIntOps::shl(Y, nshift);
- APIntOps::shl(X, nshift);
- }
- div((unsigned*)X.pVal, xlen*2-1,
- (unsigned*)(Y.isSingleWord() ? &Y.VAL : Y.pVal), ylen*2);
- memset(API.pVal, 0, API.getNumWords() * 8);
- for (unsigned i = 0; i < ylen-1; ++i)
- API.pVal[i] = (X.pVal[i] >> nshift) | (X.pVal[i+1] << (64 - nshift));
- API.pVal[ylen-1] = X.pVal[ylen-1] >> nshift;
- }
+ if (isSingleWord()) {
+ assert(RHS.VAL != 0 && "Remainder by zero?");
+ return APInt(BitWidth, VAL % RHS.VAL);
}
- return API;
+
+ // Make a temporary to hold the result
+ APInt Result(*this);
+
+ // Get some facts about the RHS
+ unsigned rhsBits = RHS.getActiveBits();
+ unsigned rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
+ assert(rhsWords && "Performing remainder operation by zero ???");
+
+ // Get some facts about the LHS
+ unsigned lhsBits = Result.getActiveBits();
+ 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 {
+ // Do it the hard way
+ APInt X((lhsWords+1)*64, 0);
+ APInt Y(rhsWords*64, 0);
+ unsigned nshift = 63 - (rhsBits - 1) % 64;
+ if (nshift) {
+ APIntOps::shl(Y, nshift);
+ APIntOps::shl(X, nshift);
+ }
+ div((unsigned*)X.pVal, rhsWords*2-1, (unsigned*)Y.pVal, rhsWords*2);
+ memset(Result.pVal, 0, Result.getNumWords() * 8);
+ for (unsigned i = 0; i < rhsWords-1; ++i)
+ Result.pVal[i] = (X.pVal[i] >> nshift) | (X.pVal[i+1] << (64 - nshift));
+ Result.pVal[rhsWords-1] = X.pVal[rhsWords-1] >> nshift;
+ }
+ return Result;
}
More information about the llvm-commits
mailing list