timshen updated this revision to Diff 85217.
timshen marked 2 inline comments as done.
timshen added a comment.

Stylish changes.


https://reviews.llvm.org/D27872

Files:
  clang/test/CodeGen/ppc64-complex-parms.c
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/test/CodeGen/PowerPC/fp128-bitcast-after-operation.ll
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===================================================================
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -9,6 +9,7 @@
 
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
@@ -3181,7 +3182,7 @@
                       0x7948000000000000ull, 0ull, APFloat::fcInfinity,
                       APFloat::rmNearestTiesToEven),
       // TODO: change the 4th 0x75effffffffffffe to 0x75efffffffffffff when
-      // PPCDoubleDoubleImpl is gone.
+      // semPPCDoubleDoubleLegacy is gone.
       // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >> (1023 -
       // 160))) = fcNormal
       std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
@@ -3234,14 +3235,14 @@
                       0x3ff0000000000000ull, 0x0000000000000001ull,
                       APFloat::rmNearestTiesToEven),
       // TODO: change 0xf950000000000000 to 0xf940000000000000, when
-      // PPCDoubleDoubleImpl is gone.
+      // semPPCDoubleDoubleLegacy is gone.
       // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX +
       // 1.11111... << (1023 - 52)
       std::make_tuple(0x7fefffffffffffffull, 0xf950000000000000ull,
                       0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
                       0x7c8ffffffffffffeull, APFloat::rmNearestTiesToEven),
       // TODO: change 0xf950000000000000 to 0xf940000000000000, when
-      // PPCDoubleDoubleImpl is gone.
+      // semPPCDoubleDoubleLegacy is gone.
       // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX +
       // 1.11111... << (1023 - 52)
       std::make_tuple(0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
@@ -3262,7 +3263,7 @@
         << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
                    Op2[1])
                .str();
-    EXPECT_EQ(Expected[1], A1.getSecondFloat().bitcastToAPInt().getRawData()[0])
+    EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
         << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
                    Op2[1])
                .str();
@@ -3296,7 +3297,7 @@
         << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
                    Op2[1])
                .str();
-    EXPECT_EQ(Expected[1], A1.getSecondFloat().bitcastToAPInt().getRawData()[0])
+    EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
         << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
                    Op2[1])
                .str();
@@ -3496,12 +3497,53 @@
     APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
     APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
     EXPECT_EQ(Expected, A1.compare(A2))
-        << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
+        << formatv("compare(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1],
+                   Op2[0], Op2[1])
+               .str();
+  }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleBitwiseIsEqual) {
+  using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, bool>;
+
+  DataType Data[] = {
+      // (1 + 0) = (1 + 0)
+      std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000000ull, 0, true),
+      // (1 + 0) != (1.00...1 + 0)
+      std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull, 0,
+                      false),
+      // NaN = NaN
+      std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, 0, true),
+      // NaN != NaN with a different bit pattern
+      std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull,
+                      0x3ff0000000000000ull, false),
+      // Inf = Inf
+      std::make_tuple(0x7ff0000000000000ull, 0, 0x7ff0000000000000ull, 0, true),
+  };
+
+  for (auto Tp : Data) {
+    uint64_t Op1[2], Op2[2];
+    bool Expected;
+    std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected) = Tp;
+
+    APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+    APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+    EXPECT_EQ(Expected, A1.bitwiseIsEqual(A2))
+        << formatv("({0:x} + {1:x}) = ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
                    Op2[1])
                .str();
   }
 }
 
+TEST(APFloatTest, PPCDoubleDoubleHashValue) {
+  uint64_t Data1[] = {0x3ff0000000000001ull, 0x0000000000000001ull};
+  uint64_t Data2[] = {0x3ff0000000000001ull, 0};
+  // The hash values are *hopefully* different.
+  EXPECT_NE(
+      hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data1))),
+      hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data2))));
+}
+
 TEST(APFloatTest, PPCDoubleDoubleChangeSign) {
   uint64_t Data[] = {
       0x400f000000000000ull, 0xbcb0000000000000ull,
@@ -3531,6 +3573,13 @@
   }
   {
     uint64_t Data[] = {
+        0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+    };
+    EXPECT_EQ(APInt(128, 2, Data),
+              APFloat::getLargest(APFloat::PPCDoubleDouble()).bitcastToAPInt());
+  }
+  {
+    uint64_t Data[] = {
         0x0000000000000001ull, 0,
     };
     EXPECT_EQ(
@@ -3553,24 +3602,72 @@
   }
   {
     uint64_t Data[] = {
+        0xffefffffffffffffull, 0xfc8ffffffffffffeull,
+    };
+    EXPECT_EQ(
+        APInt(128, 2, Data),
+        APFloat::getLargest(APFloat::PPCDoubleDouble(), true).bitcastToAPInt());
+  }
+  {
+    uint64_t Data[] = {
         0x8000000000000001ull, 0x0000000000000000ull,
     };
     EXPECT_EQ(APInt(128, 2, Data),
               APFloat::getSmallest(APFloat::PPCDoubleDouble(), true)
                   .bitcastToAPInt());
   }
-
-  EXPECT_EQ(0x8360000000000000ull,
-            APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true)
-                .bitcastToAPInt()
-                .getRawData()[0]);
-  EXPECT_EQ(0x0000000000000000ull,
-            APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true)
-                .getSecondFloat()
-                .bitcastToAPInt()
-                .getRawData()[0]);
-
+  {
+    uint64_t Data[] = {
+        0x8360000000000000ull, 0x0000000000000000ull,
+    };
+    EXPECT_EQ(APInt(128, 2, Data),
+              APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true)
+                  .bitcastToAPInt());
+  }
   EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isSmallest());
   EXPECT_TRUE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isLargest());
 }
+
+TEST(APFloatTest, PPCDoubleDoubleIsDenormal) {
+  EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isDenormal());
+  EXPECT_FALSE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isDenormal());
+  EXPECT_FALSE(
+      APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble()).isDenormal());
+  {
+    // (4 + 3) is not normalized
+    uint64_t Data[] = {
+        0x4010000000000000ull, 0x4008000000000000ull,
+    };
+    EXPECT_TRUE(
+        APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data)).isDenormal());
+  }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleScalbn) {
+  // 3.0 + 3.0 << 53
+  uint64_t Input[] = {
+      0x4008000000000000ull, 0x3cb8000000000000ull,
+  };
+  APFloat Result =
+      scalbn(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), 1,
+             APFloat::rmNearestTiesToEven);
+  // 6.0 + 6.0 << 53
+  EXPECT_EQ(0x4018000000000000ull, Result.bitcastToAPInt().getRawData()[0]);
+  EXPECT_EQ(0x3cc8000000000000ull, Result.bitcastToAPInt().getRawData()[1]);
+}
+
+TEST(APFloatTest, PPCDoubleDoubleFrexp) {
+  // 3.0 + 3.0 << 53
+  uint64_t Input[] = {
+      0x4008000000000000ull, 0x3cb8000000000000ull,
+  };
+  int Exp;
+  // 0.75 + 0.75 << 53
+  APFloat Result =
+      frexp(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), Exp,
+            APFloat::rmNearestTiesToEven);
+  EXPECT_EQ(2, Exp);
+  EXPECT_EQ(0x3fe8000000000000ull, Result.bitcastToAPInt().getRawData()[0]);
+  EXPECT_EQ(0x3c98000000000000ull, Result.bitcastToAPInt().getRawData()[1]);
+}
 }
Index: llvm/test/CodeGen/PowerPC/fp128-bitcast-after-operation.ll
===================================================================
--- llvm/test/CodeGen/PowerPC/fp128-bitcast-after-operation.ll
+++ llvm/test/CodeGen/PowerPC/fp128-bitcast-after-operation.ll
@@ -128,7 +128,7 @@
 ; PPC32-DAG: oris {{[0-9]+}}, [[FLIP_BIT]], 16399
 ; PPC32-DAG: xoris {{[0-9]+}}, [[FLIP_BIT]], 48304
 ; PPC32: blr
-	%0 = tail call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xMBCB0000000000000400F000000000000, ppc_fp128 %x)
+	%0 = tail call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 0xM400F000000000000BCB0000000000000, ppc_fp128 %x)
 	%1 = bitcast ppc_fp128 %0 to i128
 	ret i128 %1
 }
Index: llvm/lib/Support/APFloat.cpp
===================================================================
--- llvm/lib/Support/APFloat.cpp
+++ llvm/lib/Support/APFloat.cpp
@@ -83,16 +83,26 @@
      and we heavily rely on them having distinct addresses.             */
   static const fltSemantics semPPCDoubleDouble = {-1, 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.
+  /* These are legacy semantics for the fallback, inaccrurate implementation of
+     IBM double-double, if the accurate semPPCDoubleDouble doesn't handle the
+     case. It's equivalent to have an IEEE number with consecutive 106 bits of
+     mantissa, and 11 bits of exponent. It's not accurate, becuase the two
+     53-bit mantissa parts don't actually have to be consecutive,
+     e.g. 1 + epsilon.
 
-     TODO: Once all functions support DoubleAPFloat mode, we'll change all
-     PPCDoubleDoubleImpl to IEEEdouble and remove PPCDoubleDoubleImpl.  */
-  static const fltSemantics semPPCDoubleDoubleImpl = {1023, -1022 + 53, 53 + 53,
-                                                      128};
+     Currently, these semantics are used in the following way:
+
+       (IEEEdouble, IEEEdouble) -> (64-bit APInt, 64-bit APInt) ->
+       (128-bit APInt) -> semPPCDoubleDoubleLegacy -> IEEE operations
+
+     We use bitcastToAPInt() to get the bit representation (in APInt) of the
+     underlying IEEEdouble, then use the APInt constructor to construct the
+     legacy IEEE float.
+
+     TODO: Implement all operations in semPPCDoubleDouble, and delete these
+     semantics.  */
+  static const fltSemantics semPPCDoubleDoubleLegacy = {1023, -1022 + 53,
+                                                        53 + 53, 128};
 
   const fltSemantics &APFloatBase::IEEEhalf() {
     return semIEEEhalf;
@@ -862,11 +872,6 @@
 
 IEEEFloat::~IEEEFloat() { freeSignificand(); }
 
-// Profile - This method 'profiles' an APFloat for use with FoldingSet.
-void IEEEFloat::Profile(FoldingSetNodeID &ID) const {
-  ID.Add(bitcastToAPInt());
-}
-
 unsigned int IEEEFloat::partCount() const {
   return partCountForBits(semantics->precision + 1);
 }
@@ -1611,16 +1616,6 @@
   sign = !sign;
 }
 
-void IEEEFloat::clearSign() {
-  /* So is this one. */
-  sign = 0;
-}
-
-void IEEEFloat::copySign(const IEEEFloat &rhs) {
-  /* And this one. */
-  sign = rhs.sign;
-}
-
 /* Normalized addition or subtraction.  */
 IEEEFloat::opStatus IEEEFloat::addOrSubtract(const IEEEFloat &rhs,
                                              roundingMode rounding_mode,
@@ -1840,7 +1835,7 @@
   IEEEFloat MagicConstant(*semantics);
   fs = MagicConstant.convertFromAPInt(IntegerConstant, false,
                                       rmNearestTiesToEven);
-  MagicConstant.copySign(*this);
+  MagicConstant.sign = sign;
 
   if (fs != opOK)
     return fs;
@@ -2185,22 +2180,6 @@
   return fs;
 }
 
-/* Same as convertToInteger(integerPart*, ...), except the result is returned in
-   an APSInt, whose initial bit-width and signed-ness are used to determine the
-   precision of the conversion.
- */
-IEEEFloat::opStatus IEEEFloat::convertToInteger(APSInt &result,
-                                                roundingMode rounding_mode,
-                                                bool *isExact) const {
-  unsigned bitWidth = result.getBitWidth();
-  SmallVector<uint64_t, 4> parts(result.getNumWords());
-  opStatus status = convertToInteger(
-    parts.data(), bitWidth, result.isSigned(), rounding_mode, isExact);
-  // Keeps the original signed-ness.
-  result = APInt(bitWidth, parts);
-  return status;
-}
-
 /* Convert an unsigned integer SRC to a floating point number,
    rounding according to ROUNDING_MODE.  The sign of the floating
    point number is not modified.  */
@@ -2852,7 +2831,7 @@
 }
 
 APInt IEEEFloat::convertPPCDoubleDoubleAPFloatToAPInt() const {
-  assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleImpl);
+  assert(semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy);
   assert(partCount()==2);
 
   uint64_t words[2];
@@ -3033,7 +3012,7 @@
   if (semantics == (const llvm::fltSemantics*)&semIEEEquad)
     return convertQuadrupleAPFloatToAPInt();
 
-  if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleImpl)
+  if (semantics == (const llvm::fltSemantics *)&semPPCDoubleDoubleLegacy)
     return convertPPCDoubleDoubleAPFloatToAPInt();
 
   assert(semantics == (const llvm::fltSemantics*)&semX87DoubleExtended &&
@@ -3103,14 +3082,14 @@
 
   // Get the first double and convert to our format.
   initFromDoubleAPInt(APInt(64, i1));
-  fs = convert(semPPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo);
+  fs = convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo);
   assert(fs == opOK && !losesInfo);
   (void)fs;
 
   // Unless we have a special case, add in second double.
   if (isFiniteNonZero()) {
     IEEEFloat v(semIEEEdouble, APInt(64, i2));
-    fs = v.convert(semPPCDoubleDoubleImpl, rmNearestTiesToEven, &losesInfo);
+    fs = v.convert(semPPCDoubleDoubleLegacy, rmNearestTiesToEven, &losesInfo);
     assert(fs == opOK && !losesInfo);
     (void)fs;
 
@@ -3264,7 +3243,7 @@
     return initFromF80LongDoubleAPInt(api);
   if (Sem == &semIEEEquad)
     return initFromQuadrupleAPInt(api);
-  if (Sem == &semPPCDoubleDoubleImpl)
+  if (Sem == &semPPCDoubleDoubleLegacy)
     return initFromPPCDoubleDoubleAPInt(api);
 
   llvm_unreachable(nullptr);
@@ -3620,7 +3599,7 @@
     Str.push_back(buffer[NDigits-I-1]);
 }
 
-bool IEEEFloat::getExactInverse(IEEEFloat *inv) const {
+bool IEEEFloat::getExactInverse(APFloat *inv) const {
   // Special floats and denormals have no exact inverse.
   if (!isFiniteNonZero())
     return false;
@@ -3644,7 +3623,7 @@
          reciprocal.significandLSB() == reciprocal.semantics->precision - 1);
 
   if (inv)
-    *inv = reciprocal;
+    *inv = APFloat(reciprocal, *semantics);
 
   return true;
 }
@@ -3856,39 +3835,38 @@
 }
 
 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S)
-    : Semantics(&S), Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl),
-                                           APFloat(semIEEEdouble)}) {
+    : Semantics(&S),
+      Floats(new APFloat[2]{APFloat(semIEEEdouble), APFloat(semIEEEdouble)}) {
   assert(Semantics == &semPPCDoubleDouble);
 }
 
 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, uninitializedTag)
     : Semantics(&S),
-      Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl, uninitialized),
+      Floats(new APFloat[2]{APFloat(semIEEEdouble, uninitialized),
                             APFloat(semIEEEdouble, uninitialized)}) {
   assert(Semantics == &semPPCDoubleDouble);
 }
 
 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, integerPart I)
-    : Semantics(&S), Floats(new APFloat[2]{APFloat(semPPCDoubleDoubleImpl, I),
+    : Semantics(&S), Floats(new APFloat[2]{APFloat(semIEEEdouble, I),
                                            APFloat(semIEEEdouble)}) {
   assert(Semantics == &semPPCDoubleDouble);
 }
 
 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, const APInt &I)
-    : Semantics(&S), Floats(new APFloat[2]{
-                         APFloat(semPPCDoubleDoubleImpl, I),
-                         APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) {
+    : Semantics(&S),
+      Floats(new APFloat[2]{
+          APFloat(semIEEEdouble, APInt(64, I.getRawData()[0])),
+          APFloat(semIEEEdouble, APInt(64, I.getRawData()[1]))}) {
   assert(Semantics == &semPPCDoubleDouble);
 }
 
 DoubleAPFloat::DoubleAPFloat(const fltSemantics &S, APFloat &&First,
                              APFloat &&Second)
     : Semantics(&S),
       Floats(new APFloat[2]{std::move(First), std::move(Second)}) {
   assert(Semantics == &semPPCDoubleDouble);
-  // TODO Check for First == &IEEEdouble once the transition is done.
-  assert(&Floats[0].getSemantics() == &semPPCDoubleDoubleImpl ||
-         &Floats[0].getSemantics() == &semIEEEdouble);
+  assert(&Floats[0].getSemantics() == &semIEEEdouble);
   assert(&Floats[1].getSemantics() == &semIEEEdouble);
 }
 
@@ -4033,25 +4011,15 @@
   }
   assert(LHS.getCategory() == fcNormal && RHS.getCategory() == fcNormal);
 
-  // These conversions will go away once PPCDoubleDoubleImpl goes away.
-  // (PPCDoubleDoubleImpl, IEEEDouble) -> (IEEEDouble, IEEEDouble)
-  APFloat A(semIEEEdouble,
-            APInt(64, LHS.Floats[0].bitcastToAPInt().getRawData()[0])),
-      AA(LHS.Floats[1]),
-      C(semIEEEdouble, APInt(64, RHS.Floats[0].bitcastToAPInt().getRawData()[0])),
+  APFloat A(LHS.Floats[0]), AA(LHS.Floats[1]), C(RHS.Floats[0]),
       CC(RHS.Floats[1]);
+  assert(&A.getSemantics() == &semIEEEdouble);
   assert(&AA.getSemantics() == &semIEEEdouble);
+  assert(&C.getSemantics() == &semIEEEdouble);
   assert(&CC.getSemantics() == &semIEEEdouble);
-  Out.Floats[0] = APFloat(semIEEEdouble);
+  assert(&Out.Floats[0].getSemantics() == &semIEEEdouble);
   assert(&Out.Floats[1].getSemantics() == &semIEEEdouble);
-
-  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(semPPCDoubleDoubleImpl, APInt(128, 2, Buffer));
-  return Ret;
+  return Out.addImpl(A, AA, C, CC, RM);
 }
 
 APFloat::opStatus DoubleAPFloat::add(const DoubleAPFloat &RHS,
@@ -4067,6 +4035,64 @@
   return Ret;
 }
 
+APFloat::opStatus DoubleAPFloat::multiply(const DoubleAPFloat &RHS,
+                                          APFloat::roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret =
+      Tmp.multiply(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()), RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus DoubleAPFloat::divide(const DoubleAPFloat &RHS,
+                                        APFloat::roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret =
+      Tmp.divide(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()), RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus DoubleAPFloat::remainder(const DoubleAPFloat &RHS) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret =
+      Tmp.remainder(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus DoubleAPFloat::mod(const DoubleAPFloat &RHS) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret = Tmp.mod(APFloat(semPPCDoubleDoubleLegacy, RHS.bitcastToAPInt()));
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus
+DoubleAPFloat::fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
+                                const DoubleAPFloat &Addend,
+                                APFloat::roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret = Tmp.fusedMultiplyAdd(
+      APFloat(semPPCDoubleDoubleLegacy, Multiplicand.bitcastToAPInt()),
+      APFloat(semPPCDoubleDoubleLegacy, Addend.bitcastToAPInt()), RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus DoubleAPFloat::roundToIntegral(APFloat::roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret = Tmp.roundToIntegral(RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
 void DoubleAPFloat::changeSign() {
   Floats[0].changeSign();
   Floats[1].changeSign();
@@ -4104,11 +4130,198 @@
   Floats[1].makeZero(false);
 }
 
+void DoubleAPFloat::makeZero(bool Neg) {
+  Floats[0].makeZero(Neg);
+  Floats[1].makeZero(false);
+}
+
+void DoubleAPFloat::makeLargest(bool Neg) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x7fefffffffffffffull));
+  Floats[1] = APFloat(semIEEEdouble, APInt(64, 0x7c8ffffffffffffeull));
+  if (Neg)
+    changeSign();
+}
+
+void DoubleAPFloat::makeSmallest(bool Neg) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  Floats[0].makeSmallest(Neg);
+  Floats[1].makeZero(false);
+}
+
+void DoubleAPFloat::makeSmallestNormalized(bool Neg) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  Floats[0] = APFloat(semIEEEdouble, APInt(64, 0x0360000000000000ull));
+  if (Neg)
+    Floats[0].changeSign();
+  Floats[1].makeZero(false);
+}
+
 void DoubleAPFloat::makeNaN(bool SNaN, bool Neg, const APInt *fill) {
   Floats[0].makeNaN(SNaN, Neg, fill);
   Floats[1].makeZero(false);
 }
 
+APFloat::cmpResult DoubleAPFloat::compare(const DoubleAPFloat &RHS) const {
+  auto Result = Floats[0].compare(RHS.Floats[0]);
+  if (Result == APFloat::cmpEqual)
+    return Floats[1].compare(RHS.Floats[1]);
+  return Result;
+}
+
+bool DoubleAPFloat::bitwiseIsEqual(const DoubleAPFloat &RHS) const {
+  return Floats[0].bitwiseIsEqual(RHS.Floats[0]) &&
+         Floats[1].bitwiseIsEqual(RHS.Floats[1]);
+}
+
+hash_code hash_value(const DoubleAPFloat &Arg) {
+  if (Arg.Floats)
+    return hash_combine(hash_value(Arg.Floats[0]), hash_value(Arg.Floats[1]));
+  return hash_combine(Arg.Semantics);
+}
+
+APInt DoubleAPFloat::bitcastToAPInt() const {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  uint64_t Data[] = {
+      Floats[0].bitcastToAPInt().getRawData()[0],
+      Floats[1].bitcastToAPInt().getRawData()[0],
+  };
+  return APInt(128, 2, Data);
+}
+
+APFloat::opStatus DoubleAPFloat::convertFromString(StringRef S,
+                                                   roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy);
+  auto Ret = Tmp.convertFromString(S, RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus DoubleAPFloat::next(bool nextDown) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  auto Ret = Tmp.next(nextDown);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus DoubleAPFloat::convertToInteger(integerPart *Input,
+                                                  unsigned int Width,
+                                                  bool IsSigned,
+                                                  roundingMode RM,
+                                                  bool *IsExact) const {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
+      .convertToInteger(Input, Width, IsSigned, RM, IsExact);
+}
+
+APFloat::opStatus DoubleAPFloat::convertFromAPInt(const APInt &Input,
+                                                  bool IsSigned,
+                                                  roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy);
+  auto Ret = Tmp.convertFromAPInt(Input, IsSigned, RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus
+DoubleAPFloat::convertFromSignExtendedInteger(const integerPart *Input,
+                                              unsigned int InputSize,
+                                              bool IsSigned, roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy);
+  auto Ret = Tmp.convertFromSignExtendedInteger(Input, InputSize, IsSigned, RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+APFloat::opStatus
+DoubleAPFloat::convertFromZeroExtendedInteger(const integerPart *Input,
+                                              unsigned int InputSize,
+                                              bool IsSigned, roundingMode RM) {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy);
+  auto Ret = Tmp.convertFromZeroExtendedInteger(Input, InputSize, IsSigned, RM);
+  *this = DoubleAPFloat(semPPCDoubleDouble, Tmp.bitcastToAPInt());
+  return Ret;
+}
+
+unsigned int DoubleAPFloat::convertToHexString(char *DST,
+                                               unsigned int HexDigits,
+                                               bool UpperCase,
+                                               roundingMode RM) const {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  return APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
+      .convertToHexString(DST, HexDigits, UpperCase, RM);
+}
+
+bool DoubleAPFloat::isDenormal() const {
+  return getCategory() == fcNormal &&
+         (Floats[0].isDenormal() || Floats[1].isDenormal() ||
+          Floats[0].compare(Floats[0] + Floats[1]) != cmpEqual);
+}
+
+bool DoubleAPFloat::isSmallest() const {
+  if (getCategory() != fcNormal)
+    return false;
+  DoubleAPFloat Tmp(*this);
+  Tmp.makeSmallest(this->isNegative());
+  return Tmp.compare(*this) == cmpEqual;
+}
+
+bool DoubleAPFloat::isLargest() const {
+  if (getCategory() != fcNormal)
+    return false;
+  DoubleAPFloat Tmp(*this);
+  Tmp.makeLargest(this->isNegative());
+  return Tmp.compare(*this) == cmpEqual;
+}
+
+bool DoubleAPFloat::isInteger() const {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy);
+  (void)Tmp.add(Floats[0], rmNearestTiesToEven);
+  (void)Tmp.add(Floats[1], rmNearestTiesToEven);
+  return Tmp.isInteger();
+}
+
+void DoubleAPFloat::toString(SmallVectorImpl<char> &Str,
+                             unsigned FormatPrecision,
+                             unsigned FormatMaxPadding) const {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat(semPPCDoubleDoubleLegacy, bitcastToAPInt())
+      .toString(Str, FormatPrecision, FormatMaxPadding);
+}
+
+bool DoubleAPFloat::getExactInverse(APFloat *inv) const {
+  assert(Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat Tmp(semPPCDoubleDoubleLegacy, bitcastToAPInt());
+  if (!inv)
+    return Tmp.getExactInverse(nullptr);
+  APFloat Inv(semPPCDoubleDoubleLegacy);
+  auto Ret = Tmp.getExactInverse(&Inv);
+  *inv = APFloat(semPPCDoubleDouble, Inv.bitcastToAPInt());
+  return Ret;
+}
+
+DoubleAPFloat scalbn(DoubleAPFloat Arg, int Exp, APFloat::roundingMode RM) {
+  assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  return DoubleAPFloat(semPPCDoubleDouble, scalbn(Arg.Floats[0], Exp, RM),
+                       scalbn(Arg.Floats[1], Exp, RM));
+}
+
+DoubleAPFloat frexp(const DoubleAPFloat &Arg, int &Exp,
+                    APFloat::roundingMode RM) {
+  assert(Arg.Semantics == &semPPCDoubleDouble && "Unexpected Semantics");
+  APFloat First = frexp(Arg.Floats[0], Exp, RM);
+  APFloat Second = Arg.Floats[1];
+  if (Arg.getCategory() == APFloat::fcNormal)
+    Second = scalbn(Second, -Exp, RM);
+  return DoubleAPFloat(semPPCDoubleDouble, std::move(First), std::move(Second));
+}
+
 } // End detail namespace
 
 APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
@@ -4126,10 +4339,20 @@
 }
 
 APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
-  return getIEEE().convertFromString(Str, RM);
+  if (usesLayout<IEEEFloat>(getSemantics()))
+    return U.IEEE.convertFromString(Str, RM);
+  if (usesLayout<DoubleAPFloat>(getSemantics()))
+    return U.Double.convertFromString(Str, RM);
+  llvm_unreachable("Unexpected semantics");
 }
 
-hash_code hash_value(const APFloat &Arg) { return hash_value(Arg.getIEEE()); }
+hash_code hash_value(const APFloat &Arg) {
+  if (APFloat::usesLayout<detail::IEEEFloat>(Arg.getSemantics()))
+    return hash_value(Arg.U.IEEE);
+  if (APFloat::usesLayout<detail::DoubleAPFloat>(Arg.getSemantics()))
+    return hash_value(Arg.U.Double);
+  llvm_unreachable("Unexpected semantics");
+}
 
 APFloat::APFloat(const fltSemantics &Semantics, StringRef S)
     : APFloat(Semantics) {
@@ -4146,10 +4369,8 @@
   if (usesLayout<IEEEFloat>(getSemantics()) &&
       usesLayout<DoubleAPFloat>(ToSemantics)) {
     assert(&ToSemantics == &semPPCDoubleDouble);
-    auto Ret = U.IEEE.convert(semPPCDoubleDoubleImpl, RM, losesInfo);
-    *this = APFloat(DoubleAPFloat(semPPCDoubleDouble, std::move(*this),
-                                  APFloat(semIEEEdouble)),
-                    ToSemantics);
+    auto Ret = U.IEEE.convert(semPPCDoubleDoubleLegacy, RM, losesInfo);
+    *this = APFloat(ToSemantics, U.IEEE.bitcastToAPInt());
     return Ret;
   }
   if (usesLayout<DoubleAPFloat>(getSemantics()) &&
@@ -4191,4 +4412,24 @@
 
 void APFloat::dump() const { print(dbgs()); }
 
+void APFloat::Profile(FoldingSetNodeID &NID) const {
+  NID.Add(bitcastToAPInt());
+}
+
+/* Same as convertToInteger(integerPart*, ...), except the result is returned in
+   an APSInt, whose initial bit-width and signed-ness are used to determine the
+   precision of the conversion.
+ */
+APFloat::opStatus APFloat::convertToInteger(APSInt &result,
+                                            roundingMode rounding_mode,
+                                            bool *isExact) const {
+  unsigned bitWidth = result.getBitWidth();
+  SmallVector<uint64_t, 4> parts(result.getNumWords());
+  opStatus status = convertToInteger(parts.data(), bitWidth, result.isSigned(),
+                                     rounding_mode, isExact);
+  // Keeps the original signed-ness.
+  result = APInt(bitWidth, parts);
+  return status;
+}
+
 } // End llvm namespace
Index: llvm/include/llvm/ADT/APFloat.h
===================================================================
--- llvm/include/llvm/ADT/APFloat.h
+++ llvm/include/llvm/ADT/APFloat.h
@@ -235,10 +235,6 @@
 
   /// @}
 
-  /// Used to insert APFloat objects, or objects that contain APFloat objects,
-  /// into FoldingSets.
-  void Profile(FoldingSetNodeID &NID) const;
-
   /// \name Arithmetic
   /// @{
 
@@ -255,53 +251,12 @@
   /// IEEE-754R 5.3.1: nextUp/nextDown.
   opStatus next(bool nextDown);
 
-  /// \brief Operator+ overload which provides the default
-  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
-  IEEEFloat operator+(const IEEEFloat &RHS) const {
-    IEEEFloat Result = *this;
-    Result.add(RHS, rmNearestTiesToEven);
-    return Result;
-  }
-
-  /// \brief Operator- overload which provides the default
-  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
-  IEEEFloat operator-(const IEEEFloat &RHS) const {
-    IEEEFloat Result = *this;
-    Result.subtract(RHS, rmNearestTiesToEven);
-    return Result;
-  }
-
-  /// \brief Operator* overload which provides the default
-  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
-  IEEEFloat operator*(const IEEEFloat &RHS) const {
-    IEEEFloat Result = *this;
-    Result.multiply(RHS, rmNearestTiesToEven);
-    return Result;
-  }
-
-  /// \brief Operator/ overload which provides the default
-  /// \c nmNearestTiesToEven rounding mode and *no* error checking.
-  IEEEFloat operator/(const IEEEFloat &RHS) const {
-    IEEEFloat Result = *this;
-    Result.divide(RHS, rmNearestTiesToEven);
-    return Result;
-  }
-
   /// @}
 
   /// \name Sign operations.
   /// @{
 
   void changeSign();
-  void clearSign();
-  void copySign(const IEEEFloat &);
-
-  /// \brief A static helper to produce a copy of an APFloat value with its sign
-  /// copied from some other APFloat.
-  static IEEEFloat copySign(IEEEFloat Value, const IEEEFloat &Sign) {
-    Value.copySign(Sign);
-    return Value;
-  }
 
   /// @}
 
@@ -311,7 +266,6 @@
   opStatus convert(const fltSemantics &, roundingMode, bool *);
   opStatus convertToInteger(integerPart *, unsigned int, bool, roundingMode,
                             bool *) const;
-  opStatus convertToInteger(APSInt &, roundingMode, bool *) const;
   opStatus convertFromAPInt(const APInt &, bool, roundingMode);
   opStatus convertFromSignExtendedInteger(const integerPart *, unsigned int,
                                           bool, roundingMode);
@@ -443,7 +397,7 @@
 
   /// If this value has an exact multiplicative inverse, store it in inv and
   /// return true.
-  bool getExactInverse(IEEEFloat *inv) const;
+  bool getExactInverse(APFloat *inv) const;
 
   /// \brief Returns the exponent of the internal representation of the APFloat.
   ///
@@ -636,16 +590,63 @@
 
   opStatus add(const DoubleAPFloat &RHS, roundingMode RM);
   opStatus subtract(const DoubleAPFloat &RHS, roundingMode RM);
+  opStatus multiply(const DoubleAPFloat &RHS, roundingMode RM);
+  opStatus divide(const DoubleAPFloat &RHS, roundingMode RM);
+  opStatus remainder(const DoubleAPFloat &RHS);
+  opStatus mod(const DoubleAPFloat &RHS);
+  opStatus fusedMultiplyAdd(const DoubleAPFloat &Multiplicand,
+                            const DoubleAPFloat &Addend, roundingMode RM);
+  opStatus roundToIntegral(roundingMode RM);
   void changeSign();
   cmpResult compareAbsoluteValue(const DoubleAPFloat &RHS) const;
 
   fltCategory getCategory() const;
   bool isNegative() const;
 
   void makeInf(bool Neg);
+  void makeZero(bool Neg);
+  void makeLargest(bool Neg);
+  void makeSmallest(bool Neg);
+  void makeSmallestNormalized(bool Neg);
   void makeNaN(bool SNaN, bool Neg, const APInt *fill);
+
+  cmpResult compare(const DoubleAPFloat &RHS) const;
+  bool bitwiseIsEqual(const DoubleAPFloat &RHS) const;
+  APInt bitcastToAPInt() const;
+  opStatus convertFromString(StringRef, roundingMode);
+  opStatus next(bool nextDown);
+
+  opStatus convertToInteger(integerPart *Input, unsigned int Width,
+                            bool IsSigned, roundingMode RM,
+                            bool *IsExact) const;
+  opStatus convertFromAPInt(const APInt &Input, bool IsSigned, roundingMode RM);
+  opStatus convertFromSignExtendedInteger(const integerPart *Input,
+                                          unsigned int InputSize, bool IsSigned,
+                                          roundingMode RM);
+  opStatus convertFromZeroExtendedInteger(const integerPart *Input,
+                                          unsigned int InputSize, bool IsSigned,
+                                          roundingMode RM);
+  unsigned int convertToHexString(char *DST, unsigned int HexDigits,
+                                  bool UpperCase, roundingMode RM) const;
+
+  bool isDenormal() const;
+  bool isSmallest() const;
+  bool isLargest() const;
+  bool isInteger() const;
+
+  void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision,
+                unsigned FormatMaxPadding) const;
+
+  bool getExactInverse(APFloat *inv) const;
+
+  friend int ilogb(const DoubleAPFloat &Arg);
+  friend DoubleAPFloat scalbn(DoubleAPFloat X, int Exp, roundingMode);
+  friend DoubleAPFloat frexp(const DoubleAPFloat &X, int &Exp, roundingMode);
+  friend hash_code hash_value(const DoubleAPFloat &Arg);
 };
 
+hash_code hash_value(const DoubleAPFloat &Arg);
+
 } // End detail namespace
 
 // This is a interface class that is currently forwarding functionalities from
@@ -770,26 +771,76 @@
     llvm_unreachable("Unexpected semantics");
   }
 
-  void makeZero(bool Neg) { getIEEE().makeZero(Neg); }
+  void makeZero(bool Neg) {
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.makeZero(Neg);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      U.Double.makeZero(Neg);
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
+  }
 
   void makeInf(bool Neg) {
-    if (usesLayout<IEEEFloat>(*U.semantics))
-      return U.IEEE.makeInf(Neg);
-    if (usesLayout<DoubleAPFloat>(*U.semantics))
-      return U.Double.makeInf(Neg);
+    if (usesLayout<IEEEFloat>(*U.semantics)) {
+      U.IEEE.makeInf(Neg);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(*U.semantics)) {
+      U.Double.makeInf(Neg);
+      return;
+    }
     llvm_unreachable("Unexpected semantics");
   }
 
   void makeNaN(bool SNaN, bool Neg, const APInt *fill) {
-    getIEEE().makeNaN(SNaN, Neg, fill);
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.makeNaN(SNaN, Neg, fill);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      return U.Double.makeNaN(SNaN, Neg, fill);
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
   }
 
-  void makeLargest(bool Neg) { getIEEE().makeLargest(Neg); }
+  void makeLargest(bool Neg) {
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.makeLargest(Neg);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      U.Double.makeLargest(Neg);
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
+  }
 
-  void makeSmallest(bool Neg) { getIEEE().makeSmallest(Neg); }
+  void makeSmallest(bool Neg) {
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.makeSmallest(Neg);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      U.Double.makeSmallest(Neg);
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
+  }
 
   void makeSmallestNormalized(bool Neg) {
-    getIEEE().makeSmallestNormalized(Neg);
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.makeSmallestNormalized(Neg);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      U.Double.makeSmallestNormalized(Neg);
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
   }
 
   // FIXME: This is due to clang 3.3 (or older version) always checks for the
@@ -921,7 +972,9 @@
   /// \param isIEEE   - If 128 bit number, select between PPC and IEEE
   static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
 
-  void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
+  /// Used to insert APFloat objects, or objects that contain APFloat objects,
+  /// into FoldingSets.
+  void Profile(FoldingSetNodeID &NID) const;
 
   opStatus add(const APFloat &RHS, roundingMode RM) {
     assert(&getSemantics() == &RHS.getSemantics() &&
@@ -942,103 +995,226 @@
     llvm_unreachable("Unexpected semantics");
   }
   opStatus multiply(const APFloat &RHS, roundingMode RM) {
-    return getIEEE().multiply(RHS.getIEEE(), RM);
+    assert(&getSemantics() == &RHS.getSemantics() &&
+           "Should only call on two APFloats with the same semantics");
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.multiply(RHS.U.IEEE, RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.multiply(RHS.U.Double, RM);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus divide(const APFloat &RHS, roundingMode RM) {
-    return getIEEE().divide(RHS.getIEEE(), RM);
+    assert(&getSemantics() == &RHS.getSemantics() &&
+           "Should only call on two APFloats with the same semantics");
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.divide(RHS.U.IEEE, RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.divide(RHS.U.Double, RM);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus remainder(const APFloat &RHS) {
-    return getIEEE().remainder(RHS.getIEEE());
+    assert(&getSemantics() == &RHS.getSemantics() &&
+           "Should only call on two APFloats with the same semantics");
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.remainder(RHS.U.IEEE);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.remainder(RHS.U.Double);
+    llvm_unreachable("Unexpected semantics");
+  }
+  opStatus mod(const APFloat &RHS) {
+    assert(&getSemantics() == &RHS.getSemantics() &&
+           "Should only call on two APFloats with the same semantics");
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.mod(RHS.U.IEEE);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.mod(RHS.U.Double);
+    llvm_unreachable("Unexpected semantics");
   }
-  opStatus mod(const APFloat &RHS) { return getIEEE().mod(RHS.getIEEE()); }
   opStatus fusedMultiplyAdd(const APFloat &Multiplicand, const APFloat &Addend,
                             roundingMode RM) {
-    return getIEEE().fusedMultiplyAdd(Multiplicand.getIEEE(), Addend.getIEEE(),
-                                      RM);
+    assert(&getSemantics() == &Multiplicand.getSemantics() &&
+           "Should only call on APFloats with the same semantics");
+    assert(&getSemantics() == &Addend.getSemantics() &&
+           "Should only call on APFloats with the same semantics");
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.fusedMultiplyAdd(Multiplicand.U.IEEE, Addend.U.IEEE, RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.fusedMultiplyAdd(Multiplicand.U.Double, Addend.U.Double,
+                                       RM);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus roundToIntegral(roundingMode RM) {
-    return getIEEE().roundToIntegral(RM);
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.roundToIntegral(RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.roundToIntegral(RM);
+    llvm_unreachable("Unexpected semantics");
   }
-  opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
 
+  opStatus next(bool nextDown) {
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.next(nextDown);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.next(nextDown);
+    llvm_unreachable("Unexpected semantics");
+  }
+
+  /// \brief Operator+ overload which provides the default
+  /// \c rmNearestTiesToEven rounding mode and *no* error checking.
   APFloat operator+(const APFloat &RHS) const {
-    return APFloat(getIEEE() + RHS.getIEEE(), getSemantics());
+    APFloat Result(*this);
+    (void)Result.add(RHS, rmNearestTiesToEven);
+    return Result;
   }
 
+  /// \brief Operator- overload which provides the default
+  /// \c rmNearestTiesToEven rounding mode and *no* error checking.
   APFloat operator-(const APFloat &RHS) const {
-    return APFloat(getIEEE() - RHS.getIEEE(), getSemantics());
+    APFloat Result(*this);
+    (void)Result.subtract(RHS, rmNearestTiesToEven);
+    return Result;
   }
 
+  /// \brief Operator* overload which provides the default
+  /// \c rmNearestTiesToEven rounding mode and *no* error checking.
   APFloat operator*(const APFloat &RHS) const {
-    return APFloat(getIEEE() * RHS.getIEEE(), getSemantics());
+    APFloat Result(*this);
+    (void)Result.multiply(RHS, rmNearestTiesToEven);
+    return Result;
   }
 
+  /// \brief Operator/ overload which provides the default
+  /// \c rmNearestTiesToEven rounding mode and *no* error checking.
   APFloat operator/(const APFloat &RHS) const {
-    return APFloat(getIEEE() / RHS.getIEEE(), getSemantics());
+    APFloat Result(*this);
+    (void)Result.divide(RHS, rmNearestTiesToEven);
+    return Result;
   }
 
-  void changeSign() { getIEEE().changeSign(); }
-  void clearSign() { getIEEE().clearSign(); }
-  void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
+  void changeSign() {
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.changeSign();
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      U.Double.changeSign();
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
+  }
+  void clearSign() {
+    if (isNegative())
+      changeSign();
+  }
+  void copySign(const APFloat &RHS) {
+    if (isNegative() != RHS.isNegative())
+      changeSign();
+  }
 
+  /// \brief A static helper to produce a copy of an APFloat value with its sign
+  /// copied from some other APFloat.
   static APFloat copySign(APFloat Value, const APFloat &Sign) {
-    return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()),
-                   Value.getSemantics());
+    Value.copySign(Sign);
+    return Value;
   }
 
   opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
                    bool *losesInfo);
   opStatus convertToInteger(integerPart *Input, unsigned int Width,
                             bool IsSigned, roundingMode RM,
                             bool *IsExact) const {
-    return getIEEE().convertToInteger(Input, Width, IsSigned, RM, IsExact);
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.convertToInteger(Input, Width, IsSigned, RM, IsExact);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.convertToInteger(Input, Width, IsSigned, RM, IsExact);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus convertToInteger(APSInt &Result, roundingMode RM,
-                            bool *IsExact) const {
-    return getIEEE().convertToInteger(Result, RM, IsExact);
-  }
+                            bool *IsExact) const;
   opStatus convertFromAPInt(const APInt &Input, bool IsSigned,
                             roundingMode RM) {
-    return getIEEE().convertFromAPInt(Input, IsSigned, RM);
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.convertFromAPInt(Input, IsSigned, RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.convertFromAPInt(Input, IsSigned, RM);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus convertFromSignExtendedInteger(const integerPart *Input,
                                           unsigned int InputSize, bool IsSigned,
                                           roundingMode RM) {
-    return getIEEE().convertFromSignExtendedInteger(Input, InputSize, IsSigned,
-                                                    RM);
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.convertFromSignExtendedInteger(Input, InputSize, IsSigned,
+                                                   RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.convertFromSignExtendedInteger(Input, InputSize, IsSigned,
+                                                     RM);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus convertFromZeroExtendedInteger(const integerPart *Input,
                                           unsigned int InputSize, bool IsSigned,
                                           roundingMode RM) {
-    return getIEEE().convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
-                                                    RM);
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
+                                                   RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.convertFromZeroExtendedInteger(Input, InputSize, IsSigned,
+                                                     RM);
+    llvm_unreachable("Unexpected semantics");
   }
   opStatus convertFromString(StringRef, roundingMode);
-  APInt bitcastToAPInt() const { return getIEEE().bitcastToAPInt(); }
+  APInt bitcastToAPInt() const {
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.bitcastToAPInt();
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.bitcastToAPInt();
+    llvm_unreachable("Unexpected semantics");
+  }
   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 getIEEE().compare(RHS.getIEEE());
+    assert(&getSemantics() == &RHS.getSemantics() &&
+           "Should only compare APFloats with the same semantics");
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.compare(RHS.U.IEEE);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.compare(RHS.U.Double);
+    llvm_unreachable("Unexpected semantics");
   }
 
   bool bitwiseIsEqual(const APFloat &RHS) const {
-    return getIEEE().bitwiseIsEqual(RHS.getIEEE());
+    if (&getSemantics() != &RHS.getSemantics())
+      return false;
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.bitwiseIsEqual(RHS.U.IEEE);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.bitwiseIsEqual(RHS.U.Double);
+    llvm_unreachable("Unexpected semantics");
   }
 
   unsigned int convertToHexString(char *DST, unsigned int HexDigits,
                                   bool UpperCase, roundingMode RM) const {
-    return getIEEE().convertToHexString(DST, HexDigits, UpperCase, RM);
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.convertToHexString(DST, HexDigits, UpperCase, RM);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.convertToHexString(DST, HexDigits, UpperCase, RM);
+    llvm_unreachable("Unexpected semantics");
   }
 
   bool isZero() const { return getCategory() == fcZero; }
   bool isInfinity() const { return getCategory() == fcInfinity; }
   bool isNaN() const { return getCategory() == fcNaN; }
 
   bool isNegative() const { return getIEEE().isNegative(); }
-  bool isDenormal() const { return getIEEE().isDenormal(); }
+  bool isDenormal() const {
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.isDenormal();
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.isDenormal();
+    llvm_unreachable("Unexpected semantics");
+  }
   bool isSignaling() const { return getIEEE().isSignaling(); }
 
   bool isNormal() const { return !isDenormal() && isFiniteNonZero(); }
@@ -1050,30 +1226,53 @@
   bool isFiniteNonZero() const { return isFinite() && !isZero(); }
   bool isPosZero() const { return isZero() && !isNegative(); }
   bool isNegZero() const { return isZero() && isNegative(); }
-  bool isSmallest() const { return getIEEE().isSmallest(); }
-  bool isLargest() const { return getIEEE().isLargest(); }
-  bool isInteger() const { return getIEEE().isInteger(); }
+  bool isSmallest() const {
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.isSmallest();
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.isSmallest();
+    llvm_unreachable("Unexpected semantics");
+  }
+  bool isLargest() const {
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.isLargest();
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.isLargest();
+    llvm_unreachable("Unexpected semantics");
+  }
+  bool isInteger() const {
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.isInteger();
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.isInteger();
+    llvm_unreachable("Unexpected semantics");
+  }
 
   APFloat &operator=(const APFloat &RHS) = default;
   APFloat &operator=(APFloat &&RHS) = default;
 
   void toString(SmallVectorImpl<char> &Str, unsigned FormatPrecision = 0,
                 unsigned FormatMaxPadding = 3) const {
-    return getIEEE().toString(Str, FormatPrecision, FormatMaxPadding);
+    if (usesLayout<IEEEFloat>(getSemantics())) {
+      U.IEEE.toString(Str, FormatPrecision, FormatMaxPadding);
+      return;
+    }
+    if (usesLayout<DoubleAPFloat>(getSemantics())) {
+      U.Double.toString(Str, FormatPrecision, FormatMaxPadding);
+      return;
+    }
+    llvm_unreachable("Unexpected semantics");
   }
 
   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();
+    if (usesLayout<IEEEFloat>(getSemantics()))
+      return U.IEEE.getExactInverse(inv);
+    if (usesLayout<DoubleAPFloat>(getSemantics()))
+      return U.Double.getExactInverse(inv);
+    llvm_unreachable("Unexpected semantics");
   }
 
   friend hash_code hash_value(const APFloat &Arg);
@@ -1090,15 +1289,23 @@
 /// xlC compiler.
 hash_code hash_value(const APFloat &Arg);
 inline APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM) {
-  return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics());
+  if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
+    return APFloat(scalbn(X.U.IEEE, Exp, RM), X.getSemantics());
+  if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
+    return APFloat(scalbn(X.U.Double, Exp, RM), X.getSemantics());
+  llvm_unreachable("Unexpected semantics");
 }
 
 /// \brief Equivalent of C standard library function.
 ///
 /// While the C standard says Exp is an unspecified value for infinity and nan,
 /// this returns INT_MAX for infinities, and INT_MIN for NaNs.
 inline APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM) {
-  return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics());
+  if (APFloat::usesLayout<detail::IEEEFloat>(X.getSemantics()))
+    return APFloat(frexp(X.U.IEEE, Exp, RM), X.getSemantics());
+  if (APFloat::usesLayout<detail::DoubleAPFloat>(X.getSemantics()))
+    return APFloat(frexp(X.U.Double, Exp, RM), X.getSemantics());
+  llvm_unreachable("Unexpected semantics");
 }
 /// \brief Returns the absolute value of the argument.
 inline APFloat abs(APFloat X) {
Index: clang/test/CodeGen/ppc64-complex-parms.c
===================================================================
--- clang/test/CodeGen/ppc64-complex-parms.c
+++ clang/test/CodeGen/ppc64-complex-parms.c
@@ -93,7 +93,7 @@
 // CHECK: %[[VAR22:[A-Za-z0-9.]+]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 0
 // CHECK: %[[VAR23:[A-Za-z0-9.]+]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 1
 // CHECK: store ppc_fp128 0xM40000000000000000000000000000000, ppc_fp128* %[[VAR22]]
-// CHECK: store ppc_fp128 0xMC0040000000000000000000000000000, ppc_fp128* %[[VAR23]]
+// CHECK: store ppc_fp128 0xMC0040000000000008000000000000000, ppc_fp128* %[[VAR23]]
 // CHECK: %[[VAR24:[A-Za-z0-9.]+]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 0
 // CHECK: %[[VAR25:[A-Za-z0-9.]+]] = load ppc_fp128, ppc_fp128* %[[VAR24]], align 16
 // CHECK: %[[VAR26:[A-Za-z0-9.]+]] = getelementptr inbounds { ppc_fp128, ppc_fp128 }, { ppc_fp128, ppc_fp128 }* %[[VAR21]], i32 0, i32 1
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to