diff --git a/lib/Support/BigIntSupport.cpp b/lib/Support/BigIntSupport.cpp index d9b0fe35b64..2453fd0bdb9 100644 --- a/lib/Support/BigIntSupport.cpp +++ b/lib/Support/BigIntSupport.cpp @@ -1741,10 +1741,6 @@ multiply(MutableBigIntRef dst, ImmutableBigIntRef lhs, ImmutableBigIntRef rhs) { namespace { namespace div_rem { -static uint32_t getResultSize(ImmutableBigIntRef lhs, ImmutableBigIntRef rhs) { - return std::max(lhs.numDigits, rhs.numDigits) + 1; -} - static OperationStatus compute( MutableBigIntRef quoc, MutableBigIntRef rem, @@ -1868,7 +1864,14 @@ static OperationStatus compute( } // namespace uint32_t divideResultSize(ImmutableBigIntRef lhs, ImmutableBigIntRef rhs) { - return div_rem::getResultSize(lhs, rhs); + if (isNegative(lhs) && compare(rhs, -1) == 0) { + // In this (and only this) case, we can end up with more digits than we started with + // Examples: -(2n**63n)/-1n, -(2n**127n)/-1n + // We avoid this in general case as it makes division much slower + return std::max(lhs.numDigits, rhs.numDigits) + 1; + } + + return std::max(lhs.numDigits, rhs.numDigits); } OperationStatus @@ -1879,7 +1882,7 @@ divide(MutableBigIntRef dst, ImmutableBigIntRef lhs, ImmutableBigIntRef rhs) { } uint32_t remainderResultSize(ImmutableBigIntRef lhs, ImmutableBigIntRef rhs) { - return div_rem::getResultSize(lhs, rhs); + return divideResultSize(lhs, rhs); // We currently expect them to be equivalent in div_rem::compute() } OperationStatus remainder(