[llvm] r285358 - Reapply r285351 "[APFloat] Add DoubleAPFloat mode to APFloat. NFC." with
Tim Shen via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 27 15:52:41 PDT 2016
Author: timshen
Date: Thu Oct 27 17:52:40 2016
New Revision: 285358
URL: http://llvm.org/viewvc/llvm-project?rev=285358&view=rev
Log:
Reapply r285351 "[APFloat] Add DoubleAPFloat mode to APFloat. NFC." with
a workaround for old clang.
Modified:
llvm/trunk/include/llvm/ADT/APFloat.h
llvm/trunk/lib/Support/APFloat.cpp
Modified: llvm/trunk/include/llvm/ADT/APFloat.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=285358&r1=285357&r2=285358&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APFloat.h (original)
+++ llvm/trunk/include/llvm/ADT/APFloat.h Thu Oct 27 17:52:40 2016
@@ -18,12 +18,15 @@
#define LLVM_ADT_APFLOAT_H
#include "llvm/ADT/APInt.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <memory>
namespace llvm {
struct fltSemantics;
class APSInt;
class StringRef;
+class APFloat;
template <typename T> class SmallVectorImpl;
@@ -206,13 +209,12 @@ struct APFloatBase {
namespace detail {
-class IEEEFloat : public APFloatBase {
+class IEEEFloat final : 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 &);
@@ -230,74 +232,10 @@ 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
- /// \param isIEEE - If 128 bit number, select between PPC and IEEE
- static IEEEFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
+ static IEEEFloat getAllOnesValue(unsigned BitWidth);
/// @}
@@ -527,6 +465,25 @@ 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
/// @{
@@ -569,21 +526,6 @@ 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
/// @{
@@ -624,6 +566,7 @@ private:
void copySignificand(const IEEEFloat &);
void freeSignificand();
+ /// Note: this must be the first data member.
/// The semantics that this value obeys.
const fltSemantics *semantics;
@@ -653,215 +596,436 @@ 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<APFloat[]> 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<IEEEFloat>::value, "");
- union {
+ union Storage {
const fltSemantics *semantics;
IEEEFloat IEEE;
- };
+ DoubleAPFloat Double;
- explicit APFloat(IEEEFloat F) : IEEE(std::move(F)) {}
+ explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {}
+ explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {}
-public:
- APFloat(const fltSemantics &Semantics) : APFloat(IEEEFloat(Semantics)) {}
- APFloat(const fltSemantics &Semantics, StringRef S);
- 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))) {}
+ template <typename... ArgTypes>
+ Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
+ if (usesLayout<IEEEFloat>(Semantics)) {
+ new (&IEEE) IEEEFloat(Semantics, std::forward<ArgTypes>(Args)...);
+ } else if (usesLayout<DoubleAPFloat>(Semantics)) {
+ new (&Double) DoubleAPFloat(Semantics, std::forward<ArgTypes>(Args)...);
+ } else {
+ llvm_unreachable("Unexpected semantics");
+ }
+ }
+
+ ~Storage() {
+ if (usesLayout<IEEEFloat>(*semantics)) {
+ IEEE.~IEEEFloat();
+ } else if (usesLayout<DoubleAPFloat>(*semantics)) {
+ Double.~DoubleAPFloat();
+ } else {
+ llvm_unreachable("Unexpected semantics");
+ }
+ }
+
+ Storage(const Storage &RHS) {
+ if (usesLayout<IEEEFloat>(*RHS.semantics)) {
+ new (this) IEEEFloat(RHS.IEEE);
+ } else if (usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ new (this) DoubleAPFloat(RHS.Double);
+ } else {
+ llvm_unreachable("Unexpected semantics");
+ }
+ }
+
+ Storage(Storage &&RHS) {
+ if (usesLayout<IEEEFloat>(*RHS.semantics)) {
+ new (this) IEEEFloat(std::move(RHS.IEEE));
+ } else if (usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ new (this) DoubleAPFloat(std::move(RHS.Double));
+ } else {
+ llvm_unreachable("Unexpected semantics");
+ }
+ }
+
+ Storage &operator=(const Storage &RHS) {
+ if (usesLayout<IEEEFloat>(*semantics) &&
+ usesLayout<IEEEFloat>(*RHS.semantics)) {
+ IEEE = RHS.IEEE;
+ } else if (usesLayout<DoubleAPFloat>(*semantics) &&
+ usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ Double = RHS.Double;
+ } else if (this != &RHS) {
+ this->~Storage();
+ new (this) Storage(RHS);
+ }
+ return *this;
+ }
- ~APFloat() { IEEE.~IEEEFloat(); }
+ Storage &operator=(Storage &&RHS) {
+ if (usesLayout<IEEEFloat>(*semantics) &&
+ usesLayout<IEEEFloat>(*RHS.semantics)) {
+ IEEE = std::move(RHS.IEEE);
+ } else if (usesLayout<DoubleAPFloat>(*semantics) &&
+ usesLayout<DoubleAPFloat>(*RHS.semantics)) {
+ Double = std::move(RHS.Double);
+ } else if (this != &RHS) {
+ this->~Storage();
+ new (this) Storage(RHS);
+ }
+ return *this;
+ }
+ } U;
- bool needsCleanup() const { return IEEE.needsCleanup(); }
+ template <typename T> static bool usesLayout(const fltSemantics &Semantics) {
+ static_assert(std::is_same<T, IEEEFloat>::value ||
+ std::is_same<T, DoubleAPFloat>::value, "");
+ if (std::is_same<T, DoubleAPFloat>::value) {
+ return &Semantics == &PPCDoubleDouble;
+ }
+ return &Semantics != &PPCDoubleDouble;
+ }
+ IEEEFloat &getIEEE() {
+ if (usesLayout<IEEEFloat>(*U.semantics)) {
+ return U.IEEE;
+ } else if (usesLayout<DoubleAPFloat>(*U.semantics)) {
+ return U.Double.getFirst().U.IEEE;
+ } else {
+ llvm_unreachable("Unexpected semantics");
+ }
+ }
+
+ const IEEEFloat &getIEEE() const {
+ if (usesLayout<IEEEFloat>(*U.semantics)) {
+ return U.IEEE;
+ } else if (usesLayout<DoubleAPFloat>(*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);
+ }
+
+ // FIXME: This is due to clang 3.3 (or older version) always checks for the
+ // default constructor in an array aggregate initialization, even if no
+ // elements in the array is default initialized.
+ APFloat() : U(IEEEdouble) {
+ 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)) {}
+
+public:
+ APFloat(const fltSemantics &Semantics) : U(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<IEEEFloat>(getSemantics())) {
+ return U.IEEE.needsCleanup();
+ } else if (usesLayout<DoubleAPFloat>(getSemantics())) {
+ return U.Double.needsCleanup();
+ } else {
+ llvm_unreachable("Unexpected semantics");
+ }
+ }
+
+ /// Factory for Positive and Negative Zero.
+ ///
+ /// \param Negative True iff the number should be negative.
static APFloat getZero(const fltSemantics &Sem, bool Negative = false) {
- return APFloat(IEEEFloat::getZero(Sem, Negative));
+ APFloat Val(Sem, uninitialized);
+ Val.makeZero(Negative);
+ return Val;
}
+ /// Factory for Positive and Negative Infinity.
+ ///
+ /// \param Negative True iff the number should be negative.
static APFloat getInf(const fltSemantics &Sem, bool Negative = false) {
- return APFloat(IEEEFloat::getInf(Sem, Negative));
+ APFloat Val(Sem, uninitialized);
+ Val.makeInf(Negative);
+ return Val;
}
+ /// 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) {
- return APFloat(IEEEFloat::getNaN(Sem, Negative, type));
+ if (type) {
+ APInt fill(64, type);
+ return getQNaN(Sem, Negative, &fill);
+ } else {
+ return getQNaN(Sem, Negative, nullptr);
+ }
}
+ /// Factory for QNaN values.
static APFloat getQNaN(const fltSemantics &Sem, bool Negative = false,
const APInt *payload = nullptr) {
- return APFloat(IEEEFloat::getQNaN(Sem, Negative, payload));
+ APFloat Val(Sem, uninitialized);
+ Val.makeNaN(false, Negative, payload);
+ return Val;
}
+ /// Factory for SNaN values.
static APFloat getSNaN(const fltSemantics &Sem, bool Negative = false,
const APInt *payload = nullptr) {
- return APFloat(IEEEFloat::getSNaN(Sem, Negative, payload));
+ APFloat Val(Sem, uninitialized);
+ Val.makeNaN(true, Negative, payload);
+ return Val;
}
+ /// 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) {
- return APFloat(IEEEFloat::getLargest(Sem, Negative));
+ APFloat Val(Sem, uninitialized);
+ Val.makeLargest(Negative);
+ return Val;
}
+ /// 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) {
- return APFloat(IEEEFloat::getSmallest(Sem, Negative));
+ APFloat Val(Sem, uninitialized);
+ Val.makeSmallest(Negative);
+ return Val;
}
+ /// 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) {
- return APFloat(IEEEFloat::getSmallestNormalized(Sem, Negative));
+ APFloat Val(Sem, uninitialized);
+ Val.makeSmallestNormalized(Negative);
+ return Val;
}
+ /// 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) {
- return APFloat(IEEEFloat::getAllOnesValue(BitWidth, isIEEE));
+ if (isIEEE) {
+ return APFloat(IEEEFloat::getAllOnesValue(BitWidth));
+ } else {
+ assert(BitWidth == 128);
+ return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
+ }
}
- void Profile(FoldingSetNodeID &NID) const { IEEE.Profile(NID); }
+ void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
opStatus add(const APFloat &RHS, roundingMode RM) {
- return IEEE.add(RHS.IEEE, RM);
+ return getIEEE().add(RHS.getIEEE(), RM);
}
opStatus subtract(const APFloat &RHS, roundingMode RM) {
- return IEEE.subtract(RHS.IEEE, RM);
+ return getIEEE().subtract(RHS.getIEEE(), RM);
}
opStatus multiply(const APFloat &RHS, roundingMode RM) {
- return IEEE.multiply(RHS.IEEE, RM);
+ return getIEEE().multiply(RHS.getIEEE(), RM);
}
opStatus divide(const APFloat &RHS, roundingMode RM) {
- return IEEE.divide(RHS.IEEE, RM);
+ return getIEEE().divide(RHS.getIEEE(), RM);
+ }
+ opStatus remainder(const APFloat &RHS) {
+ return getIEEE().remainder(RHS.getIEEE());
}
- opStatus remainder(const APFloat &RHS) { return IEEE.remainder(RHS.IEEE); }
- opStatus mod(const APFloat &RHS) { return IEEE.mod(RHS.IEEE); }
+ opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); }
opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
roundingMode RM) {
- return IEEE.fusedMultiplyAdd(Multiplicand.IEEE, Addend.IEEE, RM);
+ return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(),
+ RM);
}
- opStatus roundToIntegral(roundingMode RM) { return IEEE.roundToIntegral(RM); }
- opStatus next(bool nextDown) { return IEEE.next(nextDown); }
+ opStatus roundToIntegral(roundingMode RM) {
+ return getIEEE().roundToIntegral(RM);
+ }
+ opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
APFloat operator+(const APFloat &RHS) const {
- return APFloat(IEEE + RHS.IEEE);
+ return APFloat(getIEEE() + RHS.getIEEE());
}
APFloat operator-(const APFloat &RHS) const {
- return APFloat(IEEE - RHS.IEEE);
+ return APFloat(getIEEE() - RHS.getIEEE());
}
APFloat operator*(const APFloat &RHS) const {
- return APFloat(IEEE * RHS.IEEE);
+ return APFloat(getIEEE() * RHS.getIEEE());
}
APFloat operator/(const APFloat &RHS) const {
- return APFloat(IEEE / RHS.IEEE);
+ return APFloat(getIEEE() / RHS.getIEEE());
}
- void changeSign() { IEEE.changeSign(); }
- void clearSign() { IEEE.clearSign(); }
- void copySign(const APFloat &RHS) { IEEE.copySign(RHS.IEEE); }
+ 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.IEEE, Sign.IEEE));
+ return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()));
}
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
- bool *losesInfo) {
- return IEEE.convert(ToSemantics, RM, losesInfo);
- }
+ bool *losesInfo);
opStatus convertToInteger(integerPart *Input, unsigned int Width,
bool IsSigned, roundingMode RM,
bool *IsExact) const {
- return IEEE.convertToInteger(Input, Width, IsSigned, RM, IsExact);
+ return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact);
}
opStatus convertToInteger(APSInt &Result, roundingMode RM,
bool *IsExact) const {
- return IEEE.convertToInteger(Result, RM, IsExact);
+ return getIEEE().convertToInteger(Result, RM, IsExact);
}
opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
roundingMode RM) {
- return IEEE.convertFromAPInt(Input, IsSigned, RM);
+ return getIEEE().convertFromAPInt(Input, IsSigned, RM);
}
opStatus convertFromSignExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM) {
- return IEEE.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM);
+ return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned,
+ RM);
}
opStatus convertFromZeroExtendedInteger(const integerPart *Input,
unsigned int InputSize, bool IsSigned,
roundingMode RM) {
- return IEEE.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM);
+ return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
+ RM);
}
opStatus convertFromString(StringRef, roundingMode);
- APInt bitcastToAPInt() const { return IEEE.bitcastToAPInt(); }
- double convertToDouble() const { return IEEE.convertToDouble(); }
- float convertToFloat() const { return IEEE.convertToFloat(); }
+ APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); }
+ double convertToDouble() const { return getIEEE().convertToDouble(); }
+ float convertToFloat() const { return getIEEE().convertToFloat(); }
bool operator==(const APFloat &) const = delete;
- cmpResult compare(const APFloat &RHS) const { return IEEE.compare(RHS.IEEE); }
+ cmpResult compare(const APFloat &RHS) const {
+ return getIEEE().compare(RHS.getIEEE());
+ }
bool bitwiseIsEqual(const APFloat &RHS) const {
- return IEEE.bitwiseIsEqual(RHS.IEEE);
+ return getIEEE().bitwiseIsEqual(RHS.getIEEE());
}
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
bool UpperCase, roundingMode RM) const {
- return IEEE.convertToHexString(DST, HexDigits, UpperCase, RM);
+ return getIEEE().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 IEEE.isNegative(); }
- bool isDenormal() const { return IEEE.isDenormal(); }
- bool isSignaling() const { return IEEE.isSignaling(); }
+ bool isNegative() const { return getIEEE().isNegative(); }
+ bool isDenormal() const { return getIEEE().isDenormal(); }
+ bool isSignaling() const { return getIEEE().isSignaling(); }
bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
bool isFinite() const { return !isNaN() && !isInfinity(); }
- fltCategory getCategory() const { return IEEE.getCategory(); }
- const fltSemantics &getSemantics() const { return *semantics; }
+ fltCategory getCategory() const { return getIEEE().getCategory(); }
+ const fltSemantics &getSemantics() const { return *U.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 IEEE.isSmallest(); }
- bool isLargest() const { return IEEE.isLargest(); }
- bool isInteger() const { return IEEE.isInteger(); }
+ bool isSmallest() const { return getIEEE().isSmallest(); }
+ bool isLargest() const { return getIEEE().isLargest(); }
+ bool isInteger() const { return getIEEE().isInteger(); }
- APFloat &operator=(const APFloat &RHS) {
- IEEE = RHS.IEEE;
- return *this;
- }
- APFloat &operator=(APFloat &&RHS) {
- IEEE = std::move(RHS.IEEE);
- return *this;
- }
+ APFloat &operator=(const APFloat &RHS) = default;
+ APFloat &operator=(APFloat &&RHS) = default;
void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
unsigned FormatMaxPadding = 3) const {
- return IEEE.toString(Str, FormatPrecision, FormatMaxPadding);
+ return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
}
bool getExactInverse(APFloat *inv) const {
- return IEEE.getExactInverse(inv ? &inv->IEEE : nullptr);
+ return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr);
}
friend hash_code hash_value(const APFloat &Arg);
- friend int ilogb(const APFloat &Arg) { return ilogb(Arg.IEEE); }
+ friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
+ friend DoubleAPFloat;
};
/// See friend declarations above.
@@ -870,7 +1034,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.IEEE, Exp, RM));
+ return APFloat(scalbn(X.getIEEE(), Exp, RM));
}
/// \brief Equivalent of C standard library function.
@@ -878,7 +1042,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.IEEE, Exp, RM));
+ return APFloat(frexp(X.getIEEE(), Exp, RM));
}
/// \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=285358&r1=285357&r2=285358&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Thu Oct 27 17:52:40 2016
@@ -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
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
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(
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::convertF80LongDoubleAPF
}
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::initFromPPCDoubleDoubleA
// 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 fltS
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(uns
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 Negati
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, in
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
More information about the llvm-commits
mailing list