From: John McCall Date: Thu, 24 Dec 2009 12:16:56 +0000 (+0000) Subject: Substantially optimize APFloat::toString() by doing a single large divide to X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=003a09c68daa4934b3fe94ba03c7f50f8786310a;p=oota-llvm.git Substantially optimize APFloat::toString() by doing a single large divide to cut the significand down to the desired precision *before* entering the core divmod loop. Makes the overall algorithm logarithmic in the exponent. There's still a lot of room for improvement here, but this gets the performance back down to acceptable-for-diagnostics levels, even for long doubles. negligible, even on long doubles. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@92130 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 4426a361c06..5f748a2c24c 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -3223,6 +3223,41 @@ namespace { append(Buffer, N, Str); } + /// Removes data from the given significand until it is no more + /// precise than is required for the desired precision. + void AdjustToPrecision(APInt &significand, + int &exp, unsigned FormatPrecision) { + unsigned bits = significand.getActiveBits(); + + // 196/59 is a very slight overestimate of lg_2(10). + unsigned bitsRequired = (FormatPrecision * 196 + 58) / 59; + + if (bits <= bitsRequired) return; + + unsigned tensRemovable = (bits - bitsRequired) * 59 / 196; + if (!tensRemovable) return; + + exp += tensRemovable; + + APInt divisor(significand.getBitWidth(), 1); + APInt powten(significand.getBitWidth(), 10); + while (true) { + if (tensRemovable & 1) + divisor *= powten; + tensRemovable >>= 1; + if (!tensRemovable) break; + powten *= powten; + } + + significand = significand.udiv(divisor); + + // Truncate the significand down to its active bit count, but + // don't try to drop below 32. + unsigned newPrecision = std::min(32U, significand.getActiveBits()); + significand.trunc(newPrecision); + } + + void AdjustToPrecision(SmallVectorImpl &buffer, int &exp, unsigned FormatPrecision) { unsigned N = buffer.size(); @@ -3343,6 +3378,8 @@ void APFloat::toString(SmallVectorImpl &Str, } } + AdjustToPrecision(significand, exp, FormatPrecision); + llvm::SmallVector buffer; // Fill the buffer.