Skip to content

Commit

Permalink
[APFloat] Make functions that produce APFloaat objects use correct se…
Browse files Browse the repository at this point in the history
…mantics.

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
  • Loading branch information
timshen91 committed Nov 6, 2016
1 parent 5471fc2 commit 398f90f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 45 deletions.
45 changes: 19 additions & 26 deletions llvm/include/llvm/ADT/APFloat.h
Expand Up @@ -232,11 +232,6 @@ class IEEEFloat final : public APFloatBase {
/// \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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {}
Expand All @@ -781,8 +780,8 @@ class APFloat : public APFloatBase {
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;

Expand Down Expand Up @@ -881,14 +880,7 @@ class APFloat : public APFloatBase {
///
/// \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); }

Expand Down Expand Up @@ -919,27 +911,28 @@ class APFloat : public APFloatBase {
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(); }
void clearSign() { getIEEE().clearSign(); }
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,
Expand Down Expand Up @@ -1035,15 +1028,15 @@ class APFloat : public APFloatBase {
/// 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.
///
/// 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) {
Expand Down
56 changes: 37 additions & 19 deletions llvm/lib/Support/APFloat.cpp
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -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
28 changes: 28 additions & 0 deletions llvm/unittests/ADT/APFloatTest.cpp
Expand Up @@ -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) {
Expand Down

0 comments on commit 398f90f

Please sign in to comment.