[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