OSDN Git Service

Avoid turning a floating point division with a constant power of two into a denormal...
authorBenjamin Kramer <benny.kra@googlemail.com>
Wed, 30 Mar 2011 17:02:54 +0000 (17:02 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Wed, 30 Mar 2011 17:02:54 +0000 (17:02 +0000)
Some platforms may treat denormals as zero, on other platforms multiplication
with a subnormal is slower than dividing by a normal.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128555 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/APFloat.cpp
test/Transforms/InstCombine/fdiv.ll
unittests/ADT/APFloatTest.cpp

index abe5575..3a63258 100644 (file)
@@ -3583,6 +3583,14 @@ bool APFloat::getExactInverse(APFloat *inv) const {
   if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK)
     return false;
 
+  // Avoid multiplication with a denormal, it is not safe on all platforms and
+  // may be slower than a normal division.
+  if (reciprocal.significandMSB() + 1 < reciprocal.semantics->precision)
+    return false;
+
+  assert(reciprocal.category == fcNormal &&
+         reciprocal.significandLSB() == reciprocal.semantics->precision - 1);
+
   if (inv)
     *inv = reciprocal;
 
index f4e0b48..a2cce01 100644 (file)
@@ -13,7 +13,7 @@ define float @test2(float %x) nounwind readnone ssp {
   ret float %div
 
 ; CHECK: @test2
-; CHECK-NEXT: fmul float %x, 0x3800000000000000
+; CHECK-NEXT: fdiv float %x, 0x47E0000000000000
 }
 
 define float @test3(float %x) nounwind readnone ssp {
index dea4a65..5f05b86 100644 (file)
@@ -589,10 +589,8 @@ TEST(APFloatTest, exactInverse) {
   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)));
-
+  // Large float, inverse is a denormal.
+  EXPECT_FALSE(APFloat(1.7014118e38f).getExactInverse(0));
   // Zero
   EXPECT_FALSE(APFloat(0.0).getExactInverse(0));
   // Denormalized float