[llvm] r289472 - [APFloat] Implement PPCDoubleDouble add and subtract.

Mike Aizatsky via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 12 16:48:34 PST 2016


I think this breaks ubsan:

http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/1361/steps/check-llvm%20ubsan/logs/stdio

FAILED: unittests/ADT/CMakeFiles/ADTTests.dir/APFloatTest.cpp.o
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm_build0/bin/clang++
  -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Iunittests/ADT
-I/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT
-Iinclude
-I/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include
-I/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/utils/unittest/googletest/include
-fsanitize=undefined -w -fPIC -fvisibility-inlines-hidden -Wall -W
-Wno-unused-parameter -Wwrite-strings -Wcast-qual
-Wmissing-field-initializers -pedantic -Wno-long-long
-Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor
-Werror=date-time -std=c++11 -fno-omit-frame-pointer -O1
-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all
-fcolor-diagnostics -g    -Wno-variadic-macros -fno-exceptions -fno-rtti
-MMD -MT unittests/ADT/CMakeFiles/ADTTests.dir/APFloatTest.cpp.o -MF
unittests/ADT/CMakeFiles/ADTTests.dir/APFloatTest.cpp.o.d -o
unittests/ADT/CMakeFiles/ADTTests.dir/APFloatTest.cpp.o -c
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp:3179:7:
error: chosen constructor is explicit in copy-initialization
      {0x3ff0000000000000ull, 0, 0xbff0000000000000ull, 0, APFloat::fcZero,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/tuple:406:19:
note: constructor declared here
        constexpr tuple(_UElements&&... __elements)
                  ^
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp:3182:7:
error: chosen constructor is explicit in copy-initialization
      {0x7fefffffffffffffull, 0x7c8ffffffffffffeull, 0x7948000000000000ull,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/tuple:406:19:
note: constructor declared here
        constexpr tuple(_UElements&&... __elements)
                  ^
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp:3188:7:
error: chosen constructor is explicit in copy-initialization
      {0x7fefffffffffffffull, 0x7c8ffffffffffffeull, 0x7947ffffffffffffull,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/tuple:406:19:
note: constructor declared here
        constexpr tuple(_UElements&&... __elements)
                  ^
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp:3191:7:
error: chosen constructor is explicit in copy-initialization
      {0x7fefffffffffffffull, 0x7c8ffffffffffffeull, 0x7fefffffffffffffull,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/tuple:406:19:
note: constructor declared here
        constexpr tuple(_UElements&&... __elements)
                  ^
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp:3195:7:
error: chosen constructor is explicit in copy-initialization
      {0x7ff8000000000000ull, 0, 0x3ff0000000000000ull, 0, APFloat::fcNaN,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/tuple:406:19:
note: constructor declared here
        constexpr tuple(_UElements&&... __elements)
                  ^
/mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/unittests/ADT/APFloatTest.cpp:3218:7:
error: chosen constructor is explicit in copy-initialization
      {0x3ff0000000000000ull, 0, 0x3960000000000000ull, 0,
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/tuple:406:19:
note: constructor declared here
        constexpr tuple(_UElements&&... __elements)
                  ^


On Mon, Dec 12, 2016 at 2:09 PM Tim Shen via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: timshen
> Date: Mon Dec 12 15:59:30 2016
> New Revision: 289472
>
> URL: http://llvm.org/viewvc/llvm-project?rev=289472&view=rev
> Log:
> [APFloat] Implement PPCDoubleDouble add and subtract.
>
> Summary:
> I looked at libgcc's implementation (which is based on the paper,
> Software for Doubled-Precision Floating-Point Computations", by Seppo
> Linnainmaa,
> ACM TOMS vol 7 no 3, September 1981, pages 272-283.) and made it generic to
> arbitrary IEEE floats.
>
> Differential Revision: https://reviews.llvm.org/D26817
>
> Modified:
>     llvm/trunk/include/llvm/ADT/APFloat.h
>     llvm/trunk/lib/Support/APFloat.cpp
>     llvm/trunk/unittests/ADT/APFloatTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/APFloat.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/APFloat.h?rev=289472&r1=289471&r2=289472&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/APFloat.h (original)
> +++ llvm/trunk/include/llvm/ADT/APFloat.h Mon Dec 12 15:59:30 2016
> @@ -27,6 +27,7 @@ struct fltSemantics;
>  class APSInt;
>  class StringRef;
>  class APFloat;
> +class raw_ostream;
>
>  template <typename T> class SmallVectorImpl;
>
> @@ -479,6 +480,8 @@ public:
>
>    /// @}
>
> +  cmpResult compareAbsoluteValue(const IEEEFloat &) const;
> +
>  private:
>    /// \name Simple Queries
>    /// @{
> @@ -527,7 +530,6 @@ private:
>    bool convertFromStringSpecials(StringRef str);
>    opStatus normalize(roundingMode, lostFraction);
>    opStatus addOrSubtract(const IEEEFloat &, roundingMode, bool subtract);
> -  cmpResult compareAbsoluteValue(const IEEEFloat &) const;
>    opStatus handleOverflow(roundingMode);
>    bool roundAwayFromZero(roundingMode, lostFraction, unsigned int) const;
>    opStatus convertToSignExtendedInteger(integerPart *, unsigned int, bool,
> @@ -600,6 +602,12 @@ class DoubleAPFloat final : public APFlo
>    const fltSemantics *Semantics;
>    std::unique_ptr<APFloat[]> Floats;
>
> +  opStatus addImpl(const APFloat &a, const APFloat &aa, const APFloat &c,
> +                   const APFloat &cc, roundingMode RM);
> +
> +  opStatus addWithSpecial(const DoubleAPFloat &LHS, const DoubleAPFloat
> &RHS,
> +                          DoubleAPFloat &Out, roundingMode RM);
> +
>  public:
>    DoubleAPFloat(const fltSemantics &S);
>    DoubleAPFloat(const fltSemantics &S, uninitializedTag);
> @@ -623,6 +631,19 @@ public:
>
>    APFloat &getFirst() { return Floats[0]; }
>    const APFloat &getFirst() const { return Floats[0]; }
> +  APFloat &getSecond() { return Floats[1]; }
> +  const APFloat &getSecond() const { return Floats[1]; }
> +
> +  opStatus add(const DoubleAPFloat &RHS, roundingMode RM);
> +  opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM);
> +  void changeSign();
> +  cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const;
> +
> +  fltCategory getCategory() const;
> +  bool isNegative() const;
> +
> +  void makeInf(bool Neg);
> +  void makeNaN(bool SNaN, bool Neg, const APInt *fill);
>  };
>
>  } // End detail namespace
> @@ -747,7 +768,15 @@ class APFloat : public APFloatBase {
>
>    void makeZero(bool Neg) { getIEEE().makeZero(Neg); }
>
> -  void makeInf(bool Neg) { getIEEE().makeInf(Neg); }
> +  void makeInf(bool Neg) {
> +    if (usesLayout<IEEEFloat>(*U.semantics)) {
> +      return U.IEEE.makeInf(Neg);
> +    } else if (usesLayout<DoubleAPFloat>(*U.semantics)) {
> +      return U.Double.makeInf(Neg);
> +    } else {
> +      llvm_unreachable("Unexpected semantics");
> +    }
> +  }
>
>    void makeNaN(bool SNaN, bool Neg, const APInt *fill) {
>      getIEEE().makeNaN(SNaN, Neg, fill);
> @@ -772,6 +801,17 @@ class APFloat : public APFloatBase {
>    explicit APFloat(DoubleAPFloat F, const fltSemantics &S)
>        : U(std::move(F), S) {}
>
> +  cmpResult compareAbsoluteValue(const APFloat &RHS) const {
> +    assert(&getSemantics() == &RHS.getSemantics());
> +    if (usesLayout<IEEEFloat>(getSemantics())) {
> +      return U.IEEE.compareAbsoluteValue(RHS.U.IEEE);
> +    } else if (usesLayout<DoubleAPFloat>(getSemantics())) {
> +      return U.Double.compareAbsoluteValue(RHS.U.Double);
> +    } else {
> +      llvm_unreachable("Unexpected semantics");
> +    }
> +  }
> +
>  public:
>    APFloat(const fltSemantics &Semantics) : U(Semantics) {}
>    APFloat(const fltSemantics &Semantics, StringRef S);
> @@ -885,10 +925,22 @@ public:
>    void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
>
>    opStatus add(const APFloat &RHS, roundingMode RM) {
> -    return getIEEE().add(RHS.getIEEE(), RM);
> +    if (usesLayout<IEEEFloat>(getSemantics())) {
> +      return U.IEEE.add(RHS.U.IEEE, RM);
> +    } else if (usesLayout<DoubleAPFloat>(getSemantics())) {
> +      return U.Double.add(RHS.U.Double, RM);
> +    } else {
> +      llvm_unreachable("Unexpected semantics");
> +    }
>    }
>    opStatus subtract(const APFloat &RHS, roundingMode RM) {
> -    return getIEEE().subtract(RHS.getIEEE(), RM);
> +    if (usesLayout<IEEEFloat>(getSemantics())) {
> +      return U.IEEE.subtract(RHS.U.IEEE, RM);
> +    } else if (usesLayout<DoubleAPFloat>(getSemantics())) {
> +      return U.Double.subtract(RHS.U.Double, RM);
> +    } else {
> +      llvm_unreachable("Unexpected semantics");
> +    }
>    }
>    opStatus multiply(const APFloat &RHS, roundingMode RM) {
>      return getIEEE().multiply(RHS.getIEEE(), RM);
> @@ -1011,14 +1063,25 @@ public:
>      return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
>    }
>
> +  void print(raw_ostream &) const;
> +  void dump() const;
> +
>    bool getExactInverse(APFloat *inv) const {
>      return getIEEE().getExactInverse(inv ? &inv->getIEEE() : nullptr);
>    }
>
> +  // This is for internal test only.
> +  // TODO: Remove it after the PPCDoubleDouble transition.
> +  const APFloat &getSecondFloat() const {
> +    assert(&getSemantics() == &PPCDoubleDouble);
> +    return U.Double.getSecond();
> +  }
> +
>    friend hash_code hash_value(const APFloat &Arg);
>    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 IEEEFloat;
>    friend DoubleAPFloat;
>  };
>
>
> Modified: llvm/trunk/lib/Support/APFloat.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APFloat.cpp?rev=289472&r1=289471&r2=289472&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Support/APFloat.cpp (original)
> +++ llvm/trunk/lib/Support/APFloat.cpp Mon Dec 12 15:59:30 2016
> @@ -19,8 +19,10 @@
>  #include "llvm/ADT/Hashing.h"
>  #include "llvm/ADT/StringExtras.h"
>  #include "llvm/ADT/StringRef.h"
> +#include "llvm/Support/Debug.h"
>  #include "llvm/Support/ErrorHandling.h"
>  #include "llvm/Support/MathExtras.h"
> +#include "llvm/Support/raw_ostream.h"
>  #include <cstring>
>  #include <limits.h>
>
> @@ -3847,8 +3849,9 @@ DoubleAPFloat::DoubleAPFloat(const fltSe
>  }
>
>  DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I)
> -    : Semantics(&S), Floats(new APFloat[2]{APFloat(PPCDoubleDoubleImpl,
> I),
> -                                           APFloat(IEEEdouble)}) {
> +    : Semantics(&S), Floats(new APFloat[2]{
> +                         APFloat(PPCDoubleDoubleImpl, I),
> +                         APFloat(IEEEdouble, APInt(64,
> I.getRawData()[1]))}) {
>    assert(Semantics == &PPCDoubleDouble);
>  }
>
> @@ -3858,7 +3861,8 @@ DoubleAPFloat::DoubleAPFloat(const fltSe
>        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[0].getSemantics() == &PPCDoubleDoubleImpl ||
> +         &Floats[0].getSemantics() == &IEEEdouble);
>    assert(&Floats[1].getSemantics() == &IEEEdouble);
>  }
>
> @@ -3887,6 +3891,198 @@ DoubleAPFloat &DoubleAPFloat::operator=(
>    return *this;
>  }
>
> +// "Software for Doubled-Precision Floating-Point Computations",
> +// by Seppo Linnainmaa, ACM TOMS vol 7 no 3, September 1981, pages
> 272-283.
> +APFloat::opStatus DoubleAPFloat::addImpl(const APFloat &a, const APFloat
> &aa,
> +                                         const APFloat &c, const APFloat
> &cc,
> +                                         roundingMode RM) {
> +  int Status = opOK;
> +  APFloat z = a;
> +  Status |= z.add(c, RM);
> +  if (!z.isFinite()) {
> +    if (!z.isInfinity()) {
> +      Floats[0] = std::move(z);
> +      Floats[1].makeZero(false);
> +      return (opStatus)Status;
> +    }
> +    Status = opOK;
> +    auto AComparedToC = a.compareAbsoluteValue(c);
> +    z = cc;
> +    Status |= z.add(aa, RM);
> +    if (AComparedToC == APFloat::cmpGreaterThan) {
> +      // z = cc + aa + c + a;
> +      Status |= z.add(c, RM);
> +      Status |= z.add(a, RM);
> +    } else {
> +      // z = cc + aa + a + c;
> +      Status |= z.add(a, RM);
> +      Status |= z.add(c, RM);
> +    }
> +    if (!z.isFinite()) {
> +      Floats[0] = std::move(z);
> +      Floats[1].makeZero(false);
> +      return (opStatus)Status;
> +    }
> +    Floats[0] = z;
> +    APFloat zz = aa;
> +    Status |= zz.add(cc, RM);
> +    if (AComparedToC == APFloat::cmpGreaterThan) {
> +      // Floats[1] = a - z + c + zz;
> +      Floats[1] = a;
> +      Status |= Floats[1].subtract(z, RM);
> +      Status |= Floats[1].add(c, RM);
> +      Status |= Floats[1].add(zz, RM);
> +    } else {
> +      // Floats[1] = c - z + a + zz;
> +      Floats[1] = c;
> +      Status |= Floats[1].subtract(z, RM);
> +      Status |= Floats[1].add(a, RM);
> +      Status |= Floats[1].add(zz, RM);
> +    }
> +  } else {
> +    // q = a - z;
> +    APFloat q = a;
> +    Status |= q.subtract(z, RM);
> +
> +    // zz = q + c + (a - (q + z)) + aa + cc;
> +    // Compute a - (q + z) as -((q + z) - a) to avoid temporary copies.
> +    auto zz = q;
> +    Status |= zz.add(c, RM);
> +    Status |= q.add(z, RM);
> +    Status |= q.subtract(a, RM);
> +    q.changeSign();
> +    Status |= zz.add(q, RM);
> +    Status |= zz.add(aa, RM);
> +    Status |= zz.add(cc, RM);
> +    if (zz.isZero() && !zz.isNegative()) {
> +      Floats[0] = std::move(z);
> +      Floats[1].makeZero(false);
> +      return opOK;
> +    }
> +    Floats[0] = z;
> +    Status |= Floats[0].add(zz, RM);
> +    if (!Floats[0].isFinite()) {
> +      Floats[1].makeZero(false);
> +      return (opStatus)Status;
> +    }
> +    Floats[1] = std::move(z);
> +    Status |= Floats[1].subtract(Floats[0], RM);
> +    Status |= Floats[1].add(zz, RM);
> +  }
> +  return (opStatus)Status;
> +}
> +
> +APFloat::opStatus DoubleAPFloat::addWithSpecial(const DoubleAPFloat &LHS,
> +                                                const DoubleAPFloat &RHS,
> +                                                DoubleAPFloat &Out,
> +                                                roundingMode RM) {
> +  if (LHS.getCategory() == fcNaN) {
> +    Out = LHS;
> +    return opOK;
> +  }
> +  if (RHS.getCategory() == fcNaN) {
> +    Out = RHS;
> +    return opOK;
> +  }
> +  if (LHS.getCategory() == fcZero) {
> +    Out = RHS;
> +    return opOK;
> +  }
> +  if (RHS.getCategory() == fcZero) {
> +    Out = LHS;
> +    return opOK;
> +  }
> +  if (LHS.getCategory() == fcInfinity && RHS.getCategory() == fcInfinity
> &&
> +      LHS.isNegative() != RHS.isNegative()) {
> +    Out.makeNaN(false, Out.isNegative(), nullptr);
> +    return opInvalidOp;
> +  }
> +  if (LHS.getCategory() == fcInfinity) {
> +    Out = LHS;
> +    return opOK;
> +  }
> +  if (RHS.getCategory() == fcInfinity) {
> +    Out = RHS;
> +    return opOK;
> +  }
> +  assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal);
> +
> +  // These conversions will go away once PPCDoubleDoubleImpl goes away.
> +  // (PPCDoubleDoubleImpl, IEEEDouble) -> (IEEEDouble, IEEEDouble)
> +  APFloat A(IEEEdouble,
> +            APInt(64, LHS.Floats[0].bitcastToAPInt().getRawData()[0])),
> +      AA(LHS.Floats[1]),
> +      C(IEEEdouble, APInt(64,
> RHS.Floats[0].bitcastToAPInt().getRawData()[0])),
> +      CC(RHS.Floats[1]);
> +  assert(&AA.getSemantics() == &IEEEdouble);
> +  assert(&CC.getSemantics() == &IEEEdouble);
> +  Out.Floats[0] = APFloat(IEEEdouble);
> +  assert(&Out.Floats[1].getSemantics() == &IEEEdouble);
> +
> +  auto Ret = Out.addImpl(A, AA, C, CC, RM);
> +
> +  // (IEEEDouble, IEEEDouble) -> (PPCDoubleDoubleImpl, IEEEDouble)
> +  uint64_t Buffer[] = {Out.Floats[0].bitcastToAPInt().getRawData()[0],
> +                       Out.Floats[1].bitcastToAPInt().getRawData()[0]};
> +  Out.Floats[0] = APFloat(PPCDoubleDoubleImpl, APInt(128, 2, Buffer));
> +  return Ret;
> +}
> +
> +APFloat::opStatus DoubleAPFloat::add(const DoubleAPFloat &RHS,
> +                                     roundingMode RM) {
> +  return addWithSpecial(*this, RHS, *this, RM);
> +}
> +
> +APFloat::opStatus DoubleAPFloat::subtract(const DoubleAPFloat &RHS,
> +                                          roundingMode RM) {
> +  changeSign();
> +  auto Ret = add(RHS, RM);
> +  changeSign();
> +  return Ret;
> +}
> +
> +void DoubleAPFloat::changeSign() {
> +  Floats[0].changeSign();
> +  Floats[1].changeSign();
> +}
> +
> +APFloat::cmpResult
> +DoubleAPFloat::compareAbsoluteValue(const DoubleAPFloat &RHS) const {
> +  auto Result = Floats[0].compareAbsoluteValue(RHS.Floats[0]);
> +  if (Result != cmpEqual)
> +    return Result;
> +  Result = Floats[1].compareAbsoluteValue(RHS.Floats[1]);
> +  if (Result == cmpLessThan || Result == cmpGreaterThan) {
> +    auto Against = Floats[0].isNegative() ^ Floats[1].isNegative();
> +    auto RHSAgainst = RHS.Floats[0].isNegative() ^
> RHS.Floats[1].isNegative();
> +    if (Against && !RHSAgainst)
> +      return cmpLessThan;
> +    if (!Against && RHSAgainst)
> +      return cmpGreaterThan;
> +    if (!Against && !RHSAgainst)
> +      return Result;
> +    if (Against && RHSAgainst)
> +      return (cmpResult)(cmpLessThan + cmpGreaterThan - Result);
> +  }
> +  return Result;
> +}
> +
> +APFloat::fltCategory DoubleAPFloat::getCategory() const {
> +  return Floats[0].getCategory();
> +}
> +
> +bool DoubleAPFloat::isNegative() const { return Floats[0].isNegative(); }
> +
> +void DoubleAPFloat::makeInf(bool Neg) {
> +  Floats[0].makeInf(Neg);
> +  Floats[1].makeZero(false);
> +}
> +
> +void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) {
> +  Floats[0].makeNaN(SNaN, Neg, fill);
> +  Floats[1].makeZero(false);
> +}
> +
>  } // End detail namespace
>
>  APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
> @@ -3959,4 +4155,12 @@ APFloat APFloat::getAllOnesValue(unsigne
>    }
>  }
>
> +void APFloat::print(raw_ostream &OS) const {
> +  SmallVector<char, 16> Buffer;
> +  toString(Buffer);
> +  OS << Buffer << "\n";
> +}
> +
> +void APFloat::dump() const { print(dbgs()); }
> +
>  } // End llvm namespace
>
> Modified: llvm/trunk/unittests/ADT/APFloatTest.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APFloatTest.cpp?rev=289472&r1=289471&r2=289472&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/ADT/APFloatTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/APFloatTest.cpp Mon Dec 12 15:59:30 2016
> @@ -1512,22 +1512,6 @@ TEST(APFloatTest, PPCDoubleDouble) {
>    EXPECT_EQ(0x0360000000000000ull, test.bitcastToAPInt().getRawData()[0]);
>    EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
>
> -  test = APFloat(APFloat::PPCDoubleDouble, "1.0");
> -  test.add(APFloat(APFloat::PPCDoubleDouble, "0x1p-105"),
> APFloat::rmNearestTiesToEven);
> -  EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]);
> -  EXPECT_EQ(0x3960000000000000ull, test.bitcastToAPInt().getRawData()[1]);
> -
> -  test = APFloat(APFloat::PPCDoubleDouble, "1.0");
> -  test.add(APFloat(APFloat::PPCDoubleDouble, "0x1p-106"),
> APFloat::rmNearestTiesToEven);
> -  EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]);
> -#if 0 // XFAIL
> -  // This is what we would expect with a true double-double implementation
> -  EXPECT_EQ(0x3950000000000000ull, test.bitcastToAPInt().getRawData()[1]);
> -#else
> -  // This is what we get with our 106-bit mantissa approximation
> -  EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
> -#endif
> -
>    // PR30869
>    {
>      auto Result = APFloat(APFloat::PPCDoubleDouble, "1.0") +
> @@ -3186,4 +3170,123 @@ TEST(APFloatTest, frexp) {
>    EXPECT_EQ(52, Exp);
>    EXPECT_TRUE(APFloat(APFloat::IEEEdouble,
> "0x1.c60f120d9f87cp-1").bitwiseIsEqual(Frac));
>  }
> +
> +TEST(APFloatTest, PPCDoubleDoubleAddSpecial) {
> +  using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
> +                              APFloat::fltCategory,
> APFloat::roundingMode>;
> +  DataType Data[] = {
> +      // (1 + 0) + (-1 + 0) = fcZero
> +      {0x3ff0000000000000ull, 0, 0xbff0000000000000ull, 0,
> APFloat::fcZero,
> +       APFloat::rmNearestTiesToEven},
> +      // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = fcInfinity
> +      {0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
> 0x7948000000000000ull,
> +       0ull, APFloat::fcInfinity, APFloat::rmNearestTiesToEven},
> +      // TODO: change the 4th 0x75effffffffffffe to 0x75efffffffffffff
> when
> +      // PPCDoubleDoubleImpl is gone.
> +      // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >>
> (1023 -
> +      // 160))) = fcNormal
> +      {0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
> 0x7947ffffffffffffull,
> +       0x75effffffffffffeull, APFloat::fcNormal,
> APFloat::rmNearestTiesToEven},
> +      // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = fcInfinity
> +      {0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
> 0x7fefffffffffffffull,
> +       0x7c8ffffffffffffeull, APFloat::fcInfinity,
> +       APFloat::rmNearestTiesToEven},
> +      // NaN + (1 + 0) = fcNaN
> +      {0x7ff8000000000000ull, 0, 0x3ff0000000000000ull, 0, APFloat::fcNaN,
> +       APFloat::rmNearestTiesToEven},
> +  };
> +
> +  for (auto Tp : Data) {
> +    uint64_t Op1[2], Op2[2];
> +    APFloat::fltCategory Expected;
> +    APFloat::roundingMode RM;
> +    std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected, RM) = Tp;
> +
> +    APFloat A1(APFloat::PPCDoubleDouble, APInt(128, 2, Op1));
> +    APFloat A2(APFloat::PPCDoubleDouble, APInt(128, 2, Op2));
> +    A1.add(A2, RM);
> +
> +    EXPECT_EQ(Expected, A1.getCategory());
> +  }
> +}
> +
> +TEST(APFloatTest, PPCDoubleDoubleAdd) {
> +  using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
> uint64_t,
> +                              uint64_t, APFloat::roundingMode>;
> +  DataType Data[] = {
> +      // (1 + 0) + (1e-105 + 0) = (1 + 1e-105)
> +      {0x3ff0000000000000ull, 0, 0x3960000000000000ull, 0,
> +       0x3ff0000000000000ull, 0x3960000000000000ull,
> +       APFloat::rmNearestTiesToEven},
> +      // (1 + 0) + (1e-106 + 0) = (1 + 1e-106)
> +      {0x3ff0000000000000ull, 0, 0x3950000000000000ull, 0,
> +       0x3ff0000000000000ull, 0x3950000000000000ull,
> +       APFloat::rmNearestTiesToEven},
> +      // (1 + 1e-106) + (1e-106 + 0) = (1 + 1e-105)
> +      {0x3ff0000000000000ull, 0x3950000000000000ull,
> 0x3950000000000000ull, 0,
> +       0x3ff0000000000000ull, 0x3960000000000000ull,
> +       APFloat::rmNearestTiesToEven},
> +      // (1 + 0) + (epsilon + 0) = (1 + epsilon)
> +      {0x3ff0000000000000ull, 0, 0x0000000000000001ull, 0,
> +       0x3ff0000000000000ull, 0x0000000000000001ull,
> +       APFloat::rmNearestTiesToEven},
> +      // TODO: change 0xf950000000000000 to 0xf940000000000000, when
> +      // PPCDoubleDoubleImpl is gone.
> +      // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX
> +
> +      // 1.11111... << (1023 - 52)
> +      {0x7fefffffffffffffull, 0xf950000000000000ull,
> 0x7c90000000000000ull, 0,
> +       0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
> +       APFloat::rmNearestTiesToEven},
> +      // TODO: change 0xf950000000000000 to 0xf940000000000000, when
> +      // PPCDoubleDoubleImpl is gone.
> +      // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX
> +
> +      // 1.11111... << (1023 - 52)
> +      {0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
> 0xf950000000000000ull,
> +       0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
> +       APFloat::rmNearestTiesToEven},
> +  };
> +
> +  for (auto Tp : Data) {
> +    uint64_t Op1[2], Op2[2], Expected[2];
> +    APFloat::roundingMode RM;
> +    std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1],
> RM) = Tp;
> +
> +    APFloat A1(APFloat::PPCDoubleDouble, APInt(128, 2, Op1));
> +    APFloat A2(APFloat::PPCDoubleDouble, APInt(128, 2, Op2));
> +    A1.add(A2, RM);
> +
> +    EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0]);
> +    EXPECT_EQ(Expected[1],
> +              A1.getSecondFloat().bitcastToAPInt().getRawData()[0]);
> +  }
> +}
> +
> +TEST(APFloatTest, PPCDoubleDoubleSubtract) {
> +  using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
> uint64_t,
> +                              uint64_t, APFloat::roundingMode>;
> +  DataType Data[] = {
> +      // (1 + 0) - (-1e-105 + 0) = (1 + 1e-105)
> +      {0x3ff0000000000000ull, 0, 0xb960000000000000ull, 0,
> +       0x3ff0000000000000ull, 0x3960000000000000ull,
> +       APFloat::rmNearestTiesToEven},
> +      // (1 + 0) - (-1e-106 + 0) = (1 + 1e-106)
> +      {0x3ff0000000000000ull, 0, 0xb950000000000000ull, 0,
> +       0x3ff0000000000000ull, 0x3950000000000000ull,
> +       APFloat::rmNearestTiesToEven},
> +  };
> +
> +  for (auto Tp : Data) {
> +    uint64_t Op1[2], Op2[2], Expected[2];
> +    APFloat::roundingMode RM;
> +    std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1],
> RM) = Tp;
> +
> +    APFloat A1(APFloat::PPCDoubleDouble, APInt(128, 2, Op1));
> +    APFloat A2(APFloat::PPCDoubleDouble, APInt(128, 2, Op2));
> +    A1.subtract(A2, RM);
> +
> +    EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0]);
> +    EXPECT_EQ(Expected[1],
> +              A1.getSecondFloat().bitcastToAPInt().getRawData()[0]);
> +  }
> +}
>  }
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-- 
Mike
Sent from phone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161213/3ea72934/attachment-0001.html>


More information about the llvm-commits mailing list