Make long addition and subtraction work. Speed things up by using internal

functions more.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34458 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2007-02-20 23:40:25 +00:00
parent e811636f33
commit 54362ca095

View File

@ -85,13 +85,13 @@ APInt::APInt(uint32_t numbits, const std::string& Val, uint8_t radix)
} }
/// @brief Copy constructor /// @brief Copy constructor
APInt::APInt(const APInt& APIVal) APInt::APInt(const APInt& that)
: BitWidth(APIVal.BitWidth), pVal(0) { : BitWidth(that.BitWidth), pVal(0) {
if (isSingleWord()) if (isSingleWord())
VAL = APIVal.VAL; VAL = that.VAL;
else { else {
pVal = getMemory(getNumWords()); pVal = getMemory(getNumWords());
memcpy(pVal, APIVal.pVal, getNumWords() * APINT_WORD_SIZE); memcpy(pVal, that.pVal, getNumWords() * APINT_WORD_SIZE);
} }
} }
@ -186,11 +186,11 @@ APInt& APInt::operator--() {
/// y[] and returns the carry. /// y[] and returns the carry.
static uint64_t add(uint64_t dest[], uint64_t x[], static uint64_t add(uint64_t dest[], uint64_t x[],
uint64_t y[], uint32_t len) { uint64_t y[], uint32_t len) {
uint32_t carry = 0; uint64_t carry = 0;
for (uint32_t i = 0; i< len; ++i) { for (uint32_t i = 0; i< len; ++i) {
carry += x[i]; uint64_t save = x[i];
dest[i] = carry + y[i]; dest[i] = x[i] + y[i] + carry;
carry = carry < x[i] ? 1 : (dest[i] < carry ? 1 : 0); carry = dest[i] < save ? 1 : 0;
} }
return carry; return carry;
} }
@ -199,18 +199,10 @@ static uint64_t add(uint64_t dest[], uint64_t x[],
/// RHS and assigns the result to this APInt. /// RHS and assigns the result to this APInt.
APInt& APInt::operator+=(const APInt& RHS) { APInt& APInt::operator+=(const APInt& RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) VAL += RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; if (isSingleWord())
VAL += RHS.VAL;
else { else {
if (RHS.isSingleWord()) add_1(pVal, pVal, getNumWords(), RHS.VAL); add(pVal, pVal, RHS.pVal, getNumWords());
else {
if (getNumWords() <= RHS.getNumWords())
add(pVal, pVal, RHS.pVal, getNumWords());
else {
uint64_t carry = add(pVal, pVal, RHS.pVal, RHS.getNumWords());
add_1(pVal + RHS.getNumWords(), pVal + RHS.getNumWords(),
getNumWords() - RHS.getNumWords(), carry);
}
}
} }
clearUnusedBits(); clearUnusedBits();
return *this; return *this;
@ -220,19 +212,13 @@ APInt& APInt::operator+=(const APInt& RHS) {
/// integer array y[], and returns the borrow-out carry. /// integer array y[], and returns the borrow-out carry.
static uint64_t sub(uint64_t dest[], uint64_t x[], static uint64_t sub(uint64_t dest[], uint64_t x[],
uint64_t y[], uint32_t len) { uint64_t y[], uint32_t len) {
// Carry indicator. uint64_t borrow = 0;
uint64_t cy = 0;
for (uint32_t i = 0; i < len; ++i) { for (uint32_t i = 0; i < len; ++i) {
uint64_t Y = y[i], X = x[i]; uint64_t save = x[i];
Y += cy; dest[i] = x[i] - borrow - y[i];
borrow = save < dest[i] ? 1 : 0;
cy = Y < cy ? 1 : 0;
Y = X - Y;
cy += Y > X ? 1 : 0;
dest[i] = Y;
} }
return cy; return borrow;
} }
/// @brief Subtraction assignment operator. Subtracts this APInt by the given /// @brief Subtraction assignment operator. Subtracts this APInt by the given
@ -240,20 +226,9 @@ static uint64_t sub(uint64_t dest[], uint64_t x[],
APInt& APInt::operator-=(const APInt& RHS) { APInt& APInt::operator-=(const APInt& RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) if (isSingleWord())
VAL -= RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]; VAL -= RHS.VAL;
else { else
if (RHS.isSingleWord()) sub(pVal, pVal, RHS.pVal, getNumWords());
sub_1(pVal, getNumWords(), RHS.VAL);
else {
if (RHS.getNumWords() < getNumWords()) {
uint64_t carry = sub(pVal, pVal, RHS.pVal, RHS.getNumWords());
sub_1(pVal + RHS.getNumWords(), getNumWords() - RHS.getNumWords(),
carry);
}
else
sub(pVal, pVal, RHS.pVal, getNumWords());
}
}
clearUnusedBits(); clearUnusedBits();
return *this; return *this;
} }
@ -330,7 +305,7 @@ static void mul(uint64_t dest[], uint64_t x[], uint32_t xlen,
/// given APInt& RHS and assigns the result to this APInt. /// given APInt& RHS and assigns the result to this APInt.
APInt& APInt::operator*=(const APInt& RHS) { APInt& APInt::operator*=(const APInt& RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) if (isSingleWord())
VAL *= RHS.VAL; VAL *= RHS.VAL;
else { else {
// one-based first non-zero bit position. // one-based first non-zero bit position.
@ -338,8 +313,6 @@ APInt& APInt::operator*=(const APInt& RHS) {
uint32_t xlen = !first ? 0 : whichWord(first - 1) + 1; uint32_t xlen = !first ? 0 : whichWord(first - 1) + 1;
if (!xlen) if (!xlen)
return *this; return *this;
else if (RHS.isSingleWord())
mul_1(pVal, pVal, xlen, RHS.VAL);
else { else {
first = RHS.getActiveBits(); first = RHS.getActiveBits();
uint32_t ylen = !first ? 0 : whichWord(first - 1) + 1; uint32_t ylen = !first ? 0 : whichWord(first - 1) + 1;
@ -392,11 +365,13 @@ APInt& APInt::operator^=(const APInt& RHS) {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) { if (isSingleWord()) {
VAL ^= RHS.VAL; VAL ^= RHS.VAL;
this->clearUnusedBits();
return *this; return *this;
} }
uint32_t numWords = getNumWords(); uint32_t numWords = getNumWords();
for (uint32_t i = 0; i < numWords; ++i) for (uint32_t i = 0; i < numWords; ++i)
pVal[i] ^= RHS.pVal[i]; pVal[i] ^= RHS.pVal[i];
this->clearUnusedBits();
return *this; return *this;
} }
@ -420,6 +395,7 @@ APInt APInt::operator|(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) if (isSingleWord())
return APInt(getBitWidth(), VAL | RHS.VAL); return APInt(getBitWidth(), VAL | RHS.VAL);
APInt Result(*this); APInt Result(*this);
uint32_t numWords = getNumWords(); uint32_t numWords = getNumWords();
for (uint32_t i = 0; i < numWords; ++i) for (uint32_t i = 0; i < numWords; ++i)
@ -431,8 +407,11 @@ APInt APInt::operator|(const APInt& RHS) const {
/// and the given APInt& RHS. /// and the given APInt& RHS.
APInt APInt::operator^(const APInt& RHS) const { APInt APInt::operator^(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) if (isSingleWord()) {
return APInt(getBitWidth(), VAL ^ RHS.VAL); APInt Result(BitWidth, VAL ^ RHS.VAL);
Result.clearUnusedBits();
return Result;
}
APInt Result(*this); APInt Result(*this);
uint32_t numWords = getNumWords(); uint32_t numWords = getNumWords();
for (uint32_t i = 0; i < numWords; ++i) for (uint32_t i = 0; i < numWords; ++i)
@ -456,6 +435,11 @@ bool APInt::operator !() const {
/// RHS. /// RHS.
APInt APInt::operator*(const APInt& RHS) const { APInt APInt::operator*(const APInt& RHS) const {
assert(BitWidth == RHS.BitWidth && "Bit widths must be the same"); assert(BitWidth == RHS.BitWidth && "Bit widths must be the same");
if (isSingleWord()) {
APInt Result(BitWidth, VAL * RHS.VAL);
Result.clearUnusedBits();
return Result;
}
APInt Result(*this); APInt Result(*this);
Result *= RHS; Result *= RHS;
Result.clearUnusedBits(); Result.clearUnusedBits();
@ -465,18 +449,29 @@ APInt APInt::operator*(const APInt& RHS) const {
/// @brief Addition operator. Adds this APInt by the given APInt& RHS. /// @brief Addition operator. Adds this APInt by the given APInt& RHS.
APInt APInt::operator+(const APInt& RHS) const { APInt APInt::operator+(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()) {
API += RHS; APInt Result(BitWidth, VAL + RHS.VAL);
API.clearUnusedBits(); Result.clearUnusedBits();
return API; return Result;
}
APInt Result(BitWidth, 0);
add(Result.pVal, this->pVal, RHS.pVal, getNumWords());
Result.clearUnusedBits();
return Result;
} }
/// @brief Subtraction operator. Subtracts this APInt by the given APInt& RHS /// @brief Subtraction operator. Subtracts this APInt by the given APInt& RHS
APInt APInt::operator-(const APInt& RHS) const { APInt APInt::operator-(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()) {
API -= RHS; APInt Result(BitWidth, VAL - RHS.VAL);
return API; Result.clearUnusedBits();
return Result;
}
APInt Result(BitWidth, 0);
sub(Result.pVal, this->pVal, RHS.pVal, getNumWords());
Result.clearUnusedBits();
return Result;
} }
/// @brief Array-indexing support. /// @brief Array-indexing support.
@ -488,17 +483,20 @@ bool APInt::operator[](uint32_t bitPosition) const {
/// @brief Equality operator. Compare this APInt with the given APInt& RHS /// @brief Equality operator. Compare this APInt with the given APInt& RHS
/// for the validity of the equality relationship. /// for the validity of the equality relationship.
bool APInt::operator==(const APInt& RHS) const { bool APInt::operator==(const APInt& RHS) const {
if (isSingleWord())
return VAL == RHS.VAL;
uint32_t n1 = getActiveBits(); uint32_t n1 = getActiveBits();
uint32_t n2 = RHS.getActiveBits(); uint32_t n2 = RHS.getActiveBits();
if (n1 != n2) return false; if (n1 != n2)
else if (isSingleWord()) return false;
return VAL == (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
else { if (n1 <= APINT_BITS_PER_WORD)
if (n1 <= APINT_BITS_PER_WORD) return pVal[0] == RHS.pVal[0];
return pVal[0] == (RHS.isSingleWord() ? RHS.VAL : RHS.pVal[0]);
for (int i = whichWord(n1 - 1); i >= 0; --i) for (int i = whichWord(n1 - 1); i >= 0; --i)
if (pVal[i] != RHS.pVal[i]) return false; if (pVal[i] != RHS.pVal[i])
} return false;
return true; return true;
} }
@ -507,13 +505,12 @@ bool APInt::operator==(const APInt& RHS) const {
bool APInt::operator==(uint64_t Val) const { bool APInt::operator==(uint64_t Val) const {
if (isSingleWord()) if (isSingleWord())
return VAL == Val; return VAL == Val;
else {
uint32_t n = getActiveBits(); uint32_t n = getActiveBits();
if (n <= APINT_BITS_PER_WORD) if (n <= APINT_BITS_PER_WORD)
return pVal[0] == Val; return pVal[0] == Val;
else else
return false; return false;
}
} }
/// @brief Unsigned less than comparison /// @brief Unsigned less than comparison