[llvm] r285358 - Reapply r285351 "[APFloat] Add DoubleAPFloat mode to APFloat. NFC." with
Evgenii Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 28 11:09:35 PDT 2016
This is breaking the MSan bot.
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/151/steps/check-clang%20msan/logs/stdio
WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x48ebebb in
llvm::detail::IEEEFloat::assign(llvm::detail::IEEEFloat const&)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Support/APFloat.cpp:629:25
#1 0x490fa98 in APFloat
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/APFloat.h:785:3
#2 0x490fa98 in
llvm::detail::DoubleAPFloat::DoubleAPFloat(llvm::detail::DoubleAPFloat
const&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Support/APFloat.cpp:3880
#3 0x3a756ab in Storage
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/APFloat.h:676:20
#4 0x3a756ab in
llvm::APFloat::Storage::operator=(llvm::APFloat::Storage&&)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/APFloat.h:715
#5 0xa2b406a in operator=
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/APFloat.h:1013:45
#6 0xa2b406a in ZeroInitialization
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:8234
#7 0xa2b406a in (anonymous
namespace)::ExprEvaluatorBase<(anonymous
namespace)::FloatExprEvaluator>::DerivedZeroInitialization(clang::Expr
const*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:4171
#8 0xa2a7c5c in VisitImplicitValueInitExpr
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:4456:12
#9 0xa2a7c5c in clang::StmtVisitorBase<clang::make_const_ptr,
(anonymous namespace)::FloatExprEvaluator, bool>::Visit(clang::Stmt
const*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build_msan/tools/clang/include/clang/AST/StmtNodes.inc:537
#10 0xa1db318 in EvaluateFloat
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:8254:43
#11 0xa1db318 in Evaluate(clang::APValue&, (anonymous
namespace)::EvalInfo&, clang::Expr const*)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:9044
#12 0xa1d16f9 in EvaluateInPlace(clang::APValue&, (anonymous
namespace)::EvalInfo&, (anonymous namespace)::LValue const&,
clang::Expr const*, bool)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:9112:10
#13 0xa1d0d40 in
clang::Expr::EvaluateAsInitializer(clang::APValue&, clang::ASTContext
const&, clang::VarDecl const*,
llvm::SmallVectorImpl<std::__1::pair<clang::SourceLocation,
clang::PartialDiagnostic> >&) const
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/ExprConstant.cpp:9263:10
#14 0xa0a0f1e in
clang::VarDecl::evaluateValue(llvm::SmallVectorImpl<std::__1::pair<clang::SourceLocation,
clang::PartialDiagnostic> >&) const
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/Decl.cpp:2175:23
#15 0xa0a0ce1 in clang::VarDecl::evaluateValue() const
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/AST/Decl.cpp:2143:10
#16 0x5062a23 in
clang::CodeGen::CodeGenModule::EmitConstantInit(clang::VarDecl const&,
clang::CodeGen::CodeGenFunction*)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CGExprConstant.cpp:1217:32
#17 0x51bc3fb in
clang::CodeGen::CodeGenModule::EmitGlobalVarDefinition(clang::VarDecl
const*, bool) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:2450:12
#18 0x51aa0a5 in
clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl,
llvm::GlobalValue*)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:1833:12
#19 0x51c2dc5 in
clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CodeGenModule.cpp:3796:5
#20 0x6928a83 in (anonymous
namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/ModuleBuilder.cpp:148:18
#21 0x6924d49 in
clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp:126:12
#22 0x79dc1a4 in clang::ParseAST(clang::Sema&, bool, bool)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseAST.cpp:151:29
#23 0x5de9637 in clang::FrontendAction::Execute()
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:458:8
#24 0x5d33380 in
clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:871:11
#25 0x60146c0 in
clang::ExecuteCompilerInvocation(clang::CompilerInstance*)
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:249:25
#26 0x953e4c in cc1_main(llvm::ArrayRef<char const*>, char const*,
void*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/cc1_main.cpp:221:13
#27 0x94f0b2 in ExecuteCC1Tool
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:299:12
#28 0x94f0b2 in main
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:380
On Thu, Oct 27, 2016 at 3:52 PM, Tim Shen via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> 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
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list