diff options
author | Tim Shen <timshen91@gmail.com> | 2016-10-27 22:52:40 +0000 |
---|---|---|
committer | Tim Shen <timshen91@gmail.com> | 2016-10-27 22:52:40 +0000 |
commit | 139a58f75ea887a6cc12623eb3e59187c3c5ce62 (patch) | |
tree | b0f6858a044b801af6d786ab68657a3dc5ea98b6 /llvm/lib/Support/APFloat.cpp | |
parent | f817bae1616852aeae880aa8e6a22407276aa223 (diff) | |
download | bcm5719-llvm-139a58f75ea887a6cc12623eb3e59187c3c5ce62.tar.gz bcm5719-llvm-139a58f75ea887a6cc12623eb3e59187c3c5ce62.zip |
Reapply r285351 "[APFloat] Add DoubleAPFloat mode to APFloat. NFC." with
a workaround for old clang.
llvm-svn: 285358
Diffstat (limited to 'llvm/lib/Support/APFloat.cpp')
-rw-r--r-- | llvm/lib/Support/APFloat.cpp | 174 |
1 files changed, 115 insertions, 59 deletions
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp index 5a9e9833b04..05afa06a552 100644 --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -75,8 +75,18 @@ namespace llvm { to represent all possible values held by a PPC double-double number, for example: (long double) 1.0 + (long double) 0x1p-106 Should this be replaced by a full emulation of PPC double-double? */ - const fltSemantics APFloatBase::PPCDoubleDouble = {1023, -1022 + 53, 53 + 53, - 128}; + const fltSemantics APFloatBase::PPCDoubleDouble = {0, 0, 0, 0}; + + /* There are temporary semantics for the real PPCDoubleDouble implementation. + Currently, APFloat of PPCDoubleDouble holds one PPCDoubleDoubleImpl as the + high part of double double, and one IEEEdouble as the low part, so that + the old operations operate on PPCDoubleDoubleImpl, while the newly added + operations also populate the IEEEdouble. + + TODO: Once all functions support DoubleAPFloat mode, we'll change all + PPCDoubleDoubleImpl to IEEEdouble and remove PPCDoubleDoubleImpl. */ + static const fltSemantics PPCDoubleDoubleImpl = {1023, -1022 + 53, 53 + 53, + 128}; /* A tight upper bound on number of parts required to hold the value pow(5, power) is @@ -677,13 +687,6 @@ void IEEEFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) { APInt::tcSetBit(significand, QNaNBit + 1); } -IEEEFloat IEEEFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, - const APInt *fill) { - IEEEFloat value(Sem, uninitialized); - value.makeNaN(SNaN, Negative, fill); - return value; -} - IEEEFloat &IEEEFloat::operator=(const IEEEFloat &rhs) { if (this != &rhs) { if (semantics != rhs.semantics) { @@ -820,11 +823,6 @@ IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, uninitializedTag tag) { initialize(&ourSemantics); } -IEEEFloat::IEEEFloat(const fltSemantics &ourSemantics, StringRef text) { - initialize(&ourSemantics); - convertFromString(text, rmNearestTiesToEven); -} - IEEEFloat::IEEEFloat(const IEEEFloat &rhs) { initialize(rhs.semantics); assign(rhs); @@ -2366,7 +2364,8 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts, excessPrecision = calcSemantics.precision - semantics->precision; truncatedBits = excessPrecision; - IEEEFloat decSig = IEEEFloat::getZero(calcSemantics, sign); + IEEEFloat decSig(calcSemantics, uninitialized); + decSig.makeZero(sign); IEEEFloat pow5(calcSemantics); sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount, @@ -2821,7 +2820,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const { } APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const { - assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); + assert(semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl); assert(partCount()==2); uint64_t words[2]; @@ -3002,7 +3001,7 @@ APInt IEEEFloat::bitcastToAPInt() const { if (semantics == (const llvm::fltSemantics*)&IEEEquad) return convertQuadrupleAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble) + if (semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl) return convertPPCDoubleDoubleAPFloatToAPInt(); assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended && @@ -3072,14 +3071,14 @@ void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) { // Get the first double and convert to our format. initFromDoubleAPInt(APInt(64, i1)); - fs = convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); + fs = convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; // Unless we have a special case, add in second double. if (isFiniteNonZero()) { IEEEFloat v(IEEEdouble, APInt(64, i2)); - fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); + fs = v.convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; @@ -3233,13 +3232,13 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { return initFromF80LongDoubleAPInt(api); if (Sem == &IEEEquad) return initFromQuadrupleAPInt(api); - if (Sem == &PPCDoubleDouble) + if (Sem == &PPCDoubleDoubleImpl) return initFromPPCDoubleDoubleAPInt(api); llvm_unreachable(nullptr); } -IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) { +IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) { switch (BitWidth) { case 16: return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth)); @@ -3250,9 +3249,7 @@ IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) { case 80: return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth)); case 128: - if (isIEEE) - return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); - return IEEEFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth)); + return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); default: llvm_unreachable("Unknown floating bit width"); } @@ -3296,43 +3293,18 @@ void IEEEFloat::makeSmallest(bool Negative) { APInt::tcSet(significandParts(), 1, partCount()); } -IEEEFloat IEEEFloat::getLargest(const fltSemantics &Sem, bool Negative) { - // We want (in interchange format): - // sign = {Negative} - // exponent = 1..10 - // significand = 1..1 - IEEEFloat Val(Sem, uninitialized); - Val.makeLargest(Negative); - return Val; -} - -IEEEFloat IEEEFloat::getSmallest(const fltSemantics &Sem, bool Negative) { - // We want (in interchange format): - // sign = {Negative} - // exponent = 0..0 - // significand = 0..01 - IEEEFloat Val(Sem, uninitialized); - Val.makeSmallest(Negative); - return Val; -} - -IEEEFloat IEEEFloat::getSmallestNormalized(const fltSemantics &Sem, - bool Negative) { - IEEEFloat Val(Sem, uninitialized); - +void IEEEFloat::makeSmallestNormalized(bool Negative) { // We want (in interchange format): // sign = {Negative} // exponent = 0..0 // significand = 10..0 - Val.category = fcNormal; - Val.zeroSignificand(); - Val.sign = Negative; - Val.exponent = Sem.minExponent; - Val.significandParts()[partCountForBits(Sem.precision)-1] |= - (((integerPart) 1) << ((Sem.precision - 1) % integerPartWidth)); - - return Val; + category = fcNormal; + zeroSignificand(); + sign = Negative; + exponent = semantics->minExponent; + significandParts()[partCountForBits(semantics->precision) - 1] |= + (((integerPart)1) << ((semantics->precision - 1) % integerPartWidth)); } IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) { @@ -3868,15 +3840,99 @@ IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM) { return scalbn(Val, -Exp, RM); } +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S) + : Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl), + APFloat(IEEEdouble)}) { + assert(Semantics == &PPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag) + : Semantics(&S), + Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl, uninitialized), + APFloat(IEEEdouble, uninitialized)}) { + assert(Semantics == &PPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I) + : Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl, I), + APFloat(IEEEdouble)}) { + assert(Semantics == &PPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I) + : Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl, I), + APFloat(IEEEdouble)}) { + assert(Semantics == &PPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First, + APFloat &&Second) + : Semantics(&S), + Floats(new APFloat[2]{std::move(First), std::move(Second)}) { + assert(Semantics == &PPCDoubleDouble); + // TODO Check for First == &IEEEdouble once the transition is done. + assert(&Floats[0].getSemantics() == &PPCDoubleDoubleImpl); + assert(&Floats[1].getSemantics() == &IEEEdouble); +} + +DoubleAPFloat::DoubleAPFloat(const DoubleAPFloat &RHS) + : Semantics(RHS.Semantics), + Floats(new APFloat[2]{APFloat(RHS.Floats[0]), APFloat(RHS.Floats[1])}) { + assert(Semantics == &PPCDoubleDouble); +} + +DoubleAPFloat::DoubleAPFloat(DoubleAPFloat &&RHS) + : Semantics(RHS.Semantics), Floats(std::move(RHS.Floats)) { + RHS.Semantics = &Bogus; + assert(Semantics == &PPCDoubleDouble); +} + +DoubleAPFloat &DoubleAPFloat::operator=(const DoubleAPFloat &RHS) { + if (Semantics == RHS.Semantics) { + Floats[0] = RHS.Floats[0]; + Floats[1] = RHS.Floats[1]; + } else if (this != &RHS) { + this->~DoubleAPFloat(); + new (this) DoubleAPFloat(RHS); + } + return *this; +} + } // End detail namespace APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) { - return IEEE.convertFromString(Str, RM); + return getIEEE().convertFromString(Str, RM); } -hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.IEEE); } +hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.getIEEE()); } APFloat::APFloat(const fltSemantics &Semantics, StringRef S) - : APFloat(IEEEFloat(Semantics, S)) {} + : APFloat(Semantics) { + convertFromString(S, rmNearestTiesToEven); +} + +APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics, + roundingMode RM, bool *losesInfo) { + if (&getSemantics() == &ToSemantics) + return opOK; + if (usesLayout<IEEEFloat>(getSemantics()) && + usesLayout<IEEEFloat>(ToSemantics)) { + return U.IEEE.convert(ToSemantics, RM, losesInfo); + } else if (usesLayout<IEEEFloat>(getSemantics()) && + usesLayout<DoubleAPFloat>(ToSemantics)) { + assert(&ToSemantics == &PPCDoubleDouble); + auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo); + *this = APFloat( + DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble))); + return Ret; + } else if (usesLayout<DoubleAPFloat>(getSemantics()) && + usesLayout<IEEEFloat>(ToSemantics)) { + auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo); + *this = APFloat(std::move(getIEEE())); + return Ret; + } else { + llvm_unreachable("Unexpected semantics"); + } +} } // End llvm namespace |