[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:14:17 PDT 2011
Note also that even on many platforms where denormals are supported, multiplication by a denormal can be slower than division by a normal number.
- Steve
On Mar 30, 2011, at 9:11 AM, Stephen Canon wrote:
> 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
>
> _______________________________________________
> 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