Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit c7524ad

Browse files
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286060 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e7c8559 commit c7524ad

File tree

3 files changed

+84
-45
lines changed

3 files changed

+84
-45
lines changed

include/llvm/ADT/APFloat.h

+19-26
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,6 @@ class IEEEFloat final : public APFloatBase {
232232
/// \name Convenience "constructors"
233233
/// @{
234234

235-
/// Returns a float which is bitcasted from an all one value int.
236-
///
237-
/// \param BitWidth - Select float type
238-
static IEEEFloat getAllOnesValue(unsigned BitWidth);
239-
240235
/// @}
241236

242237
/// Used to insert APFloat objects, or objects that contain APFloat objects,
@@ -645,8 +640,11 @@ class APFloat : public APFloatBase {
645640
IEEEFloat IEEE;
646641
DoubleAPFloat Double;
647642

648-
explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {}
649-
explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {}
643+
explicit Storage(IEEEFloat F, const fltSemantics &S);
644+
explicit Storage(DoubleAPFloat F, const fltSemantics &S)
645+
: Double(std::move(F)) {
646+
assert(&S == &PPCDoubleDouble);
647+
}
650648

651649
template <typename... ArgTypes>
652650
Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
@@ -770,8 +768,9 @@ class APFloat : public APFloatBase {
770768
llvm_unreachable("This is a workaround for old clang.");
771769
}
772770

773-
explicit APFloat(IEEEFloat F) : U(std::move(F)) {}
774-
explicit APFloat(DoubleAPFloat F) : U(std::move(F)) {}
771+
explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {}
772+
explicit APFloat(DoubleAPFloat F, const fltSemantics &S)
773+
: U(std::move(F), S) {}
775774

776775
public:
777776
APFloat(const fltSemantics &Semantics) : U(Semantics) {}
@@ -781,8 +780,8 @@ class APFloat : public APFloatBase {
781780
APFloat(const fltSemantics &Semantics, uninitializedTag)
782781
: U(Semantics, uninitialized) {}
783782
APFloat(const fltSemantics &Semantics, const APInt &I) : U(Semantics, I) {}
784-
explicit APFloat(double d) : U(IEEEFloat(d)) {}
785-
explicit APFloat(float f) : U(IEEEFloat(f)) {}
783+
explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble) {}
784+
explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle) {}
786785
APFloat(const APFloat &RHS) = default;
787786
APFloat(APFloat &&RHS) = default;
788787

@@ -881,14 +880,7 @@ class APFloat : public APFloatBase {
881880
///
882881
/// \param BitWidth - Select float type
883882
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
884-
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false) {
885-
if (isIEEE) {
886-
return APFloat(IEEEFloat::getAllOnesValue(BitWidth));
887-
} else {
888-
assert(BitWidth == 128);
889-
return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
890-
}
891-
}
883+
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
892884

893885
void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
894886

@@ -919,27 +911,28 @@ class APFloat : public APFloatBase {
919911
opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
920912

921913
APFloat operator+(const APFloat &RHS) const {
922-
return APFloat(getIEEE() + RHS.getIEEE());
914+
return APFloat(getIEEE() + RHS.getIEEE(), getSemantics());
923915
}
924916

925917
APFloat operator-(const APFloat &RHS) const {
926-
return APFloat(getIEEE() - RHS.getIEEE());
918+
return APFloat(getIEEE() - RHS.getIEEE(), getSemantics());
927919
}
928920

929921
APFloat operator*(const APFloat &RHS) const {
930-
return APFloat(getIEEE() * RHS.getIEEE());
922+
return APFloat(getIEEE() * RHS.getIEEE(), getSemantics());
931923
}
932924

933925
APFloat operator/(const APFloat &RHS) const {
934-
return APFloat(getIEEE() / RHS.getIEEE());
926+
return APFloat(getIEEE() / RHS.getIEEE(), getSemantics());
935927
}
936928

937929
void changeSign() { getIEEE().changeSign(); }
938930
void clearSign() { getIEEE().clearSign(); }
939931
void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
940932

941933
static APFloat copySign(APFloat Value, const APFloat &Sign) {
942-
return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()));
934+
return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()),
935+
Value.getSemantics());
943936
}
944937

945938
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
@@ -1035,15 +1028,15 @@ class APFloat : public APFloatBase {
10351028
/// xlC compiler.
10361029
hash_code hash_value(const APFloat &Arg);
10371030
inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
1038-
return APFloat(scalbn(X.getIEEE(), Exp, RM));
1031+
return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics());
10391032
}
10401033

10411034
/// \brief Equivalent of C standard library function.
10421035
///
10431036
/// While the C standard says Exp is an unspecified value for infinity and nan,
10441037
/// this returns INT_MAX for infinities, and INT_MIN for NaNs.
10451038
inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
1046-
return APFloat(frexp(X.getIEEE(), Exp, RM));
1039+
return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics());
10471040
}
10481041
/// \brief Returns the absolute value of the argument.
10491042
inline APFloat abs(APFloat X) {

lib/Support/APFloat.cpp

+37-19
Original file line numberDiff line numberDiff line change
@@ -3238,23 +3238,6 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) {
32383238
llvm_unreachable(nullptr);
32393239
}
32403240

3241-
IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) {
3242-
switch (BitWidth) {
3243-
case 16:
3244-
return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
3245-
case 32:
3246-
return IEEEFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth));
3247-
case 64:
3248-
return IEEEFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth));
3249-
case 80:
3250-
return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
3251-
case 128:
3252-
return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
3253-
default:
3254-
llvm_unreachable("Unknown floating bit width");
3255-
}
3256-
}
3257-
32583241
/// Make this number the largest magnitude normal number in the given
32593242
/// semantics.
32603243
void IEEEFloat::makeLargest(bool Negative) {
@@ -3902,6 +3885,18 @@ DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) {
39023885

39033886
} // End detail namespace
39043887

3888+
APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
3889+
if (usesLayout<IEEEFloat>(Semantics)) {
3890+
new (&IEEE) IEEEFloat(std::move(F));
3891+
} else if (usesLayout<DoubleAPFloat>(Semantics)) {
3892+
new (&Double)
3893+
DoubleAPFloat(Semantics, APFloat(std::move(F), F.getSemantics()),
3894+
APFloat(IEEEdouble));
3895+
} else {
3896+
llvm_unreachable("Unexpected semantics");
3897+
}
3898+
}
3899+
39053900
APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
39063901
return getIEEE().convertFromString(Str, RM);
39073902
}
@@ -3925,16 +3920,39 @@ APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics,
39253920
assert(&ToSemantics == &PPCDoubleDouble);
39263921
auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo);
39273922
*this = APFloat(
3928-
DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)));
3923+
DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)),
3924+
ToSemantics);
39293925
return Ret;
39303926
} else if (usesLayout<DoubleAPFloat>(getSemantics()) &&
39313927
usesLayout<IEEEFloat>(ToSemantics)) {
39323928
auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
3933-
*this = APFloat(std::move(getIEEE()));
3929+
*this = APFloat(std::move(getIEEE()), ToSemantics);
39343930
return Ret;
39353931
} else {
39363932
llvm_unreachable("Unexpected semantics");
39373933
}
39383934
}
39393935

3936+
APFloat APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
3937+
if (isIEEE) {
3938+
switch (BitWidth) {
3939+
case 16:
3940+
return APFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
3941+
case 32:
3942+
return APFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth));
3943+
case 64:
3944+
return APFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth));
3945+
case 80:
3946+
return APFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
3947+
case 128:
3948+
return APFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
3949+
default:
3950+
llvm_unreachable("Unknown floating bit width");
3951+
}
3952+
} else {
3953+
assert(BitWidth == 128);
3954+
return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
3955+
}
3956+
}
3957+
39403958
} // End llvm namespace

unittests/ADT/APFloatTest.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,34 @@ TEST(APFloatTest, PPCDoubleDouble) {
15271527
// This is what we get with our 106-bit mantissa approximation
15281528
EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
15291529
#endif
1530+
1531+
// PR30869
1532+
{
1533+
auto Result = APFloat(APFloat::PPCDoubleDouble, "1.0") +
1534+
APFloat(APFloat::PPCDoubleDouble, "1.0");
1535+
EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
1536+
1537+
Result = APFloat(APFloat::PPCDoubleDouble, "1.0") -
1538+
APFloat(APFloat::PPCDoubleDouble, "1.0");
1539+
EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
1540+
1541+
Result = APFloat(APFloat::PPCDoubleDouble, "1.0") *
1542+
APFloat(APFloat::PPCDoubleDouble, "1.0");
1543+
EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
1544+
1545+
Result = APFloat(APFloat::PPCDoubleDouble, "1.0") /
1546+
APFloat(APFloat::PPCDoubleDouble, "1.0");
1547+
EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
1548+
1549+
int Exp;
1550+
Result = frexp(APFloat(APFloat::PPCDoubleDouble, "1.0"), Exp,
1551+
APFloat::rmNearestTiesToEven);
1552+
EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
1553+
1554+
Result = scalbn(APFloat(APFloat::PPCDoubleDouble, "1.0"), 1,
1555+
APFloat::rmNearestTiesToEven);
1556+
EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
1557+
}
15301558
}
15311559

15321560
TEST(APFloatTest, isNegative) {

0 commit comments

Comments
 (0)