add a few operations for signed operations that also

return an overflow flag.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116452 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-10-13 23:46:33 +00:00
parent 95369599c6
commit f2ddc64c87
2 changed files with 69 additions and 11 deletions

View File

@ -741,11 +741,11 @@ public:
/// RHS are treated as unsigned quantities for purposes of this division. /// RHS are treated as unsigned quantities for purposes of this division.
/// @returns a new APInt value containing the division result /// @returns a new APInt value containing the division result
/// @brief Unsigned division operation. /// @brief Unsigned division operation.
APInt udiv(const APInt& RHS) const; APInt udiv(const APInt &RHS) const;
/// Signed divide this APInt by APInt RHS. /// Signed divide this APInt by APInt RHS.
/// @brief Signed division function for APInt. /// @brief Signed division function for APInt.
APInt sdiv(const APInt& RHS) const { APInt sdiv(const APInt &RHS) const {
if (isNegative()) if (isNegative())
if (RHS.isNegative()) if (RHS.isNegative())
return (-(*this)).udiv(-RHS); return (-(*this)).udiv(-RHS);
@ -763,11 +763,11 @@ public:
/// which is *this. /// which is *this.
/// @returns a new APInt value containing the remainder result /// @returns a new APInt value containing the remainder result
/// @brief Unsigned remainder operation. /// @brief Unsigned remainder operation.
APInt urem(const APInt& RHS) const; APInt urem(const APInt &RHS) const;
/// Signed remainder operation on APInt. /// Signed remainder operation on APInt.
/// @brief Function for signed remainder operation. /// @brief Function for signed remainder operation.
APInt srem(const APInt& RHS) const { APInt srem(const APInt &RHS) const {
if (isNegative()) if (isNegative())
if (RHS.isNegative()) if (RHS.isNegative())
return -((-(*this)).urem(-RHS)); return -((-(*this)).urem(-RHS));
@ -788,8 +788,7 @@ public:
APInt &Quotient, APInt &Remainder); APInt &Quotient, APInt &Remainder);
static void sdivrem(const APInt &LHS, const APInt &RHS, static void sdivrem(const APInt &LHS, const APInt &RHS,
APInt &Quotient, APInt &Remainder) APInt &Quotient, APInt &Remainder) {
{
if (LHS.isNegative()) { if (LHS.isNegative()) {
if (RHS.isNegative()) if (RHS.isNegative())
APInt::udivrem(-LHS, -RHS, Quotient, Remainder); APInt::udivrem(-LHS, -RHS, Quotient, Remainder);
@ -804,6 +803,16 @@ public:
APInt::udivrem(LHS, RHS, Quotient, Remainder); APInt::udivrem(LHS, RHS, Quotient, Remainder);
} }
} }
// Operations that return overflow indicators.
// ssub_ov - Signed subtraction. Unsigned subtraction never overflows.
APInt sadd_ov(const APInt &RHS, bool &Overflow);
APInt ssub_ov(const APInt &RHS, bool &Overflow);
APInt sdiv_ov(const APInt &RHS, bool &Overflow);
APInt smul_ov(const APInt &RHS, bool &Overflow);
APInt sshl_ov(unsigned Amt, bool &Overflow);
/// @returns the bit value at bitPosition /// @returns the bit value at bitPosition
/// @brief Array-indexing support. /// @brief Array-indexing support.
@ -988,6 +997,9 @@ public:
return sge(APInt(getBitWidth(), RHS)); return sge(APInt(getBitWidth(), RHS));
} }
/// This operation tests if there are any pairs of corresponding bits /// This operation tests if there are any pairs of corresponding bits
/// between this APInt and RHS that are both set. /// between this APInt and RHS that are both set.
bool intersects(const APInt &RHS) const { bool intersects(const APInt &RHS) const {
@ -1029,7 +1041,7 @@ public:
/// @name Bit Manipulation Operators /// @name Bit Manipulation Operators
/// @{ /// @{
/// @brief Set every bit to 1. /// @brief Set every bit to 1.
APInt& set() { APInt &set() {
if (isSingleWord()) { if (isSingleWord()) {
VAL = -1ULL; VAL = -1ULL;
return clearUnusedBits(); return clearUnusedBits();
@ -1044,10 +1056,10 @@ public:
/// Set the given bit to 1 whose position is given as "bitPosition". /// Set the given bit to 1 whose position is given as "bitPosition".
/// @brief Set a given bit to 1. /// @brief Set a given bit to 1.
APInt& set(unsigned bitPosition); APInt &set(unsigned bitPosition);
/// @brief Set every bit to 0. /// @brief Set every bit to 0.
APInt& clear() { APInt &clear() {
if (isSingleWord()) if (isSingleWord())
VAL = 0; VAL = 0;
else else
@ -1057,10 +1069,10 @@ public:
/// Set the given bit to 0 whose position is given as "bitPosition". /// Set the given bit to 0 whose position is given as "bitPosition".
/// @brief Set a given bit to 0. /// @brief Set a given bit to 0.
APInt& clear(unsigned bitPosition); APInt &clear(unsigned bitPosition);
/// @brief Toggle every bit to its opposite value. /// @brief Toggle every bit to its opposite value.
APInt& flip() { APInt &flip() {
if (isSingleWord()) { if (isSingleWord()) {
VAL ^= -1ULL; VAL ^= -1ULL;
return clearUnusedBits(); return clearUnusedBits();

View File

@ -2046,6 +2046,52 @@ void APInt::udivrem(const APInt &LHS, const APInt &RHS,
divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder); divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder);
} }
APInt APInt::sadd_ov(const APInt &RHS, bool &Overflow) {
APInt Res = *this+RHS;
Overflow = isNonNegative() == RHS.isNonNegative() &&
Res.isNonNegative() != isNonNegative();
return Res;
}
APInt APInt::ssub_ov(const APInt &RHS, bool &Overflow) {
APInt Res = *this - RHS;
Overflow = isNonNegative() != RHS.isNonNegative() &&
Res.isNonNegative() != isNonNegative();
return Res;
}
APInt APInt::sdiv_ov(const APInt &RHS, bool &Overflow) {
// MININT/-1 --> overflow.
Overflow = isMinSignedValue() && RHS.isAllOnesValue();
return sdiv(RHS);
}
APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) {
APInt Res = *this * RHS;
if (*this != 0 && RHS != 0)
Overflow = Res.sdiv(RHS) != *this || Res.sdiv(*this) != RHS;
else
Overflow = false;
return Res;
}
APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) {
Overflow = ShAmt >= getBitWidth();
if (Overflow)
ShAmt = getBitWidth()-1;
if (isNonNegative()) // Don't allow sign change.
Overflow = ShAmt >= countLeadingZeros();
else
Overflow = ShAmt >= countLeadingOnes();
return *this << ShAmt;
}
void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) { void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
// Check our assumptions here // Check our assumptions here
assert(!str.empty() && "Invalid string length"); assert(!str.empty() && "Invalid string length");