Index: include/llvm/ADT/APFloat.h =================================================================== --- include/llvm/ADT/APFloat.h +++ include/llvm/ADT/APFloat.h @@ -511,16 +511,7 @@ /// 0 -> \c IEK_Zero /// Inf -> \c IEK_Inf /// - friend int ilogb(const APFloat &Arg) { - if (Arg.isNaN()) - return IEK_NaN; - if (Arg.isZero()) - return IEK_Zero; - if (Arg.isInfinity()) - return IEK_Inf; - - return Arg.exponent; - } + friend int ilogb(const APFloat &Arg); /// \brief Returns: X * 2^Exp for integral exponents. friend APFloat scalbn(APFloat X, int Exp, roundingMode); Index: lib/Support/APFloat.cpp =================================================================== --- lib/Support/APFloat.cpp +++ lib/Support/APFloat.cpp @@ -3945,6 +3945,24 @@ APInt::tcSet(significandParts(), 0, partCount()); } +int llvm::ilogb(const APFloat &Arg) { + if (Arg.isNaN()) + return APFloat::IEK_NaN; + if (Arg.isZero()) + return APFloat::IEK_Zero; + if (Arg.isInfinity()) + return APFloat::IEK_Inf; + if (!Arg.isDenormal()) + return Arg.exponent; + + APFloat Normalized(Arg); + int SignificandBits = Arg.getSemantics().precision - 1; + + Normalized.exponent += SignificandBits; + Normalized.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero); + return Normalized.exponent - SignificandBits; +} + APFloat llvm::scalbn(APFloat X, int Exp, APFloat::roundingMode RoundingMode) { auto MaxExp = X.getSemantics().maxExponent; auto MinExp = X.getSemantics().minExponent; Index: unittests/ADT/APFloatTest.cpp =================================================================== --- unittests/ADT/APFloatTest.cpp +++ unittests/ADT/APFloatTest.cpp @@ -2821,6 +2821,19 @@ } TEST(APFloatTest, ilogb) { + EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble, false))); + EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble, true))); + EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1024"))); + EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1023"))); + EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "-0x1.ffffffffffffep-1023"))); + EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble, "0x1p-51"))); + EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp-1023"))); + EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble, "0x0.ffffp-1"))); + EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble, "0x1.fffep-1023"))); + EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble, false))); + EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble, true))); + + EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+0"))); EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "-0x1p+0"))); EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+42"))); @@ -2841,8 +2854,9 @@ EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, false))); EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, true))); - EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false))); - EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true))); + + EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false))); + EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true))); EXPECT_EQ(-126, ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, false))); EXPECT_EQ(-126,