Index: lib/Support/APFloat.cpp =================================================================== --- lib/Support/APFloat.cpp +++ lib/Support/APFloat.cpp @@ -3951,13 +3951,19 @@ auto MaxExp = X.getSemantics().maxExponent; auto MinExp = X.getSemantics().minExponent; - if (Exp > (MaxExp - X.exponent)) + + if (Exp + X.exponent > (MaxExp - MinExp + 1)) { // Overflow saturates to infinity. return APFloat::getInf(X.getSemantics(), X.isNegative()); - if (Exp < (MinExp - X.exponent)) + } + + if (Exp + X.exponent < (MinExp - MaxExp - 1)) { // Underflow saturates to zero. return APFloat::getZero(X.getSemantics(), X.isNegative()); + } X.exponent += Exp; + + X.normalize(APFloat::rmNearestTiesToEven, lfExactlyZero); return X; } Index: unittests/ADT/APFloatTest.cpp =================================================================== --- unittests/ADT/APFloatTest.cpp +++ unittests/ADT/APFloatTest.cpp @@ -2883,12 +2883,104 @@ EXPECT_TRUE( PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+127"), 1))); EXPECT_TRUE(PZero.bitwiseIsEqual( - scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -127))); + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-127"), -127))); EXPECT_TRUE(MZero.bitwiseIsEqual( - scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), -127))); + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p-127"), -127))); + EXPECT_TRUE(APFloat(APFloat::IEEEsingle, "-0x1p-149").bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p-127"), -22))); EXPECT_TRUE(PZero.bitwiseIsEqual( - scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); - EXPECT_TRUE(PZero.bitwiseIsEqual( - scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -24))); + + + APFloat SmallestF64 = APFloat::getSmallest(APFloat::IEEEdouble, false); + APFloat NegSmallestF64 = APFloat::getSmallest(APFloat::IEEEdouble, true); + + APFloat LargestF64 = APFloat::getLargest(APFloat::IEEEdouble, false); + APFloat NegLargestF64 = APFloat::getLargest(APFloat::IEEEdouble, true); + + APFloat SmallestNormalizedF64 = APFloat::getSmallestNormalized(APFloat::IEEEdouble, false); + APFloat NegSmallestNormalizedF64 = APFloat::getSmallestNormalized(APFloat::IEEEdouble, true); + + APFloat LargestDenormalF64(APFloat::IEEEdouble, "0x1.ffffffffffffep-1023"); + APFloat NegLargestDenormalF64(APFloat::IEEEdouble, "-0x1.ffffffffffffep-1023"); + + + EXPECT_TRUE(SmallestF64.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble, "0x1p-1074"), 0))); + EXPECT_TRUE(NegSmallestF64.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble, "-0x1p-1074"), 0))); + + + EXPECT_TRUE(scalbn(SmallestF64, -2098).isZero()); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1p+1023").bitwiseIsEqual(scalbn(SmallestF64, 2097))); + EXPECT_TRUE(scalbn(SmallestF64, 2098).isInfinity()); + EXPECT_TRUE(scalbn(SmallestF64, 2099).isInfinity()); + + + EXPECT_TRUE(LargestDenormalF64.bitwiseIsEqual(scalbn(LargestDenormalF64, 0))); + EXPECT_TRUE(NegLargestDenormalF64.bitwiseIsEqual(scalbn(NegLargestDenormalF64, 0))); + + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1022") + .bitwiseIsEqual(scalbn(LargestDenormalF64, 1))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "-0x1.ffffffffffffep-1021") + .bitwiseIsEqual(scalbn(NegLargestDenormalF64, 2))); + + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep+1") + .bitwiseIsEqual(scalbn(LargestDenormalF64, 1024))); + EXPECT_TRUE(scalbn(LargestDenormalF64, -1023).isZero()); + EXPECT_TRUE(scalbn(LargestDenormalF64, -1024).isZero()); + EXPECT_TRUE(scalbn(LargestDenormalF64, -2048).isZero()); + EXPECT_TRUE(scalbn(LargestDenormalF64, 2047).isInfinity()); + EXPECT_TRUE(scalbn(LargestDenormalF64, 2098).isInfinity()); + EXPECT_TRUE(scalbn(LargestDenormalF64, 2099).isInfinity()); + + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-2") + .bitwiseIsEqual(scalbn(LargestDenormalF64, 1021))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep-1") + .bitwiseIsEqual(scalbn(LargestDenormalF64, 1022))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep+0") + .bitwiseIsEqual(scalbn(LargestDenormalF64, 1023))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.ffffffffffffep+1023") + .bitwiseIsEqual(scalbn(LargestDenormalF64, 2046))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1p+974") + .bitwiseIsEqual(scalbn(SmallestF64, 2048))); + + APFloat RandomDenormalF64(APFloat::IEEEdouble, "0x1.c60f120d9f87cp+51"); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp-972") + .bitwiseIsEqual(scalbn(RandomDenormalF64, -1023))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp-1") + .bitwiseIsEqual(scalbn(RandomDenormalF64, -52))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp-2") + .bitwiseIsEqual(scalbn(RandomDenormalF64, -53))); + EXPECT_TRUE(APFloat(APFloat::IEEEdouble, "0x1.c60f120d9f87cp+0") + .bitwiseIsEqual(scalbn(RandomDenormalF64, -51))); + + EXPECT_TRUE(scalbn(RandomDenormalF64, -2097).isZero()); + EXPECT_TRUE(scalbn(RandomDenormalF64, -2090).isZero()); + + EXPECT_TRUE( + APFloat(APFloat::IEEEdouble, "-0x1p-1073") + .bitwiseIsEqual(scalbn(NegLargestF64, -2097))); + + EXPECT_TRUE( + APFloat(APFloat::IEEEdouble, "-0x1p-1024") + .bitwiseIsEqual(scalbn(NegLargestF64, -2048))); + + EXPECT_TRUE( + APFloat(APFloat::IEEEdouble, "0x1p-1073") + .bitwiseIsEqual(scalbn(LargestF64, -2097))); + + EXPECT_TRUE( + APFloat(APFloat::IEEEdouble, "0x1p-1074") + .bitwiseIsEqual(scalbn(LargestF64, -2098))); + + EXPECT_TRUE(scalbn(NegLargestF64, -2099).isZero()); + EXPECT_TRUE(scalbn(LargestF64, 1).isInfinity()); + + EXPECT_TRUE( + APFloat(APFloat::IEEEdouble, "0x1p+0") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble, "0x1p+52"), -52))); + + EXPECT_TRUE( + APFloat(APFloat::IEEEdouble, "0x1p-103") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble, "0x1p-51"), -52))); } }