mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 19:31:58 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128545 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d01f2633b9
commit
2746000f4f
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user