[llvm-commits] [llvm] r128545 - in /llvm/trunk: include/llvm/ADT/APFloat.h lib/Support/APFloat.cpp unittests/ADT/APFloatTest.cpp
Stephen Canon
scanon at apple.com
Wed Mar 30 09:11:54 PDT 2011
What will this patch do on a platform where denormals are treated as zero?
Specifically, I'm interested in a case like this:
float a;
float b = a / 0x1.0p127f;
If this is converted into the reciprocal multiply by 0x0.8p-126f (a denormal value), on platforms where denormals are treated as zero (the default state on many ARM cores, cell BE, and GPUs), this will become a multiplication by zero, which is incorrect.
The "safe" range of divisors that can be optimized into reciprocal multiplies with regard to this issue, for any IEEE-754 type, is +/-[minNormal, 1/minNormal].
- Steve
On Mar 30, 2011, at 8:42 AM, Benjamin Kramer wrote:
> Author: d0k
> Date: Wed Mar 30 10:42:27 2011
> New Revision: 128545
>
> URL: http://llvm.org/viewvc/llvm-project?rev=128545&view=rev
> Log:
> Add APFloat::getExactInverse.
>
> The idea is, that if an ieee 754 float is divided by a power of two, we can
> turn the division into a cheaper multiplication. This function sees if we can
> get an exact multiplicative inverse for a divisor and returns it if possible.
>
> This is the hard part of PR9587.
>
> I tested many inputs against llvm-gcc's frotend implementation of this
> optimization and didn't find any difference. However, floating point is the
> land of weird edge cases, so any review would be appreciated.
>
> Modified:
> llvm/trunk/include/llvm/ADT/APFloat.h
> llvm/trunk/lib/Support/APFloat.cpp
> llvm/trunk/unittests/ADT/APFloatTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/APFloat.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=128545&r1=128544&r2=128545&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/APFloat.h (original)
> +++ llvm/trunk/include/llvm/ADT/APFloat.h Wed Mar 30 10:42:27 2011
> @@ -353,6 +353,10 @@
> unsigned FormatPrecision = 0,
> unsigned FormatMaxPadding = 3) const;
>
> + /// getExactInverse - If this value has an exact multiplicative inverse,
> + /// store it in inv and return true.
> + bool getExactInverse(APFloat *inv) const;
> +
> private:
>
> /* Trivial queries. */
>
> Modified: llvm/trunk/lib/Support/APFloat.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=128545&r1=128544&r2=128545&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Support/APFloat.cpp (original)
> +++ llvm/trunk/lib/Support/APFloat.cpp Wed Mar 30 10:42:27 2011
> @@ -3562,3 +3562,29 @@
> for (; I != NDigits; ++I)
> Str.push_back(buffer[NDigits-I-1]);
> }
> +
> +bool APFloat::getExactInverse(APFloat *inv) const {
> + // We can only guarantee the existance of an exact inverse for IEEE floats.
> + if (semantics != &IEEEhalf && semantics != &IEEEsingle &&
> + semantics != &IEEEdouble && semantics != &IEEEquad)
> + return false;
> +
> + // Special floats and denormals have no exact inverse.
> + if (category != fcNormal)
> + return false;
> +
> + // Check that the number is a power of two by making sure that only the
> + // integer bit is set in the significand.
> + if (significandLSB() != semantics->precision - 1)
> + return false;
> +
> + // Get the inverse.
> + APFloat reciprocal(*semantics, 1ULL);
> + if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK)
> + return false;
> +
> + if (inv)
> + *inv = reciprocal;
> +
> + return true;
> +}
>
> Modified: llvm/trunk/unittests/ADT/APFloatTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APFloatTest.cpp?rev=128545&r1=128544&r2=128545&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/ADT/APFloatTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/APFloatTest.cpp Wed Mar 30 10:42:27 2011
> @@ -576,4 +576,27 @@
> #endif
> #endif
>
> +TEST(APFloatTest, exactInverse) {
> + APFloat inv(0.0f);
> +
> + // Trivial operation.
> + EXPECT_TRUE(APFloat(2.0).getExactInverse(&inv));
> + EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5)));
> + EXPECT_TRUE(APFloat(2.0f).getExactInverse(&inv));
> + EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5f)));
> +
> + // FLT_MIN
> + EXPECT_TRUE(APFloat(1.17549435e-38f).getExactInverse(&inv));
> + EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(8.5070592e+37f)));
> +
> + // Large float
> + EXPECT_TRUE(APFloat(1.7014118e38f).getExactInverse(&inv));
> + EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(5.8774718e-39f)));
> +
> + // Zero
> + EXPECT_FALSE(APFloat(0.0).getExactInverse(0));
> + // Denormalized float
> + EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(0));
> +}
> +
> }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list