Index: llvm/include/llvm/ADT/APFloat.h =================================================================== --- llvm/include/llvm/ADT/APFloat.h +++ llvm/include/llvm/ADT/APFloat.h @@ -489,10 +489,17 @@ /// return true. bool getExactInverse(APFloat *inv) const; + // If this is an exact power of two, return the exponent while ignoring the + // sign bit. If it's not an exact power of 2, return INT_MIN + LLVM_READONLY + int getExactLog2Abs() const; + // If this is an exact power of two, return the exponent. If it's not an exact // power of 2, return INT_MIN LLVM_READONLY - int getExactLog2() const; + inline int getExactLog2() const { + return isNegative() ? INT_MIN : getExactLog2Abs(); + } /// Returns the exponent of the internal representation of the APFloat. /// @@ -754,6 +761,8 @@ LLVM_READONLY int getExactLog2() const; + LLVM_READONLY + int getExactLog2Abs() const; friend DoubleAPFloat scalbn(const DoubleAPFloat &X, int Exp, roundingMode); friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode); @@ -1324,6 +1333,11 @@ APFLOAT_DISPATCH_ON_SEMANTICS(getExactInverse(inv)); } + LLVM_READONLY + int getExactLog2Abs() const { + APFLOAT_DISPATCH_ON_SEMANTICS(getExactLog2Abs()); + } + LLVM_READONLY int getExactLog2() const { APFLOAT_DISPATCH_ON_SEMANTICS(getExactLog2()); Index: llvm/lib/Support/APFloat.cpp =================================================================== --- llvm/lib/Support/APFloat.cpp +++ llvm/lib/Support/APFloat.cpp @@ -4292,8 +4292,8 @@ return true; } -int IEEEFloat::getExactLog2() const { - if (!isFinite() || isZero() || isNegative()) +int IEEEFloat::getExactLog2Abs() const { + if (!isFinite() || isZero()) return INT_MIN; const integerPart *Parts = significandParts(); @@ -5121,6 +5121,11 @@ return INT_MIN; } +int DoubleAPFloat::getExactLog2Abs() const { + // TODO: Implement me + return INT_MIN; +} + DoubleAPFloat scalbn(const DoubleAPFloat &Arg, int Exp, APFloat::roundingMode RM) { assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics"); Index: llvm/unittests/ADT/APFloatTest.cpp =================================================================== --- llvm/unittests/ADT/APFloatTest.cpp +++ llvm/unittests/ADT/APFloatTest.cpp @@ -6597,6 +6597,7 @@ if (I == APFloat::S_PPCDoubleDouble) { // Not implemented EXPECT_EQ(INT_MIN, One.getExactLog2()); + EXPECT_EQ(INT_MIN, One.getExactLog2Abs()); continue; } @@ -6607,10 +6608,16 @@ EXPECT_EQ(0, One.getExactLog2()); EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2()); EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat(Semantics, "3.0").getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat(Semantics, "-3.0").getExactLog2Abs()); EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2()); EXPECT_EQ(INT_MIN, APFloat(Semantics, "-8.0").getExactLog2()); - EXPECT_EQ(INT_MIN, APFloat(Semantics, "-0.25").getExactLog2()); EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2()); + EXPECT_EQ(-2, APFloat(Semantics, "0.25").getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat(Semantics, "-0.25").getExactLog2()); + EXPECT_EQ(-2, APFloat(Semantics, "-0.25").getExactLog2Abs()); + EXPECT_EQ(3, APFloat(Semantics, "8.0").getExactLog2Abs()); + EXPECT_EQ(3, APFloat(Semantics, "-8.0").getExactLog2Abs()); EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2()); EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2()); @@ -6619,6 +6626,13 @@ EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2()); EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, false).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getZero(Semantics, true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getInf(Semantics, true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, false).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, APFloat::getNaN(Semantics, true).getExactLog2Abs()); + EXPECT_EQ(INT_MIN, scalbn(One, MinExp - Precision - 1, APFloat::rmNearestTiesToEven) .getExactLog2());