Add APFloat::getExactInverse.
authorBenjamin Kramer <benny.kra@googlemail.com>
Wed, 30 Mar 2011 15:42:27 +0000 (15:42 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Wed, 30 Mar 2011 15:42:27 +0000 (15:42 +0000)
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.

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

include/llvm/ADT/APFloat.h
lib/Support/APFloat.cpp
unittests/ADT/APFloatTest.cpp

index ca4138b825a64373050152c59e18bba9752b8366..21b8c86d1d5b644ced60fb47727e7a79d1106f24 100644 (file)
@@ -353,6 +353,10 @@ namespace llvm {
                   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.  */
index 93806facff03a2bfd6bc8379386e63d563934549..abe55753181d6a7d7b42804ae276e1ae33e9e887 100644 (file)
@@ -3562,3 +3562,29 @@ void APFloat::toString(SmallVectorImpl<char> &Str,
   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;
+}
index 964b04da473c19b475417ba782bb7b9c70241ae0..dea4a65b88ae9580aa9986cd5f260ae1ea3b4721 100644 (file)
@@ -576,4 +576,27 @@ TEST(APFloatTest, StringHexadecimalExponentDeath) {
 #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));
+}
+
 }