Index: llvm/include/llvm/ADT/APFloat.h =================================================================== --- llvm/include/llvm/ADT/APFloat.h +++ llvm/include/llvm/ADT/APFloat.h @@ -232,11 +232,6 @@ /// \name Convenience "constructors" /// @{ - /// Returns a float which is bitcasted from an all one value int. - /// - /// \param BitWidth - Select float type - static IEEEFloat getAllOnesValue(unsigned BitWidth); - /// @} /// Used to insert APFloat objects, or objects that contain APFloat objects, @@ -645,8 +640,11 @@ IEEEFloat IEEE; DoubleAPFloat Double; - explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {} - explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {} + explicit Storage(IEEEFloat F, const fltSemantics &S); + explicit Storage(DoubleAPFloat F, const fltSemantics &S) + : Double(std::move(F)) { + assert(&S == &PPCDoubleDouble); + } template Storage(const fltSemantics &Semantics, ArgTypes &&... Args) { @@ -770,8 +768,9 @@ llvm_unreachable("This is a workaround for old clang."); } - explicit APFloat(IEEEFloat F) : U(std::move(F)) {} - explicit APFloat(DoubleAPFloat F) : U(std::move(F)) {} + explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {} + explicit APFloat(DoubleAPFloat F, const fltSemantics &S) + : U(std::move(F), S) {} public: APFloat(const fltSemantics &Semantics) : U(Semantics) {} @@ -781,8 +780,8 @@ APFloat(const fltSemantics &Semantics, uninitializedTag) : U(Semantics, uninitialized) {} APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {} - explicit APFloat(double d) : U(IEEEFloat(d)) {} - explicit APFloat(float f) : U(IEEEFloat(f)) {} + explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble) {} + explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle) {} APFloat(const APFloat &RHS) = default; APFloat(APFloat &&RHS) = default; @@ -881,14 +880,7 @@ /// /// \param BitWidth - Select float type /// \param isIEEE - If 128 bit number, select between PPC and IEEE - static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false) { - if (isIEEE) { - return APFloat(IEEEFloat::getAllOnesValue(BitWidth)); - } else { - assert(BitWidth == 128); - return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth)); - } - } + static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); } @@ -919,19 +911,19 @@ opStatus next(bool nextDown) { return getIEEE().next(nextDown); } APFloat operator+(const APFloat &RHS) const { - return APFloat(getIEEE() + RHS.getIEEE()); + return APFloat(getIEEE() + RHS.getIEEE(), getSemantics()); } APFloat operator-(const APFloat &RHS) const { - return APFloat(getIEEE() - RHS.getIEEE()); + return APFloat(getIEEE() - RHS.getIEEE(), getSemantics()); } APFloat operator*(const APFloat &RHS) const { - return APFloat(getIEEE() * RHS.getIEEE()); + return APFloat(getIEEE() * RHS.getIEEE(), getSemantics()); } APFloat operator/(const APFloat &RHS) const { - return APFloat(getIEEE() / RHS.getIEEE()); + return APFloat(getIEEE() / RHS.getIEEE(), getSemantics()); } void changeSign() { getIEEE().changeSign(); } @@ -939,7 +931,8 @@ void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); } static APFloat copySign(APFloat Value, const APFloat &Sign) { - return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE())); + return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()), + Value.getSemantics()); } opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, @@ -1035,7 +1028,7 @@ /// xlC compiler. hash_code hash_value(const APFloat &Arg); inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) { - return APFloat(scalbn(X.getIEEE(), Exp, RM)); + return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics()); } /// \brief Equivalent of C standard library function. @@ -1043,7 +1036,7 @@ /// While the C standard says Exp is an unspecified value for infinity and nan, /// this returns INT_MAX for infinities, and INT_MIN for NaNs. inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) { - return APFloat(frexp(X.getIEEE(), Exp, RM)); + return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics()); } /// \brief Returns the absolute value of the argument. inline APFloat abs(APFloat X) { Index: llvm/lib/Support/APFloat.cpp =================================================================== --- llvm/lib/Support/APFloat.cpp +++ llvm/lib/Support/APFloat.cpp @@ -3238,23 +3238,6 @@ llvm_unreachable(nullptr); } -IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) { - switch (BitWidth) { - case 16: - return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth)); - case 32: - return IEEEFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth)); - case 64: - return IEEEFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth)); - case 80: - return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth)); - case 128: - return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); - default: - llvm_unreachable("Unknown floating bit width"); - } -} - /// Make this number the largest magnitude normal number in the given /// semantics. void IEEEFloat::makeLargest(bool Negative) { @@ -3902,6 +3885,18 @@ } // End detail namespace +APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) { + if (usesLayout(Semantics)) { + new (&IEEE) IEEEFloat(std::move(F)); + } else if (usesLayout(Semantics)) { + new (&Double) + DoubleAPFloat(Semantics, APFloat(std::move(F), F.getSemantics()), + APFloat(IEEEdouble)); + } else { + llvm_unreachable("Unexpected semantics"); + } +} + APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) { return getIEEE().convertFromString(Str, RM); } @@ -3925,16 +3920,39 @@ assert(&ToSemantics == &PPCDoubleDouble); auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo); *this = APFloat( - DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble))); + DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)), + ToSemantics); return Ret; } else if (usesLayout(getSemantics()) && usesLayout(ToSemantics)) { auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo); - *this = APFloat(std::move(getIEEE())); + *this = APFloat(std::move(getIEEE()), ToSemantics); return Ret; } else { llvm_unreachable("Unexpected semantics"); } } +APFloat APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) { + if (isIEEE) { + switch (BitWidth) { + case 16: + return APFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth)); + case 32: + return APFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth)); + case 64: + return APFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth)); + case 80: + return APFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth)); + case 128: + return APFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); + default: + llvm_unreachable("Unknown floating bit width"); + } + } else { + assert(BitWidth == 128); + return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth)); + } +} + } // End llvm namespace Index: llvm/unittests/ADT/APFloatTest.cpp =================================================================== --- llvm/unittests/ADT/APFloatTest.cpp +++ llvm/unittests/ADT/APFloatTest.cpp @@ -1527,6 +1527,34 @@ // This is what we get with our 106-bit mantissa approximation EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]); #endif + + // PR30869 + { + auto Result = APFloat(APFloat::PPCDoubleDouble, "1.0") + + APFloat(APFloat::PPCDoubleDouble, "1.0"); + EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics()); + + Result = APFloat(APFloat::PPCDoubleDouble, "1.0") - + APFloat(APFloat::PPCDoubleDouble, "1.0"); + EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics()); + + Result = APFloat(APFloat::PPCDoubleDouble, "1.0") * + APFloat(APFloat::PPCDoubleDouble, "1.0"); + EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics()); + + Result = APFloat(APFloat::PPCDoubleDouble, "1.0") / + APFloat(APFloat::PPCDoubleDouble, "1.0"); + EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics()); + + int Exp; + Result = frexp(APFloat(APFloat::PPCDoubleDouble, "1.0"), Exp, + APFloat::rmNearestTiesToEven); + EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics()); + + Result = scalbn(APFloat(APFloat::PPCDoubleDouble, "1.0"), 1, + APFloat::rmNearestTiesToEven); + EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics()); + } } TEST(APFloatTest, isNegative) {