From 0b706b18bd0a7760d971727460a1f26bff8289b0 Mon Sep 17 00:00:00 2001 From: Zhou Sheng Date: Thu, 8 Feb 2007 14:35:19 +0000 Subject: [PATCH] As Chris and Reid suggested, remove "isSigned" field from APInt, instead, add some signed/unsigned arithmetic operation functions into APInt.h to handle the signed/unsigned issue. These functions will be defined inside a namespace "APIntOps" which is inside llvm namespace. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34053 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APInt.h | 140 ++++++++++------ lib/Support/APInt.cpp | 348 +++++++++++++++++++-------------------- 2 files changed, 262 insertions(+), 226 deletions(-) diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 62a33d5320a..8709fb80e08 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -21,6 +21,21 @@ namespace llvm { +/// Forward declaration. +class APInt; +namespace APIntOps { + bool isIntN(unsigned N, const APInt& APIVal); + APInt ByteSwap(const APInt& APIVal); + APInt LogBase2(const APInt& APIVal); + APInt ashr(const APInt& LHS, unsigned shiftAmt); + APInt lshr(const APInt& LHS, unsigned shiftAmt); + APInt shl(const APInt& LHS, unsigned shiftAmt); + APInt sdiv(const APInt& LHS, const APInt& RHS); + APInt udiv(const APInt& LHS, const APInt& RHS); + APInt srem(const APInt& LHS, const APInt& RHS); + APInt urem(const APInt& LHS, const APInt& RHS); +} + //===----------------------------------------------------------------------===// // APInt Class //===----------------------------------------------------------------------===// @@ -40,14 +55,18 @@ namespace llvm { class APInt { /// Friend Functions of APInt declared here. For detailed comments, /// see bottom of this file. - friend bool isIntN(unsigned N, const APInt& APIVal); - friend APInt ByteSwap(const APInt& APIVal); - friend APInt LogBase2(const APInt& APIVal); - friend double APIntToDouble(const APInt& APIVal); - friend float APIntToFloat(const APInt& APIVal); + friend bool APIntOps::isIntN(unsigned N, const APInt& APIVal); + friend APInt APIntOps::ByteSwap(const APInt& APIVal); + friend APInt APIntOps::LogBase2(const APInt& APIVal); + friend APInt APIntOps::ashr(const APInt& LHS, unsigned shiftAmt); + friend APInt APIntOps::lshr(const APInt& LHS, unsigned shiftAmt); + friend APInt APIntOps::shl(const APInt& LHS, unsigned shiftAmt); + friend APInt APIntOps::sdiv(const APInt& LHS, const APInt& RHS); + friend APInt APIntOps::udiv(const APInt& LHS, const APInt& RHS); + friend APInt APIntOps::srem(const APInt& LHS, const APInt& RHS); + friend APInt APIntOps::urem(const APInt& LHS, const APInt& RHS); unsigned BitsNum; ///< The number of bits. - bool isSigned; ///< The sign flag for this APInt. /// This union is used to store the integer value. When the /// integer bit-width <= 64, it uses VAL; @@ -114,20 +133,19 @@ class APInt { public: /// @brief Create a new APInt of numBits bit-width, and initialized as val. - APInt(uint64_t val = 0, unsigned numBits = APINT_BITS_PER_WORD, - bool sign = false); + APInt(uint64_t val = 0, unsigned numBits = APINT_BITS_PER_WORD); /// @brief Create a new APInt of numBits bit-width, and initialized as /// bigVal[]. - APInt(unsigned numBits, uint64_t bigVal[], bool sign = false); + APInt(unsigned numBits, uint64_t bigVal[]); /// @brief Create a new APInt by translating the string represented /// integer value. - APInt(const std::string& Val, uint8_t radix = 10, bool sign = false); + APInt(const std::string& Val, uint8_t radix = 10); /// @brief Create a new APInt by translating the char array represented /// integer value. - APInt(const char StrStart[], unsigned slen, uint8_t radix, bool sign = false); + APInt(const char StrStart[], unsigned slen, uint8_t radix); /// @brief Copy Constructor. APInt(const APInt& API); @@ -179,14 +197,6 @@ public: /// @brief Bitwise XOR assignment operator. APInt& operator^=(const APInt& RHS); - /// Left-shift the APInt by shiftAmt and assigns the result to this APInt. - /// @brief Left-shift assignment operator. - APInt& operator<<=(unsigned shiftAmt); - - /// Right-shift the APInt by shiftAmt and assigns the result to this APInt. - /// @brief Right-shift assignment operator. - APInt& operator>>=(unsigned shiftAmt); - /// Performs a bitwise complement operation on this APInt. /// @brief Bitwise complement operator. APInt operator~() const; @@ -196,11 +206,6 @@ public: /// @brief Multiplication assignment operator. APInt& operator*=(const APInt& RHS); - /// Divides this APInt by the given APInt &RHS and - /// assigns the result to this APInt. - /// @brief Division assignment operator. - APInt& operator/=(const APInt& RHS); - /// Adds this APInt by the given APInt& RHS and /// assigns the result to this APInt. /// @brief Addition assignment operator. @@ -211,11 +216,6 @@ public: /// @brief Subtraction assignment operator. APInt& operator-=(const APInt& RHS); - /// Yields the remainder from the division of this APInt by - /// the given APInt& RHS and assigns the remainder to this APInt. - /// @brief Remainder assignment operator. - APInt& operator%=(const APInt& RHS); - /// Performs bitwise AND operation on this APInt and /// the given APInt& RHS. /// @brief Bitwise AND operator. @@ -245,15 +245,6 @@ public: /// @brief Multiplication operator. APInt operator*(const APInt& RHS) const; - /// Divides this APInt by the given APInt& RHS. - /// @brief Division operator. - APInt operator/(const APInt& RHS) const; - - /// Yields the remainder from the division of - /// this APInt and the given APInt& RHS. - /// @brief Remainder operator. - APInt operator%(const APInt& RHS) const; - /// Adds this APInt by the given APInt& RHS. /// @brief Addition operator. APInt operator+(const APInt& RHS) const; @@ -262,13 +253,10 @@ public: /// @brief Subtraction operator. APInt operator-(const APInt& RHS) const; - /// Left-shift the APInt by shiftAmt. - /// @brief Left-shift operator. - APInt operator<<(unsigned shiftAmt) const; - - /// Right-shift the APInt by shiftAmt. - /// @brief Right-shift operator. - APInt operator>>(unsigned shiftAmt) const; + /// + inline APInt operator-() const { + return APInt(0, BitsNum) - (*this); + } /// @brief Array-indexing support. bool operator[](unsigned bitPosition) const; @@ -321,9 +309,7 @@ public: /// word, just returns VAL, otherwise pVal[0]. inline uint64_t getValue() { if (isSingleWord()) - return isSigned ? ((int64_t(VAL) << (APINT_BITS_PER_WORD - BitsNum)) >> - (APINT_BITS_PER_WORD - BitsNum)) : - VAL; + return VAL; assert(0 && "This APInt's bitwidth > 64"); } @@ -403,6 +389,8 @@ public: }; +namespace APIntOps { + /// @brief Check if the specified APInt has a N-bits integer value. inline bool isIntN(unsigned N, const APInt& APIVal) { if (APIVal.isSingleWord()) { @@ -439,6 +427,62 @@ inline APInt LogBase2(const APInt& APIVal) { /// using Euclid's algorithm. APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2); +/// Arithmetic right-shift the APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt ashr(const APInt& LHS, unsigned shiftAmt); + +/// Logical right-shift the APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt lshr(const APInt& LHS, unsigned shiftAmt); + +/// Left-shift the APInt by shiftAmt. +/// @brief Left-shift function. +APInt shl(const APInt& LHS, unsigned shiftAmt); + +/// Signed divide APInt LHS by APInt RHS. +/// @brief Signed division function for APInt. +inline APInt sdiv(const APInt& LHS, const APInt& RHS) { + bool isSignedLHS = LHS[LHS.BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1]; + APInt API = udiv(isSignedLHS ? -LHS : LHS, isSignedRHS ? -RHS : RHS); + return isSignedLHS != isSignedRHS ? -API : API;; +} + +/// Unsigned divide APInt LHS by APInt RHS. +/// @brief Unsigned division function for APInt. +APInt udiv(const APInt& LHS, const APInt& RHS); + +/// Signed remainder operation on APInt. +/// @brief Function for signed remainder operation. +inline APInt srem(const APInt& LHS, const APInt& RHS) { + bool isSignedLHS = LHS[LHS.BitsNum - 1], isSignedRHS = RHS[RHS.BitsNum - 1]; + APInt API = urem(isSignedLHS ? -LHS : LHS, isSignedRHS ? -RHS : RHS); + return isSignedLHS ? -API : API; +} + +/// Unsigned remainder operation on APInt. +/// @brief Function for unsigned remainder operation. +APInt urem(const APInt& LHS, const APInt& RHS); + +/// Performs multiplication on APInt values. +/// @brief Function for multiplication operation. +inline APInt mul(const APInt& LHS, const APInt& RHS) { + return LHS * RHS; +} + +/// Performs addition on APInt values. +/// @brief Function for addition operation. +inline APInt add(const APInt& LHS, const APInt& RHS) { + return LHS + RHS; +} + +/// Performs subtraction on APInt values. +/// @brief Function for subtraction operation. +inline APInt sub(const APInt& LHS, const APInt& RHS) { + return LHS - RHS; +} + +} // End of APIntOps namespace + } // End of llvm namespace #endif diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index c288f98ff9a..21fb8cffc7f 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -14,7 +14,7 @@ #include "llvm/ADT/APInt.h" -#if 0 +#if 1 #include "llvm/DerivedTypes.h" #include "llvm/Support/MathExtras.h" #include @@ -262,8 +262,8 @@ static uint64_t lshift(uint64_t dest[], unsigned d_offset, return retVal; } -APInt::APInt(uint64_t val, unsigned numBits, bool sign) - : BitsNum(numBits), isSigned(sign) { +APInt::APInt(uint64_t val, unsigned numBits) + : BitsNum(numBits) { assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small"); assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large"); if (isSingleWord()) @@ -277,8 +277,8 @@ APInt::APInt(uint64_t val, unsigned numBits, bool sign) } } -APInt::APInt(unsigned numBits, uint64_t bigVal[], bool sign) - : BitsNum(numBits), isSigned(sign) { +APInt::APInt(unsigned numBits, uint64_t bigVal[]) + : BitsNum(numBits) { assert(BitsNum >= IntegerType::MIN_INT_BITS && "bitwidth too small"); assert(BitsNum <= IntegerType::MAX_INT_BITS && "bitwidth too large"); assert(bigVal && "Null pointer detected!"); @@ -301,15 +301,13 @@ APInt::APInt(unsigned numBits, uint64_t bigVal[], bool sign) /// @brief Create a new APInt by translating the char array represented /// integer value. -APInt::APInt(const char StrStart[], unsigned slen, uint8_t radix, bool sign) - : isSigned(sign) { +APInt::APInt(const char StrStart[], unsigned slen, uint8_t radix) { StrToAPInt(StrStart, slen, radix); } /// @brief Create a new APInt by translating the string represented /// integer value. -APInt::APInt(const std::string& Val, uint8_t radix, bool sign) - : isSigned(sign) { +APInt::APInt(const std::string& Val, uint8_t radix) { assert(!Val.empty() && "String empty?"); StrToAPInt(Val.c_str(), Val.size(), radix); } @@ -386,7 +384,7 @@ void APInt::StrToAPInt(const char *StrStart, unsigned slen, uint8_t radix) { } APInt::APInt(const APInt& APIVal) - : BitsNum(APIVal.BitsNum), isSigned(APIVal.isSigned) { + : BitsNum(APIVal.BitsNum) { if (isSingleWord()) VAL = APIVal.VAL; else { // Memory allocation and check if successful. @@ -421,6 +419,7 @@ APInt& APInt::operator=(uint64_t RHS) { pVal[0] = RHS; memset(pVal, 0, (getNumWords() - 1) * 8); } + TruncToBits(); return *this; } @@ -514,101 +513,6 @@ APInt& APInt::operator*=(const APInt& RHS) { return *this; } -/// @brief Division assignment operator. Divides this APInt by the given APInt -/// &RHS and assigns the result to this APInt. -APInt& APInt::operator/=(const APInt& RHS) { - unsigned first = RHS.getNumWords() * APINT_BITS_PER_WORD - - RHS.CountLeadingZeros(); - unsigned ylen = !first ? 0 : whichWord(first - 1) + 1; - assert(ylen && "Divided by zero???"); - if (isSingleWord()) { - if (isSigned && RHS.isSigned) - VAL = RHS.isSingleWord() ? (int64_t(VAL) / int64_t(RHS.VAL)) : - (ylen > 1 ? 0 : int64_t(VAL) / int64_t(RHS.pVal[0])); - else - VAL = RHS.isSingleWord() ? (VAL / RHS.VAL) : - (ylen > 1 ? 0 : VAL / RHS.pVal[0]); - } else { - unsigned first2 = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros(); - unsigned xlen = !first2 ? 0 : whichWord(first2 - 1) + 1; - if (!xlen) - return *this; - else if ((*this) < RHS) - memset(pVal, 0, getNumWords() * 8); - else if ((*this) == RHS) { - memset(pVal, 0, getNumWords() * 8); - pVal[0] = 1; - } else if (xlen == 1) - pVal[0] /= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; - else { - uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen]; - assert(xwords && ywords && "Memory Allocation Failed!"); - memcpy(xwords, pVal, xlen * 8); - xwords[xlen] = 0; - memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8); - if (unsigned nshift = 63 - (first - 1) % 64) { - lshift(ywords, 0, ywords, ylen, nshift); - unsigned xlentmp = xlen; - xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift); - } - div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2); - memset(pVal, 0, getNumWords() * 8); - memcpy(pVal, xwords + ylen, (xlen - ylen) * 8); - delete[] xwords; - delete[] ywords; - } - } - return *this; -} - -/// @brief Remainder assignment operator. Yields the remainder from the -/// division of this APInt by the given APInt& RHS and assigns the remainder -/// to this APInt. -APInt& APInt::operator%=(const APInt& RHS) { - unsigned first = RHS.getNumWords() * APINT_BITS_PER_WORD - - RHS.CountLeadingZeros(); - unsigned ylen = !first ? 0 : whichWord(first - 1) + 1; - assert(ylen && "Performing remainder operation by zero ???"); - if (isSingleWord()) { - if (isSigned && RHS.isSigned) - VAL = RHS.isSingleWord() ? (int64_t(VAL) % int64_t(RHS.VAL)) : - (ylen > 1 ? VAL : int64_t(VAL) % int64_t(RHS.pVal[0])); - else - VAL = RHS.isSingleWord() ? (VAL % RHS.VAL) : - (ylen > 1 ? VAL : VAL % RHS.pVal[0]); - } else { - unsigned first2 = getNumWords() * APINT_BITS_PER_WORD - CountLeadingZeros(); - unsigned xlen = !first2 ? 0 : whichWord(first2 - 1) + 1; - if (!xlen || (*this) < RHS) - return *this; - else if ((*this) == RHS) - memset(pVal, 0, getNumWords() * 8); - else if (xlen == 1) - pVal[0] %= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; - else { - uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen]; - assert(xwords && ywords && "Memory Allocation Failed!"); - memcpy(xwords, pVal, xlen * 8); - xwords[xlen] = 0; - memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8); - unsigned nshift = 63 - (first - 1) % 64; - if (nshift) { - lshift(ywords, 0, ywords, ylen, nshift); - unsigned xlentmp = xlen; - xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift); - } - div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2); - memset(pVal, 0, getNumWords() * 8); - for (unsigned i = 0; i < ylen-1; ++i) - pVal[i] = (xwords[i] >> nshift) | (xwords[i+1] << (64 - nshift)); - pVal[ylen-1] = xwords[ylen-1] >> nshift; - delete[] xwords; - delete[] ywords; - } - } - return *this; -} - /// @brief Bitwise AND assignment operator. Performs bitwise AND operation on /// this APInt and the given APInt& RHS, assigns the result to this APInt. APInt& APInt::operator&=(const APInt& RHS) { @@ -753,19 +657,6 @@ APInt APInt::operator*(const APInt& RHS) const { return API; } -/// @brief Division operator. Divides this APInt by the given APInt& RHS. -APInt APInt::operator/(const APInt& RHS) const { - APInt API(*this); - return API /= RHS; -} - -/// @brief Remainder operator. Yields the remainder from the division of this -/// APInt and the given APInt& RHS. -APInt APInt::operator%(const APInt& RHS) const { - APInt API(*this); - return API %= RHS; -} - /// @brief Addition operator. Adds this APInt by the given APInt& RHS. APInt APInt::operator+(const APInt& RHS) const { APInt API(*this); @@ -778,7 +669,6 @@ APInt APInt::operator+(const APInt& RHS) const { APInt APInt::operator-(const APInt& RHS) const { APInt API(*this); API -= RHS; - API.TruncToBits(); return API; } @@ -822,12 +712,6 @@ bool APInt::operator==(uint64_t Val) const { /// @brief Less-than operator. Compare this APInt with the given APInt& RHS /// for the validity of the less-than relationship. bool APInt::operator <(const APInt& RHS) const { - if (isSigned && RHS.isSigned) { - if ((*this)[BitsNum-1] > RHS[RHS.BitsNum-1]) - return false; - else if ((*this)[BitsNum-1] < RHS[RHS.BitsNum-1]) - return true; - } unsigned n1 = getNumWords() * 64 - CountLeadingZeros(), n2 = RHS.getNumWords() * 64 - RHS.CountLeadingZeros(); if (n1 < n2) return true; @@ -896,54 +780,6 @@ APInt& APInt::clear() { return *this; } -/// @brief Left-shift assignment operator. Left-shift the APInt by shiftAmt -/// and assigns the result to this APInt. -APInt& APInt::operator<<=(unsigned shiftAmt) { - if (shiftAmt >= BitsNum) { - if (isSingleWord()) VAL = 0; - else - memset(pVal, 0, getNumWords() * 8); - } else { - for (unsigned i = 0; i < shiftAmt; ++i) clear(i); - for (unsigned i = shiftAmt; i < BitsNum; ++i) { - if ((*this)[i-shiftAmt]) set(i); - else clear(i); - } - } - return *this; -} - -/// @brief Left-shift operator. Left-shift the APInt by shiftAmt. -APInt APInt::operator<<(unsigned shiftAmt) const { - APInt API(*this); - API <<= shiftAmt; - return API; -} - -/// @brief Right-shift assignment operator. Right-shift the APInt by shiftAmt -/// and assigns the result to this APInt. -APInt& APInt::operator>>=(unsigned shiftAmt) { - bool isAShr = isSigned && (*this)[BitsNum-1]; - if (isSingleWord()) - VAL = isAShr ? (int64_t(VAL) >> shiftAmt) : (VAL >> shiftAmt); - else { - unsigned i = 0; - for (i = 0; i < BitsNum - shiftAmt; ++i) - if ((*this)[i+shiftAmt]) set(i); - else clear(i); - for (; i < BitsNum; ++i) - isAShr ? set(i) : clear(i); - } - return *this; -} - -/// @brief Right-shift operator. Right-shift the APInt by shiftAmt. -APInt APInt::operator>>(unsigned shiftAmt) const { - APInt API(*this); - API >>= shiftAmt; - return API; -} - /// @brief Bitwise NOT operator. Performs a bitwise logical NOT operation on /// this APInt. APInt APInt::operator~() const { @@ -1042,12 +878,13 @@ APInt APInt::getNullValue(unsigned numBits) { /// HiBits - This function returns the high "numBits" bits of this APInt. APInt APInt::HiBits(unsigned numBits) const { - return (*this) >> (BitsNum - numBits); + return APIntOps::lshr(*this, BitsNum - numBits); } /// LoBits - This function returns the low "numBits" bits of this APInt. APInt APInt::LoBits(unsigned numBits) const { - return ((*this) << (BitsNum - numBits)) >> (BitsNum - numBits); + return APIntOps::lshr(APIntOps::shl(*this, BitsNum - numBits), + BitsNum - numBits); } /// CountLeadingZeros - This function is a APInt version corresponding to @@ -1096,7 +933,7 @@ unsigned APInt::CountPopulation() const { /// ByteSwap - This function returns a byte-swapped representation of the /// APInt argument, APIVal. -APInt llvm::ByteSwap(const APInt& APIVal) { +APInt llvm::APIntOps::ByteSwap(const APInt& APIVal) { if (APIVal.BitsNum <= 32) return APInt(APIVal.BitsNum, ByteSwap_32(unsigned(APIVal.VAL))); else if (APIVal.BitsNum <= 64) @@ -1107,15 +944,170 @@ APInt llvm::ByteSwap(const APInt& APIVal) { /// GreatestCommonDivisor - This function returns the greatest common /// divisor of the two APInt values using Enclid's algorithm. -APInt llvm::GreatestCommonDivisor(const APInt& API1, const APInt& API2) { +APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1, + const APInt& API2) { APInt A = API1, B = API2; while (!!B) { APInt T = B; - B = A % B; + B = APIntOps::urem(A, B); A = T; } return A; } +/// Arithmetic right-shift the APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +APInt llvm::APIntOps::ashr(const APInt& LHS, unsigned shiftAmt) { + APInt API(LHS); + if (API.isSingleWord()) + API.VAL = (((int64_t(API.VAL) << (64 - API.BitsNum)) >> (64 - API.BitsNum)) + >> shiftAmt) & (~uint64_t(0UL) >> (64 - API.BitsNum)); + else { + if (shiftAmt >= API.BitsNum) { + memset(API.pVal, API[API.BitsNum-1] ? 1 : 0, (API.getNumWords()-1) * 8); + API.pVal[API.getNumWords() - 1] = ~uint64_t(0UL) >> + (64 - API.BitsNum % 64); + } else { + unsigned i = 0; + for (; i < API.BitsNum - shiftAmt; ++i) + if (API[i+shiftAmt]) + API.set(i); + else + API.clear(i); + for (; i < API.BitsNum; ++i) + API[API.BitsNum-1] ? API.set(i) : API.clear(i); + } + } + return API; +} + +/// Logical right-shift the APInt by shiftAmt. +/// @brief Logical right-shift function. +APInt llvm::APIntOps::lshr(const APInt& RHS, unsigned shiftAmt) { + APInt API(RHS); + if (API.isSingleWord()) + API.VAL >>= shiftAmt; + else { + if (shiftAmt >= API.BitsNum) + memset(API.pVal, 0, API.getNumWords() * 8); + unsigned i = 0; + for (i = 0; i < API.BitsNum - shiftAmt; ++i) + if (API[i+shiftAmt]) API.set(i); + else API.clear(i); + for (; i < API.BitsNum; ++i) + API.clear(i); + } + return API; +} + +/// Left-shift the APInt by shiftAmt. +/// @brief Left-shift function. +APInt llvm::APIntOps::shl(const APInt& RHS, unsigned shiftAmt) { + APInt API(RHS); + if (shiftAmt >= API.BitsNum) { + if (API.isSingleWord()) + API.VAL = 0; + else + memset(API.pVal, 0, API.getNumWords() * 8); + } else { + for (unsigned i = 0; i < shiftAmt; ++i) API.clear(i); + for (unsigned i = shiftAmt; i < API.BitsNum; ++i) { + if (API[i-shiftAmt]) API.set(i); + else API.clear(i); + } + } + return API; +} + +/// Unsigned divide APInt LHS by APInt RHS. +/// @brief Unsigned division function for APInt. +APInt llvm::APIntOps::udiv(const APInt& LHS, const APInt& RHS) { + APInt API(LHS); + unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD - + RHS.CountLeadingZeros(); + 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.getNumWords() * APInt::APINT_BITS_PER_WORD - + API.CountLeadingZeros(); + unsigned xlen = !first2 ? 0 : APInt::whichWord(first2 - 1) + 1; + if (!xlen) + return API; + else if (API < 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 { + uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen]; + assert(xwords && ywords && "Memory Allocation Failed!"); + memcpy(xwords, API.pVal, xlen * 8); + xwords[xlen] = 0; + memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8); + if (unsigned nshift = 63 - (first - 1) % 64) { + lshift(ywords, 0, ywords, ylen, nshift); + unsigned xlentmp = xlen; + xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift); + } + div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2); + memset(API.pVal, 0, API.getNumWords() * 8); + memcpy(API.pVal, xwords + ylen, (xlen - ylen) * 8); + delete[] xwords; + delete[] ywords; + } + } + return API; +} + +/// Unsigned remainder operation on APInt. +/// @brief Function for unsigned remainder operation. +APInt llvm::APIntOps::urem(const APInt& LHS, const APInt& RHS) { + APInt API(LHS); + unsigned first = RHS.getNumWords() * APInt::APINT_BITS_PER_WORD - + RHS.CountLeadingZeros(); + 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.getNumWords() * APInt::APINT_BITS_PER_WORD - + API.CountLeadingZeros(); + unsigned xlen = !first2 ? 0 : API.whichWord(first2 - 1) + 1; + if (!xlen || API < 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 { + uint64_t *xwords = new uint64_t[xlen+1], *ywords = new uint64_t[ylen]; + assert(xwords && ywords && "Memory Allocation Failed!"); + memcpy(xwords, API.pVal, xlen * 8); + xwords[xlen] = 0; + memcpy(ywords, RHS.isSingleWord() ? &RHS.VAL : RHS.pVal, ylen * 8); + unsigned nshift = 63 - (first - 1) % 64; + if (nshift) { + lshift(ywords, 0, ywords, ylen, nshift); + unsigned xlentmp = xlen; + xwords[xlen++] = lshift(xwords, 0, xwords, xlentmp, nshift); + } + div((unsigned*)xwords, xlen*2-1, (unsigned*)ywords, ylen*2); + memset(API.pVal, 0, API.getNumWords() * 8); + for (unsigned i = 0; i < ylen-1; ++i) + API.pVal[i] = (xwords[i] >> nshift) | (xwords[i+1] << (64 - nshift)); + API.pVal[ylen-1] = xwords[ylen-1] >> nshift; + delete[] xwords; + delete[] ywords; + } + } + return API; +} + #endif