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.

llvm-svn: 128545
This commit is contained in:
Benjamin Kramer 2011-03-30 15:42:27 +00:00
parent 2298dee87a
commit 03fd672609
3 changed files with 53 additions and 0 deletions

View 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. */

View 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;
}

View 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));
}
}