Skip to content

Commit 0a7eabc

Browse files
committed
Reapply "[APFloat] Fix getExactInverse for DoubleAPFloat"
The previous implementation of getExactInverse used the following check to identify powers of two: // 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; This condition verifies that the only set bit in the significand is the integer bit, which is correct for normal numbers. However, this logic is not correct for subnormal values. APFloat represents subnormal numbers by shifting the significand right while holding the exponent at its minimum value. For a power of two in the subnormal range, its single set bit will therefore be at a position lower than precision - 1. The original check would consequently fail, causing the function to determine that these numbers do not have an exact multiplicative inverse. The new logic calculated this correctly but it seems that test/CodeGen/Thumb2/mve-vcvt-fixed-to-float.ll expected the old behavior. Seeing as how getExactInverse does not have tests or documentation, we conservatively maintain (and document) this behavior. This reverts commit 47e62e8.
1 parent cbfa265 commit 0a7eabc

File tree

3 files changed

+74
-52
lines changed

3 files changed

+74
-52
lines changed

llvm/include/llvm/ADT/APFloat.h

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -605,10 +605,6 @@ class IEEEFloat final {
605605
unsigned FormatMaxPadding = 3,
606606
bool TruncateZero = true) const;
607607

608-
/// If this value has an exact multiplicative inverse, store it in inv and
609-
/// return true.
610-
LLVM_ABI bool getExactInverse(APFloat *inv) const;
611-
612608
LLVM_ABI LLVM_READONLY int getExactLog2Abs() const;
613609

614610
LLVM_ABI friend int ilogb(const IEEEFloat &Arg);
@@ -886,8 +882,6 @@ class DoubleAPFloat final {
886882
unsigned FormatMaxPadding,
887883
bool TruncateZero = true) const;
888884

889-
LLVM_ABI bool getExactInverse(APFloat *inv) const;
890-
891885
LLVM_ABI LLVM_READONLY int getExactLog2Abs() const;
892886

893887
LLVM_ABI friend int ilogb(const DoubleAPFloat &X);
@@ -1500,9 +1494,9 @@ class APFloat : public APFloatBase {
15001494
LLVM_DUMP_METHOD void dump() const;
15011495
#endif
15021496

1503-
bool getExactInverse(APFloat *inv) const {
1504-
APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv));
1505-
}
1497+
/// If this value is normal and has an exact, normal, multiplicative inverse,
1498+
/// store it in inv and return true.
1499+
bool getExactInverse(APFloat *Inv) const;
15061500

15071501
// If this is an exact power of two, return the exponent while ignoring the
15081502
// sign bit. If it's not an exact power of 2, return INT_MIN

llvm/lib/Support/APFloat.cpp

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4575,35 +4575,6 @@ void IEEEFloat::toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
45754575

45764576
}
45774577

4578-
bool IEEEFloat::getExactInverse(APFloat *inv) const {
4579-
// Special floats and denormals have no exact inverse.
4580-
if (!isFiniteNonZero())
4581-
return false;
4582-
4583-
// Check that the number is a power of two by making sure that only the
4584-
// integer bit is set in the significand.
4585-
if (significandLSB() != semantics->precision - 1)
4586-
return false;
4587-
4588-
// Get the inverse.
4589-
IEEEFloat reciprocal(*semantics, 1ULL);
4590-
if (reciprocal.divide(*this, rmNearestTiesToEven) != opOK)
4591-
return false;
4592-
4593-
// Avoid multiplication with a denormal, it is not safe on all platforms and
4594-
// may be slower than a normal division.
4595-
if (reciprocal.isDenormal())
4596-
return false;
4597-
4598-
assert(reciprocal.isFiniteNonZero() &&
4599-
reciprocal.significandLSB() == reciprocal.semantics->precision - 1);
4600-
4601-
if (inv)
4602-
*inv = APFloat(reciprocal, *semantics);
4603-
4604-
return true;
4605-
}
4606-
46074578
int IEEEFloat::getExactLog2Abs() const {
46084579
if (!isFinite() || isZero())
46094580
return INT_MIN;
@@ -5731,17 +5702,6 @@ void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
57315702
.toString(Str, FormatPrecision, FormatMaxPadding, TruncateZero);
57325703
}
57335704

5734-
bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
5735-
assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
5736-
APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
5737-
if (!inv)
5738-
return Tmp.getExactInverse(nullptr);
5739-
APFloat Inv(semPPCDoubleDoubleLegacy);
5740-
auto Ret = Tmp.getExactInverse(&Inv);
5741-
*inv = APFloat(semPPCDoubleDouble, Inv.bitcastToAPInt());
5742-
return Ret;
5743-
}
5744-
57455705
int DoubleAPFloat::getExactLog2Abs() const {
57465706
// In order for Hi + Lo to be a power of two, the following must be true:
57475707
// 1. Hi must be a power of two.
@@ -5926,6 +5886,64 @@ FPClassTest APFloat::classify() const {
59265886
return isSignaling() ? fcSNan : fcQNan;
59275887
}
59285888

5889+
bool APFloat::getExactInverse(APFloat *Inv) const {
5890+
// Only finite, non-zero numbers can have a useful, representable inverse.
5891+
// This check filters out +/- zero, +/- infinity, and NaN.
5892+
if (!isFiniteNonZero())
5893+
return false;
5894+
5895+
// Historically, this function rejects subnormal inputs. One reason why this
5896+
// might be important is that subnormals may behave differently under FTZ/DAZ
5897+
// runtime behavior.
5898+
if (isDenormal())
5899+
return false;
5900+
5901+
// A number has an exact, representable inverse if and only if it is a power
5902+
// of two.
5903+
//
5904+
// Mathematical Rationale:
5905+
// 1. A binary floating-point number x is a dyadic rational, meaning it can
5906+
// be written as x = M / 2^k for integers M (the significand) and k.
5907+
// 2. The inverse is 1/x = 2^k / M.
5908+
// 3. For 1/x to also be a dyadic rational (and thus exactly representable
5909+
// in binary), its denominator M must also be a power of two.
5910+
// Let's say M = 2^m.
5911+
// 4. Substituting this back into the formula for x, we get
5912+
// x = (2^m) / (2^k) = 2^(m-k).
5913+
//
5914+
// This proves that x must be a power of two.
5915+
5916+
// getExactLog2Abs() returns the integer exponent if the number is a power of
5917+
// two or INT_MIN if it is not.
5918+
const int Exp = getExactLog2Abs();
5919+
if (Exp == INT_MIN)
5920+
return false;
5921+
5922+
// The inverse of +/- 2^Exp is +/- 2^(-Exp). We can compute this by
5923+
// scaling 1.0 by the negated exponent.
5924+
APFloat Reciprocal =
5925+
scalbn(APFloat::getOne(getSemantics(), /*Negative=*/isNegative()), -Exp,
5926+
rmTowardZero);
5927+
5928+
// scalbn might round if the resulting exponent -Exp is outside the
5929+
// representable range, causing overflow (to infinity) or underflow. We
5930+
// must verify that the result is still the exact power of two we expect.
5931+
if (Reciprocal.getExactLog2Abs() != -Exp)
5932+
return false;
5933+
5934+
// Avoid multiplication with a subnormal, it is not safe on all platforms and
5935+
// may be slower than a normal division.
5936+
if (Reciprocal.isDenormal())
5937+
return false;
5938+
5939+
assert(Reciprocal.isFiniteNonZero());
5940+
5941+
if (Inv)
5942+
*Inv = std::move(Reciprocal);
5943+
5944+
return true;
5945+
}
5946+
59295947
APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
59305948
roundingMode RM, bool *losesInfo) {
59315949
if (&getSemantics() == &ToSemantics) {

llvm/unittests/ADT/APFloatTest.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1918,6 +1918,15 @@ TEST(APFloatTest, exactInverse) {
19181918
EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::PPCDoubleDouble(), "0.5")));
19191919
EXPECT_TRUE(APFloat(APFloat::x87DoubleExtended(), "2.0").getExactInverse(&inv));
19201920
EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::x87DoubleExtended(), "0.5")));
1921+
// 0x1p1022 has a normal inverse for IEEE 754 binary64: 0x1p-1022.
1922+
EXPECT_TRUE(APFloat(0x1p1022).getExactInverse(&inv));
1923+
EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0x1p-1022)));
1924+
// With regards to getExactInverse, IEEEdouble and PPCDoubleDouble should
1925+
// behave the same.
1926+
EXPECT_TRUE(
1927+
APFloat(APFloat::PPCDoubleDouble(), "0x1p1022").getExactInverse(&inv));
1928+
EXPECT_TRUE(
1929+
inv.bitwiseIsEqual(APFloat(APFloat::PPCDoubleDouble(), "0x1p-1022")));
19211930

19221931
// FLT_MIN
19231932
EXPECT_TRUE(APFloat(1.17549435e-38f).getExactInverse(&inv));
@@ -1929,6 +1938,8 @@ TEST(APFloatTest, exactInverse) {
19291938
EXPECT_FALSE(APFloat(0.0).getExactInverse(nullptr));
19301939
// Denormalized float
19311940
EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(nullptr));
1941+
// Largest subnormal
1942+
EXPECT_FALSE(APFloat(0x1p-127f).getExactInverse(nullptr));
19321943
}
19331944

19341945
TEST(APFloatTest, roundToIntegral) {
@@ -6661,13 +6672,12 @@ TEST_P(PPCDoubleDoubleFrexpValueTest, PPCDoubleDoubleFrexp) {
66616672

66626673
int ActualExponent;
66636674
const APFloat ActualFraction = frexp(Input, ActualExponent, RM);
6664-
if (ExpectedFraction.isNaN()) {
6675+
if (ExpectedFraction.isNaN())
66656676
EXPECT_TRUE(ActualFraction.isNaN());
6666-
} else {
6677+
else
66676678
EXPECT_EQ(ActualFraction.compare(ExpectedFraction), APFloat::cmpEqual)
66686679
<< ActualFraction << " vs " << ExpectedFraction << " for input "
66696680
<< Params.Input.Hi << " + " << Params.Input.Lo << " RM " << RM;
6670-
}
66716681
EXPECT_EQ(ActualExponent, Expected.Exponent)
66726682
<< "for input " << Params.Input.Hi << " + " << Params.Input.Lo
66736683
<< " RM " << RM;

0 commit comments

Comments
 (0)