[llvm] r286060 - [APFloat] Make functions that produce APFloaat objects use correct semantics.
Tim Shen via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 6 00:38:38 PDT 2016
Author: timshen
Date: Sun Nov 6 01:38:37 2016
New Revision: 286060
URL: http://llvm.org/viewvc/llvm-project?rev=286060&view=rev
Log:
[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
Modified:
llvm/trunk/include/llvm/ADT/APFloat.h
llvm/trunk/lib/Support/APFloat.cpp
llvm/trunk/unittests/ADT/APFloatTest.cpp
Modified: llvm/trunk/include/llvm/ADT/APFloat.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=286060&r1=286059&r2=286060&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APFloat.h (original)
+++ llvm/trunk/include/llvm/ADT/APFloat.h Sun Nov 6 01:38:37 2016
@@ -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
/// 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) {
Modified: llvm/trunk/lib/Support/APFloat.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=286060&r1=286059&r2=286060&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Sun Nov 6 01:38:37 2016
@@ -3238,23 +3238,6 @@ void IEEEFloat::initFromAPInt(const fltS
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=(
} // 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
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
Modified: llvm/trunk/unittests/ADT/APFloatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APFloatTest.cpp?rev=286060&r1=286059&r2=286060&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APFloatTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APFloatTest.cpp Sun Nov 6 01:38:37 2016
@@ -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) {
More information about the llvm-commits
mailing list