[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