From 441030d026b92da7392d100e94fccb5fdb291d8c Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Thu, 27 Oct 2016 21:54:29 +0000 Subject: [PATCH] Revert "[APFloat] Add DoubleAPFloat mode to APFloat. NFC." This reverts r285351, since it breaks the build. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285354 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/APFloat.h | 480 +++++++++++++------------------------ lib/Support/APFloat.cpp | 174 +++++--------- 2 files changed, 221 insertions(+), 433 deletions(-) diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 19dc4367593..c44696decdc 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -18,15 +18,12 @@ #define LLVM_ADT_APFLOAT_H #include "llvm/ADT/APInt.h" -#include "llvm/Support/ErrorHandling.h" -#include namespace llvm { struct fltSemantics; class APSInt; class StringRef; -class APFloat; template class SmallVectorImpl; @@ -209,12 +206,13 @@ struct APFloatBase { namespace detail { -class IEEEFloat final : public APFloatBase { +class IEEEFloat : public APFloatBase { public: /// \name Constructors /// @{ IEEEFloat(const fltSemantics &); // Default construct to 0.0 + IEEEFloat(const fltSemantics &, StringRef); IEEEFloat(const fltSemantics &, integerPart); IEEEFloat(const fltSemantics &, uninitializedTag); IEEEFloat(const fltSemantics &, const APInt &); @@ -232,10 +230,74 @@ public: /// \name Convenience "constructors" /// @{ + /// Factory for Positive and Negative Zero. + /// + /// \param Negative True iff the number should be negative. + static IEEEFloat getZero(const fltSemantics &Sem, bool Negative = false) { + IEEEFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; + } + + /// Factory for Positive and Negative Infinity. + /// + /// \param Negative True iff the number should be negative. + static IEEEFloat getInf(const fltSemantics &Sem, bool Negative = false) { + IEEEFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; + } + + /// Factory for QNaN values. + /// + /// \param Negative - True iff the NaN generated should be negative. + /// \param type - The unspecified fill bits for creating the NaN, 0 by + /// default. The value is truncated as necessary. + static IEEEFloat getNaN(const fltSemantics &Sem, bool Negative = false, + unsigned type = 0) { + if (type) { + APInt fill(64, type); + return getQNaN(Sem, Negative, &fill); + } else { + return getQNaN(Sem, Negative, nullptr); + } + } + + /// Factory for QNaN values. + static IEEEFloat getQNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + return makeNaN(Sem, false, Negative, payload); + } + + /// Factory for SNaN values. + static IEEEFloat getSNaN(const fltSemantics &Sem, bool Negative = false, + const APInt *payload = nullptr) { + return makeNaN(Sem, true, Negative, payload); + } + + /// Returns the largest finite number in the given semantics. + /// + /// \param Negative - True iff the number should be negative + static IEEEFloat getLargest(const fltSemantics &Sem, bool Negative = false); + + /// Returns the smallest (by magnitude) finite number in the given semantics. + /// Might be denormalized, which implies a relative loss of precision. + /// + /// \param Negative - True iff the number should be negative + static IEEEFloat getSmallest(const fltSemantics &Sem, bool Negative = false); + + /// Returns the smallest (by magnitude) normalized finite number in the given + /// semantics. + /// + /// \param Negative - True iff the number should be negative + static IEEEFloat getSmallestNormalized(const fltSemantics &Sem, + bool Negative = false); + /// Returns a float which is bitcasted from an all one value int. /// /// \param BitWidth - Select float type - static IEEEFloat getAllOnesValue(unsigned BitWidth); + /// \param isIEEE - If 128 bit number, select between PPC and IEEE + static IEEEFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); /// @} @@ -465,25 +527,6 @@ public: friend IEEEFloat frexp(const IEEEFloat &X, int &Exp, roundingMode); - /// \name Special value setters. - /// @{ - - void makeLargest(bool Neg = false); - void makeSmallest(bool Neg = false); - void makeNaN(bool SNaN = false, bool Neg = false, - const APInt *fill = nullptr); - void makeInf(bool Neg = false); - void makeZero(bool Neg = false); - void makeQuiet(); - - /// Returns the smallest (by magnitude) normalized finite number in the given - /// semantics. - /// - /// \param Negative - True iff the number should be negative - void makeSmallestNormalized(bool Negative = false); - - /// @} - private: /// \name Simple Queries /// @{ @@ -526,6 +569,21 @@ private: /// @} + /// \name Special value setters. + /// @{ + + void makeLargest(bool Neg = false); + void makeSmallest(bool Neg = false); + void makeNaN(bool SNaN = false, bool Neg = false, + const APInt *fill = nullptr); + static IEEEFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill); + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); + void makeQuiet(); + + /// @} + /// \name Miscellany /// @{ @@ -566,7 +624,6 @@ private: void copySignificand(const IEEEFloat &); void freeSignificand(); - /// Note: this must be the first data member. /// The semantics that this value obeys. const fltSemantics *semantics; @@ -596,426 +653,213 @@ int ilogb(const IEEEFloat &Arg); IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode); IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM); -// This mode implements more precise float in terms of two APFloats. -// The interface and layout is designed for arbitray underlying semantics, -// though currently only PPCDoubleDouble semantics are supported, whose -// corresponding underlying semantics are IEEEdouble. -class DoubleAPFloat final : public APFloatBase { - // Note: this must be the first data member. - const fltSemantics *Semantics; - std::unique_ptr Floats; - -public: - DoubleAPFloat(const fltSemantics &S); - DoubleAPFloat(const fltSemantics &S, uninitializedTag); - DoubleAPFloat(const fltSemantics &S, integerPart); - DoubleAPFloat(const fltSemantics &S, const APInt &I); - DoubleAPFloat(const fltSemantics &S, APFloat &&First, APFloat &&Second); - DoubleAPFloat(const DoubleAPFloat &RHS); - DoubleAPFloat(DoubleAPFloat &&RHS); - - DoubleAPFloat &operator=(const DoubleAPFloat &RHS); - - DoubleAPFloat &operator=(DoubleAPFloat &&RHS) { - if (this != &RHS) { - this->~DoubleAPFloat(); - new (this) DoubleAPFloat(std::move(RHS)); - } - return *this; - } - - bool needsCleanup() const { return Floats != nullptr; } - - APFloat &getFirst() { return Floats[0]; } - const APFloat &getFirst() const { return Floats[0]; } -}; - } // End detail namespace // This is a interface class that is currently forwarding functionalities from // detail::IEEEFloat. class APFloat : public APFloatBase { typedef detail::IEEEFloat IEEEFloat; - typedef detail::DoubleAPFloat DoubleAPFloat; static_assert(std::is_standard_layout::value, ""); - union Storage { + union { const fltSemantics *semantics; IEEEFloat IEEE; - DoubleAPFloat Double; - - explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {} - explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {} - - template - Storage(const fltSemantics &Semantics, ArgTypes &&... Args) { - if (usesLayout(Semantics)) { - new (&IEEE) IEEEFloat(Semantics, std::forward(Args)...); - } else if (usesLayout(Semantics)) { - new (&Double) DoubleAPFloat(Semantics, std::forward(Args)...); - } else { - llvm_unreachable("Unexpected semantics"); - } - } - - ~Storage() { - if (usesLayout(*semantics)) { - IEEE.~IEEEFloat(); - } else if (usesLayout(*semantics)) { - Double.~DoubleAPFloat(); - } else { - llvm_unreachable("Unexpected semantics"); - } - } - - Storage(const Storage &RHS) { - if (usesLayout(*RHS.semantics)) { - new (this) IEEEFloat(RHS.IEEE); - } else if (usesLayout(*RHS.semantics)) { - new (this) DoubleAPFloat(RHS.Double); - } else { - llvm_unreachable("Unexpected semantics"); - } - } - - Storage(Storage &&RHS) { - if (usesLayout(*RHS.semantics)) { - new (this) IEEEFloat(std::move(RHS.IEEE)); - } else if (usesLayout(*RHS.semantics)) { - new (this) DoubleAPFloat(std::move(RHS.Double)); - } else { - llvm_unreachable("Unexpected semantics"); - } - } - - Storage &operator=(const Storage &RHS) { - if (usesLayout(*semantics) && - usesLayout(*RHS.semantics)) { - IEEE = RHS.IEEE; - } else if (usesLayout(*semantics) && - usesLayout(*RHS.semantics)) { - Double = RHS.Double; - } else if (this != &RHS) { - this->~Storage(); - new (this) Storage(RHS); - } - return *this; - } - - Storage &operator=(Storage &&RHS) { - if (usesLayout(*semantics) && - usesLayout(*RHS.semantics)) { - IEEE = std::move(RHS.IEEE); - } else if (usesLayout(*semantics) && - usesLayout(*RHS.semantics)) { - Double = std::move(RHS.Double); - } else if (this != &RHS) { - this->~Storage(); - new (this) Storage(RHS); - } - return *this; - } - } U; - - template static bool usesLayout(const fltSemantics &Semantics) { - static_assert(std::is_same::value || - std::is_same::value, ""); - if (std::is_same::value) { - return &Semantics == &PPCDoubleDouble; - } - return &Semantics != &PPCDoubleDouble; - } - - IEEEFloat &getIEEE() { - if (usesLayout(*U.semantics)) { - return U.IEEE; - } else if (usesLayout(*U.semantics)) { - return U.Double.getFirst().U.IEEE; - } else { - llvm_unreachable("Unexpected semantics"); - } - } - - const IEEEFloat &getIEEE() const { - if (usesLayout(*U.semantics)) { - return U.IEEE; - } else if (usesLayout(*U.semantics)) { - return U.Double.getFirst().U.IEEE; - } else { - llvm_unreachable("Unexpected semantics"); - } - } - - void makeZero(bool Neg) { getIEEE().makeZero(Neg); } - - void makeInf(bool Neg) { getIEEE().makeInf(Neg); } - - void makeNaN(bool SNaN, bool Neg, const APInt *fill) { - getIEEE().makeNaN(SNaN, Neg, fill); - } - - void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); } - - void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); } - - void makeSmallestNormalized(bool Neg) { - getIEEE().makeSmallestNormalized(Neg); - } + }; - explicit APFloat(IEEEFloat F) : U(std::move(F)) {} - explicit APFloat(DoubleAPFloat F) : U(std::move(F)) {} + explicit APFloat(IEEEFloat F) : IEEE(std::move(F)) {} public: - APFloat(const fltSemantics &Semantics) : U(Semantics) {} + APFloat(const fltSemantics &Semantics) : APFloat(IEEEFloat(Semantics)) {} APFloat(const fltSemantics &Semantics, StringRef S); - APFloat(const fltSemantics &Semantics, integerPart I) : U(Semantics, I) {} - 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)) {} - APFloat(const APFloat &RHS) = default; - APFloat(APFloat &&RHS) = default; - - ~APFloat() = default; - - bool needsCleanup() const { - if (usesLayout(getSemantics())) { - return U.IEEE.needsCleanup(); - } else if (usesLayout(getSemantics())) { - return U.Double.needsCleanup(); - } else { - llvm_unreachable("Unexpected semantics"); - } - } + APFloat(const fltSemantics &Semantics, integerPart I) + : APFloat(IEEEFloat(Semantics, I)) {} + APFloat(const fltSemantics &Semantics, uninitializedTag U) + : APFloat(IEEEFloat(Semantics, U)) {} + APFloat(const fltSemantics &Semantics, const APInt &I) + : APFloat(IEEEFloat(Semantics, I)) {} + explicit APFloat(double d) : APFloat(IEEEFloat(d)) {} + explicit APFloat(float f) : APFloat(IEEEFloat(f)) {} + APFloat(const APFloat &RHS) : APFloat(IEEEFloat(RHS.IEEE)) {} + APFloat(APFloat &&RHS) : APFloat(IEEEFloat(std::move(RHS.IEEE))) {} + + ~APFloat() { IEEE.~IEEEFloat(); } + + bool needsCleanup() const { return IEEE.needsCleanup(); } - /// Factory for Positive and Negative Zero. - /// - /// \param Negative True iff the number should be negative. static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeZero(Negative); - return Val; + return APFloat(IEEEFloat::getZero(Sem, Negative)); } - /// Factory for Positive and Negative Infinity. - /// - /// \param Negative True iff the number should be negative. static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeInf(Negative); - return Val; + return APFloat(IEEEFloat::getInf(Sem, Negative)); } - /// Factory for NaN values. - /// - /// \param Negative - True iff the NaN generated should be negative. - /// \param type - The unspecified fill bits for creating the NaN, 0 by - /// default. The value is truncated as necessary. static APFloat getNaN(const fltSemantics &Sem, bool Negative = false, unsigned type = 0) { - if (type) { - APInt fill(64, type); - return getQNaN(Sem, Negative, &fill); - } else { - return getQNaN(Sem, Negative, nullptr); - } + return APFloat(IEEEFloat::getNaN(Sem, Negative, type)); } - /// Factory for QNaN values. static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false, const APInt *payload = nullptr) { - APFloat Val(Sem, uninitialized); - Val.makeNaN(false, Negative, payload); - return Val; + return APFloat(IEEEFloat::getQNaN(Sem, Negative, payload)); } - /// Factory for SNaN values. static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false, const APInt *payload = nullptr) { - APFloat Val(Sem, uninitialized); - Val.makeNaN(true, Negative, payload); - return Val; + return APFloat(IEEEFloat::getSNaN(Sem, Negative, payload)); } - /// Returns the largest finite number in the given semantics. - /// - /// \param Negative - True iff the number should be negative static APFloat getLargest(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeLargest(Negative); - return Val; + return APFloat(IEEEFloat::getLargest(Sem, Negative)); } - /// Returns the smallest (by magnitude) finite number in the given semantics. - /// Might be denormalized, which implies a relative loss of precision. - /// - /// \param Negative - True iff the number should be negative static APFloat getSmallest(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeSmallest(Negative); - return Val; + return APFloat(IEEEFloat::getSmallest(Sem, Negative)); } - /// Returns the smallest (by magnitude) normalized finite number in the given - /// semantics. - /// - /// \param Negative - True iff the number should be negative static APFloat getSmallestNormalized(const fltSemantics &Sem, bool Negative = false) { - APFloat Val(Sem, uninitialized); - Val.makeSmallestNormalized(Negative); - return Val; + return APFloat(IEEEFloat::getSmallestNormalized(Sem, Negative)); } - /// Returns a float which is bitcasted from an all one value int. - /// - /// \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)); - } + return APFloat(IEEEFloat::getAllOnesValue(BitWidth, isIEEE)); } - void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); } + void Profile(FoldingSetNodeID &NID) const { IEEE.Profile(NID); } opStatus add(const APFloat &RHS, roundingMode RM) { - return getIEEE().add(RHS.getIEEE(), RM); + return IEEE.add(RHS.IEEE, RM); } opStatus subtract(const APFloat &RHS, roundingMode RM) { - return getIEEE().subtract(RHS.getIEEE(), RM); + return IEEE.subtract(RHS.IEEE, RM); } opStatus multiply(const APFloat &RHS, roundingMode RM) { - return getIEEE().multiply(RHS.getIEEE(), RM); + return IEEE.multiply(RHS.IEEE, RM); } opStatus divide(const APFloat &RHS, roundingMode RM) { - return getIEEE().divide(RHS.getIEEE(), RM); - } - opStatus remainder(const APFloat &RHS) { - return getIEEE().remainder(RHS.getIEEE()); + return IEEE.divide(RHS.IEEE, RM); } - opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); } + opStatus remainder(const APFloat &RHS) { return IEEE.remainder(RHS.IEEE); } + opStatus mod(const APFloat &RHS) { return IEEE.mod(RHS.IEEE); } opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend, roundingMode RM) { - return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(), - RM); + return IEEE.fusedMultiplyAdd(Multiplicand.IEEE, Addend.IEEE, RM); } - opStatus roundToIntegral(roundingMode RM) { - return getIEEE().roundToIntegral(RM); - } - opStatus next(bool nextDown) { return getIEEE().next(nextDown); } + opStatus roundToIntegral(roundingMode RM) { return IEEE.roundToIntegral(RM); } + opStatus next(bool nextDown) { return IEEE.next(nextDown); } APFloat operator+(const APFloat &RHS) const { - return APFloat(getIEEE() + RHS.getIEEE()); + return APFloat(IEEE + RHS.IEEE); } APFloat operator-(const APFloat &RHS) const { - return APFloat(getIEEE() - RHS.getIEEE()); + return APFloat(IEEE - RHS.IEEE); } APFloat operator*(const APFloat &RHS) const { - return APFloat(getIEEE() * RHS.getIEEE()); + return APFloat(IEEE * RHS.IEEE); } APFloat operator/(const APFloat &RHS) const { - return APFloat(getIEEE() / RHS.getIEEE()); + return APFloat(IEEE / RHS.IEEE); } - void changeSign() { getIEEE().changeSign(); } - void clearSign() { getIEEE().clearSign(); } - void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); } + void changeSign() { IEEE.changeSign(); } + void clearSign() { IEEE.clearSign(); } + void copySign(const APFloat &RHS) { IEEE.copySign(RHS.IEEE); } static APFloat copySign(APFloat Value, const APFloat &Sign) { - return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE())); + return APFloat(IEEEFloat::copySign(Value.IEEE, Sign.IEEE)); } opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, - bool *losesInfo); + bool *losesInfo) { + return IEEE.convert(ToSemantics, RM, losesInfo); + } opStatus convertToInteger(integerPart *Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const { - return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact); + return IEEE.convertToInteger(Input, Width, IsSigned, RM, IsExact); } opStatus convertToInteger(APSInt &Result, roundingMode RM, bool *IsExact) const { - return getIEEE().convertToInteger(Result, RM, IsExact); + return IEEE.convertToInteger(Result, RM, IsExact); } opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM) { - return getIEEE().convertFromAPInt(Input, IsSigned, RM); + return IEEE.convertFromAPInt(Input, IsSigned, RM); } opStatus convertFromSignExtendedInteger(const integerPart *Input, unsigned int InputSize, bool IsSigned, roundingMode RM) { - return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned, - RM); + return IEEE.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM); } opStatus convertFromZeroExtendedInteger(const integerPart *Input, unsigned int InputSize, bool IsSigned, roundingMode RM) { - return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned, - RM); + return IEEE.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM); } opStatus convertFromString(StringRef, roundingMode); - APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); } - double convertToDouble() const { return getIEEE().convertToDouble(); } - float convertToFloat() const { return getIEEE().convertToFloat(); } + APInt bitcastToAPInt() const { return IEEE.bitcastToAPInt(); } + double convertToDouble() const { return IEEE.convertToDouble(); } + float convertToFloat() const { return IEEE.convertToFloat(); } bool operator==(const APFloat &) const = delete; - cmpResult compare(const APFloat &RHS) const { - return getIEEE().compare(RHS.getIEEE()); - } + cmpResult compare(const APFloat &RHS) const { return IEEE.compare(RHS.IEEE); } bool bitwiseIsEqual(const APFloat &RHS) const { - return getIEEE().bitwiseIsEqual(RHS.getIEEE()); + return IEEE.bitwiseIsEqual(RHS.IEEE); } unsigned int convertToHexString(char *DST, unsigned int HexDigits, bool UpperCase, roundingMode RM) const { - return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM); + return IEEE.convertToHexString(DST, HexDigits, UpperCase, RM); } bool isZero() const { return getCategory() == fcZero; } bool isInfinity() const { return getCategory() == fcInfinity; } bool isNaN() const { return getCategory() == fcNaN; } - bool isNegative() const { return getIEEE().isNegative(); } - bool isDenormal() const { return getIEEE().isDenormal(); } - bool isSignaling() const { return getIEEE().isSignaling(); } + bool isNegative() const { return IEEE.isNegative(); } + bool isDenormal() const { return IEEE.isDenormal(); } + bool isSignaling() const { return IEEE.isSignaling(); } bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } bool isFinite() const { return !isNaN() && !isInfinity(); } - fltCategory getCategory() const { return getIEEE().getCategory(); } - const fltSemantics &getSemantics() const { return *U.semantics; } + fltCategory getCategory() const { return IEEE.getCategory(); } + const fltSemantics &getSemantics() const { return *semantics; } bool isNonZero() const { return !isZero(); } bool isFiniteNonZero() const { return isFinite() && !isZero(); } bool isPosZero() const { return isZero() && !isNegative(); } bool isNegZero() const { return isZero() && isNegative(); } - bool isSmallest() const { return getIEEE().isSmallest(); } - bool isLargest() const { return getIEEE().isLargest(); } - bool isInteger() const { return getIEEE().isInteger(); } + bool isSmallest() const { return IEEE.isSmallest(); } + bool isLargest() const { return IEEE.isLargest(); } + bool isInteger() const { return IEEE.isInteger(); } - APFloat &operator=(const APFloat &RHS) = default; - APFloat &operator=(APFloat &&RHS) = default; + APFloat &operator=(const APFloat &RHS) { + IEEE = RHS.IEEE; + return *this; + } + APFloat &operator=(APFloat &&RHS) { + IEEE = std::move(RHS.IEEE); + return *this; + } void toString(SmallVectorImpl &Str, unsigned FormatPrecision = 0, unsigned FormatMaxPadding = 3) const { - return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding); + return IEEE.toString(Str, FormatPrecision, FormatMaxPadding); } bool getExactInverse(APFloat *inv) const { - return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr); + return IEEE.getExactInverse(inv ? &inv->IEEE : nullptr); } friend hash_code hash_value(const APFloat &Arg); - friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); } + friend int ilogb(const APFloat &Arg) { return ilogb(Arg.IEEE); } friend APFloat scalbn(APFloat X, int Exp, roundingMode RM); friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM); }; @@ -1026,7 +870,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.IEEE, Exp, RM)); } /// \brief Equivalent of C standard library function. @@ -1034,7 +878,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, /// 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.IEEE, Exp, RM)); } /// \brief Returns the absolute value of the argument. inline APFloat abs(APFloat X) { diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 05afa06a552..5a9e9833b04 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -75,18 +75,8 @@ 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 = {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}; + const fltSemantics APFloatBase::PPCDoubleDouble = {1023, -1022 + 53, 53 + 53, + 128}; /* A tight upper bound on number of parts required to hold the value pow(5, power) is @@ -687,6 +677,13 @@ 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) { @@ -823,6 +820,11 @@ 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); @@ -2364,8 +2366,7 @@ IEEEFloat::roundSignificandWithExponent(const integerPart *decSigParts, excessPrecision = calcSemantics.precision - semantics->precision; truncatedBits = excessPrecision; - IEEEFloat decSig(calcSemantics, uninitialized); - decSig.makeZero(sign); + IEEEFloat decSig = IEEEFloat::getZero(calcSemantics, sign); IEEEFloat pow5(calcSemantics); sigStatus = decSig.convertFromUnsignedParts(decSigParts, sigPartCount, @@ -2820,7 +2821,7 @@ APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const { } APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const { - assert(semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl); + assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); assert(partCount()==2); uint64_t words[2]; @@ -3001,7 +3002,7 @@ APInt IEEEFloat::bitcastToAPInt() const { if (semantics == (const llvm::fltSemantics*)&IEEEquad) return convertQuadrupleAPFloatToAPInt(); - if (semantics == (const llvm::fltSemantics *)&PPCDoubleDoubleImpl) + if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble) return convertPPCDoubleDoubleAPFloatToAPInt(); assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended && @@ -3071,14 +3072,14 @@ void IEEEFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) { // Get the first double and convert to our format. initFromDoubleAPInt(APInt(64, i1)); - fs = convert(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); + fs = convert(PPCDoubleDouble, 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(PPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo); + fs = v.convert(PPCDoubleDouble, rmNearestTiesToEven, &losesInfo); assert(fs == opOK && !losesInfo); (void)fs; @@ -3232,13 +3233,13 @@ void IEEEFloat::initFromAPInt(const fltSemantics *Sem, const APInt &api) { return initFromF80LongDoubleAPInt(api); if (Sem == &IEEEquad) return initFromQuadrupleAPInt(api); - if (Sem == &PPCDoubleDoubleImpl) + if (Sem == &PPCDoubleDouble) return initFromPPCDoubleDoubleAPInt(api); llvm_unreachable(nullptr); } -IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) { +IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) { switch (BitWidth) { case 16: return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth)); @@ -3249,7 +3250,9 @@ IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) { case 80: return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth)); case 128: - return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); + if (isIEEE) + return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth)); + return IEEEFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth)); default: llvm_unreachable("Unknown floating bit width"); } @@ -3293,18 +3296,43 @@ void IEEEFloat::makeSmallest(bool Negative) { APInt::tcSet(significandParts(), 1, partCount()); } -void IEEEFloat::makeSmallestNormalized(bool Negative) { +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); + // We want (in interchange format): // sign = {Negative} // exponent = 0..0 // significand = 10..0 - category = fcNormal; - zeroSignificand(); - sign = Negative; - exponent = semantics->minExponent; - significandParts()[partCountForBits(semantics->precision) - 1] |= - (((integerPart)1) << ((semantics->precision - 1) % integerPartWidth)); + 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; } IEEEFloat::IEEEFloat(const fltSemantics &Sem, const APInt &API) { @@ -3840,99 +3868,15 @@ 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 getIEEE().convertFromString(Str, RM); + return IEEE.convertFromString(Str, RM); } -hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.getIEEE()); } +hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.IEEE); } APFloat::APFloat(const fltSemantics &Semantics, StringRef S) - : APFloat(Semantics) { - convertFromString(S, rmNearestTiesToEven); -} - -APFloat::opStatus APFloat::convert(const fltSemantics &ToSemantics, - roundingMode RM, bool *losesInfo) { - if (&getSemantics() == &ToSemantics) - return opOK; - if (usesLayout(getSemantics()) && - usesLayout(ToSemantics)) { - return U.IEEE.convert(ToSemantics, RM, losesInfo); - } else if (usesLayout(getSemantics()) && - usesLayout(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(getSemantics()) && - usesLayout(ToSemantics)) { - auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo); - *this = APFloat(std::move(getIEEE())); - return Ret; - } else { - llvm_unreachable("Unexpected semantics"); - } -} + : APFloat(IEEEFloat(Semantics, S)) {} } // End llvm namespace -- 2.40.0