[llvm] [APFloat] Fix literals with long significands. (PR #102051)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 3 14:22:23 PDT 2024


================
@@ -761,27 +745,45 @@ ulpsFromBoundary(const APFloatBase::integerPart *parts, unsigned int bits,
   return ~(APFloatBase::integerPart) 0; /* A lot.  */
 }
 
-/* Place pow(5, power) in DST, and return the number of parts used.
-   DST must be at least one part larger than size of the answer.  */
-static unsigned int
-powerOf5(APFloatBase::integerPart *dst, unsigned int power) {
+/* Calculate and return pow(5, power). */
+static SmallVector<APFloatBase::integerPart, 0> powerOf5(unsigned int power) {
   static const APFloatBase::integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, 15625, 78125 };
-  APFloatBase::integerPart pow5s[maxPowerOfFiveParts * 2 + 5];
+
+  // Make sure that the following expression does not overflow.
+  assert(power <= UINT_MAX / 815);
+
+  // A tight upper bound on number of parts required to hold the value
+  // pow(5, power) is
+  //
+  //   power * 815 / (351 * integerPartWidth) + 1
+  //
+  // However, whilst the result may require only this many parts,
+  // because we are multiplying two values to get it, the
+  // multiplication may require an extra part with the excess part
+  // being zero (consider the trivial case of 1 * 1, tcFullMultiply
+  // requires two parts to hold the single-part result).  So we add an
+  // extra one to guarantee enough space whilst multiplying.
+  const unsigned int maxPowerOfFiveParts =
+      2 + ((power * 815) / (351 * APFloatBase::integerPartWidth));
+
+  SmallVector<APFloatBase::integerPart, 0> pow5s(maxPowerOfFiveParts * 2 + 5);
----------------
keinflue wrote:

The actual minimum size required (see lines above) is `9` and I think `SmallVector`'s default is smaller. It increases with both the length of the significand of the floating point literal as well as its exponent. I used `0` because I have no idea what a good estimation for typical floating point literals is. The old code used a fixed size array of roughly length 1200. I could of course use that, but felt that it was a bit much waste of stack space for the typical use case. All in all the arrays took roughly 14kB stack.

https://github.com/llvm/llvm-project/pull/102051


More information about the llvm-commits mailing list