diff options
Diffstat (limited to 'llvm/lib/Support/APInt.cpp')
-rw-r--r-- | llvm/lib/Support/APInt.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 2c2ce95..8be903f 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -2658,3 +2658,49 @@ void APInt::tcSetLeastSignificantBits(WordType *dst, unsigned parts, while (i < parts) dst[i++] = 0; } + +APInt llvm::APIntOps::RoundingUDiv(const APInt &A, const APInt &B, + APInt::Rounding RM) { + // Currently udivrem always rounds down. + switch (RM) { + case APInt::Rounding::DOWN: + case APInt::Rounding::TOWARD_ZERO: + return A.udiv(B); + case APInt::Rounding::UP: { + APInt Quo, Rem; + APInt::udivrem(A, B, Quo, Rem); + if (Rem == 0) + return Quo; + return Quo + 1; + } + } +} + +APInt llvm::APIntOps::RoundingSDiv(const APInt &A, const APInt &B, + APInt::Rounding RM) { + switch (RM) { + case APInt::Rounding::DOWN: + case APInt::Rounding::UP: { + APInt Quo, Rem; + APInt::sdivrem(A, B, Quo, Rem); + if (Rem == 0) + return Quo; + // This algorithm deals with arbitrary rounding mode used by sdivrem. + // We want to check whether the non-integer part of the mathematical value + // is negative or not. If the non-integer part is negative, we need to round + // down from Quo; otherwise, if it's positive or 0, we return Quo, as it's + // already rounded down. + if (RM == APInt::Rounding::DOWN) { + if (Rem.isNegative() != B.isNegative()) + return Quo - 1; + return Quo; + } + if (Rem.isNegative() != B.isNegative()) + return Quo; + return Quo + 1; + } + // Currently sdiv rounds twards zero. + case APInt::Rounding::TOWARD_ZERO: + return A.sdiv(B); + } +} |