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"
|
/// \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,
|
/// Used to insert APFloat objects, or objects that contain APFloat objects,
|
||||||
|
@ -645,8 +640,11 @@ class APFloat : public APFloatBase {
|
||||||
IEEEFloat IEEE;
|
IEEEFloat IEEE;
|
||||||
DoubleAPFloat Double;
|
DoubleAPFloat Double;
|
||||||
|
|
||||||
explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {}
|
explicit Storage(IEEEFloat F, const fltSemantics &S);
|
||||||
explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {}
|
explicit Storage(DoubleAPFloat F, const fltSemantics &S)
|
||||||
|
: Double(std::move(F)) {
|
||||||
|
assert(&S == &PPCDoubleDouble);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... ArgTypes>
|
template <typename... ArgTypes>
|
||||||
Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
|
Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
|
||||||
|
@ -770,8 +768,9 @@ class APFloat : public APFloatBase {
|
||||||
llvm_unreachable("This is a workaround for old clang.");
|
llvm_unreachable("This is a workaround for old clang.");
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit APFloat(IEEEFloat F) : U(std::move(F)) {}
|
explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {}
|
||||||
explicit APFloat(DoubleAPFloat F) : U(std::move(F)) {}
|
explicit APFloat(DoubleAPFloat F, const fltSemantics &S)
|
||||||
|
: U(std::move(F), S) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
APFloat(const fltSemantics &Semantics) : U(Semantics) {}
|
APFloat(const fltSemantics &Semantics) : U(Semantics) {}
|
||||||
|
@ -781,8 +780,8 @@ public:
|
||||||
APFloat(const fltSemantics &Semantics, uninitializedTag)
|
APFloat(const fltSemantics &Semantics, uninitializedTag)
|
||||||
: U(Semantics, uninitialized) {}
|
: U(Semantics, uninitialized) {}
|
||||||
APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {}
|
APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {}
|
||||||
explicit APFloat(double d) : U(IEEEFloat(d)) {}
|
explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble) {}
|
||||||
explicit APFloat(float f) : U(IEEEFloat(f)) {}
|
explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle) {}
|
||||||
APFloat(const APFloat &RHS) = default;
|
APFloat(const APFloat &RHS) = default;
|
||||||
APFloat(APFloat &&RHS) = default;
|
APFloat(APFloat &&RHS) = default;
|
||||||
|
|
||||||
|
@ -881,14 +880,7 @@ public:
|
||||||
///
|
///
|
||||||
/// \param BitWidth - Select float type
|
/// \param BitWidth - Select float type
|
||||||
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
||||||
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false) {
|
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
|
void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
|
||||||
|
|
||||||
|
@ -919,19 +911,19 @@ public:
|
||||||
opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
|
opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
|
||||||
|
|
||||||
APFloat operator+(const APFloat &RHS) const {
|
APFloat operator+(const APFloat &RHS) const {
|
||||||
return APFloat(getIEEE() + RHS.getIEEE());
|
return APFloat(getIEEE() + RHS.getIEEE(), getSemantics());
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat operator-(const APFloat &RHS) const {
|
APFloat operator-(const APFloat &RHS) const {
|
||||||
return APFloat(getIEEE() - RHS.getIEEE());
|
return APFloat(getIEEE() - RHS.getIEEE(), getSemantics());
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat operator*(const APFloat &RHS) const {
|
APFloat operator*(const APFloat &RHS) const {
|
||||||
return APFloat(getIEEE() * RHS.getIEEE());
|
return APFloat(getIEEE() * RHS.getIEEE(), getSemantics());
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat operator/(const APFloat &RHS) const {
|
APFloat operator/(const APFloat &RHS) const {
|
||||||
return APFloat(getIEEE() / RHS.getIEEE());
|
return APFloat(getIEEE() / RHS.getIEEE(), getSemantics());
|
||||||
}
|
}
|
||||||
|
|
||||||
void changeSign() { getIEEE().changeSign(); }
|
void changeSign() { getIEEE().changeSign(); }
|
||||||
|
@ -939,7 +931,8 @@ public:
|
||||||
void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
|
void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
|
||||||
|
|
||||||
static APFloat copySign(APFloat Value, const APFloat &Sign) {
|
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,
|
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
|
||||||
|
@ -1035,7 +1028,7 @@ public:
|
||||||
/// xlC compiler.
|
/// xlC compiler.
|
||||||
hash_code hash_value(const APFloat &Arg);
|
hash_code hash_value(const APFloat &Arg);
|
||||||
inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
|
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.
|
/// \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,
|
/// 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.
|
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
|
||||||
inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
|
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.
|
/// \brief Returns the absolute value of the argument.
|
||||||
inline APFloat abs(APFloat X) {
|
inline APFloat abs(APFloat X) {
|
||||||
|
|
|
@ -3238,23 +3238,6 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
|
||||||
llvm_unreachable(nullptr);
|
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
|
/// Make this number the largest magnitude normal number in the given
|
||||||
/// semantics.
|
/// semantics.
|
||||||
void IEEEFloat::makeLargest(bool Negative) {
|
void IEEEFloat::makeLargest(bool Negative) {
|
||||||
|
@ -3902,6 +3885,18 @@ DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
|
||||||
|
|
||||||
} // End detail namespace
|
} // 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) {
|
APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
|
||||||
return getIEEE().convertFromString(Str, RM);
|
return getIEEE().convertFromString(Str, RM);
|
||||||
}
|
}
|
||||||
|
@ -3925,16 +3920,39 @@ APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
|
||||||
assert(&ToSemantics == &PPCDoubleDouble);
|
assert(&ToSemantics == &PPCDoubleDouble);
|
||||||
auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo);
|
auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo);
|
||||||
*this = APFloat(
|
*this = APFloat(
|
||||||
DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)));
|
DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)),
|
||||||
|
ToSemantics);
|
||||||
return Ret;
|
return Ret;
|
||||||
} else if (usesLayout<DoubleAPFloat>(getSemantics()) &&
|
} else if (usesLayout<DoubleAPFloat>(getSemantics()) &&
|
||||||
usesLayout<IEEEFloat>(ToSemantics)) {
|
usesLayout<IEEEFloat>(ToSemantics)) {
|
||||||
auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
|
auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
|
||||||
*this = APFloat(std::move(getIEEE()));
|
*this = APFloat(std::move(getIEEE()), ToSemantics);
|
||||||
return Ret;
|
return Ret;
|
||||||
} else {
|
} else {
|
||||||
llvm_unreachable("Unexpected semantics");
|
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
|
} // End llvm namespace
|
||||||
|
|
|
@ -1527,6 +1527,34 @@ TEST(APFloatTest, PPCDoubleDouble) {
|
||||||
// This is what we get with our 106-bit mantissa approximation
|
// This is what we get with our 106-bit mantissa approximation
|
||||||
EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
|
EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
|
||||||
#endif
|
#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) {
|
TEST(APFloatTest, isNegative) {
|
||||||
|
|
Loading…
Reference in New Issue