[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