forked from OSchip/llvm-project
[APFloat] Make functions that produce APFloaat objects use correct semantics.
Summary: Fixes PR30869. In D25977 I meant to change all functions that care about lifetime. I changed constructors, factory functions, but I missed member/free functions that return new instances. This patch changes them. Reviewers: hfinkel, kbarton, echristo, joerg Subscribers: llvm-commits, mehdi_amini Differential Revision: https://reviews.llvm.org/D26269 llvm-svn: 286060
This commit is contained in:
parent
5471fc29e4
commit
398f90f024
|
@ -232,11 +232,6 @@ public:
|
|||
/// \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 @@ class APFloat : public APFloatBase {
|
|||
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 <typename... ArgTypes>
|
||||
Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
|
||||
|
@ -770,8 +768,9 @@ class APFloat : public APFloatBase {
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
///
|
||||
/// \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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
/// 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 @@ inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
|
|||
/// 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) {
|
||||
|
|
|
@ -3238,23 +3238,6 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
|
|||
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 @@ DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
|
|||
|
||||
} // End detail namespace
|
||||
|
||||
APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
|
||||
if (usesLayout<IEEEFloat>(Semantics)) {
|
||||
new (&IEEE) IEEEFloat(std::move(F));
|
||||
} else if (usesLayout<DoubleAPFloat>(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 @@ APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
|
|||
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<DoubleAPFloat>(getSemantics()) &&
|
||||
usesLayout<IEEEFloat>(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
|
||||
|
|
|
@ -1527,6 +1527,34 @@ TEST(APFloatTest, PPCDoubleDouble) {
|
|||
// 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) {
|
||||
|
|
Loading…
Reference in New Issue