[llvm] r286060 - [APFloat] Make functions that produce APFloaat objects use correct semantics.

Tim Shen via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 6 00:38:38 PDT 2016


Author: timshen
Date: Sun Nov  6 01:38:37 2016
New Revision: 286060

URL: http://llvm.org/viewvc/llvm-project?rev=286060&view=rev
Log:
[APFloat] Make functions that produce APFloaat objects use correct semantics.

Summary:
Fixes PR30869.

In D25977 I meant to change all functions that care about lifetime. I
changed constructors, factory functions, but I missed member/free
functions that return new instances. This patch changes them.

Reviewers: hfinkel, kbarton, echristo, joerg

Subscribers: llvm-commits, mehdi_amini

Differential Revision: https://reviews.llvm.org/D26269

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=286060&r1=286059&r2=286060&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/APFloat.h (original)
+++ llvm/trunk/include/llvm/ADT/APFloat.h Sun Nov  6 01:38:37 2016
@@ -232,11 +232,6 @@ public:
   /// \name Convenience "constructors"
   /// @{
 
-  /// Returns a float which is bitcasted from an all one value int.
-  ///
-  /// \param BitWidth - Select float type
-  static IEEEFloat getAllOnesValue(unsigned BitWidth);
-
   /// @}
 
   /// Used to insert APFloat objects, or objects that contain APFloat objects,
@@ -645,8 +640,11 @@ class APFloat : public APFloatBase {
     IEEEFloat IEEE;
     DoubleAPFloat Double;
 
-    explicit Storage(IEEEFloat F) : IEEE(std::move(F)) {}
-    explicit Storage(DoubleAPFloat F) : Double(std::move(F)) {}
+    explicit Storage(IEEEFloat F, const fltSemantics &S);
+    explicit Storage(DoubleAPFloat F, const fltSemantics &S)
+        : Double(std::move(F)) {
+      assert(&S == &PPCDoubleDouble);
+    }
 
     template <typename... ArgTypes>
     Storage(const fltSemantics &Semantics, ArgTypes &&... Args) {
@@ -770,8 +768,9 @@ class APFloat : public APFloatBase {
     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)) {}
+  explicit APFloat(IEEEFloat F, const fltSemantics &S) : U(std::move(F), S) {}
+  explicit APFloat(DoubleAPFloat F, const fltSemantics &S)
+      : U(std::move(F), S) {}
 
 public:
   APFloat(const fltSemantics &Semantics) : U(Semantics) {}
@@ -781,8 +780,8 @@ public:
   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)) {}
+  explicit APFloat(double d) : U(IEEEFloat(d), IEEEdouble) {}
+  explicit APFloat(float f) : U(IEEEFloat(f), IEEEsingle) {}
   APFloat(const APFloat &RHS) = default;
   APFloat(APFloat &&RHS) = default;
 
@@ -881,14 +880,7 @@ public:
   ///
   /// \param BitWidth - Select float type
   /// \param isIEEE   - If 128 bit number, select between PPC and IEEE
-  static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false) {
-    if (isIEEE) {
-      return APFloat(IEEEFloat::getAllOnesValue(BitWidth));
-    } else {
-      assert(BitWidth == 128);
-      return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
-    }
-  }
+  static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
 
   void Profile(FoldingSetNodeID &NID) const { getIEEE().Profile(NID); }
 
@@ -919,19 +911,19 @@ public:
   opStatus next(bool nextDown) { return getIEEE().next(nextDown); }
 
   APFloat operator+(const APFloat &RHS) const {
-    return APFloat(getIEEE() + RHS.getIEEE());
+    return APFloat(getIEEE() + RHS.getIEEE(), getSemantics());
   }
 
   APFloat operator-(const APFloat &RHS) const {
-    return APFloat(getIEEE() - RHS.getIEEE());
+    return APFloat(getIEEE() - RHS.getIEEE(), getSemantics());
   }
 
   APFloat operator*(const APFloat &RHS) const {
-    return APFloat(getIEEE() * RHS.getIEEE());
+    return APFloat(getIEEE() * RHS.getIEEE(), getSemantics());
   }
 
   APFloat operator/(const APFloat &RHS) const {
-    return APFloat(getIEEE() / RHS.getIEEE());
+    return APFloat(getIEEE() / RHS.getIEEE(), getSemantics());
   }
 
   void changeSign() { getIEEE().changeSign(); }
@@ -939,7 +931,8 @@ public:
   void copySign(const APFloat &RHS) { getIEEE().copySign(RHS.getIEEE()); }
 
   static APFloat copySign(APFloat Value, const APFloat &Sign) {
-    return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()));
+    return APFloat(IEEEFloat::copySign(Value.getIEEE(), Sign.getIEEE()),
+                   Value.getSemantics());
   }
 
   opStatus convert(const fltSemantics &ToSemantics, roundingMode RM,
@@ -1035,7 +1028,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.getIEEE(), Exp, RM));
+  return APFloat(scalbn(X.getIEEE(), Exp, RM), X.getSemantics());
 }
 
 /// \brief Equivalent of C standard library function.
@@ -1043,7 +1036,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.getIEEE(), Exp, RM));
+  return APFloat(frexp(X.getIEEE(), Exp, RM), X.getSemantics());
 }
 /// \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=286060&r1=286059&r2=286060&view=diff
==============================================================================
--- llvm/trunk/lib/Support/APFloat.cpp (original)
+++ llvm/trunk/lib/Support/APFloat.cpp Sun Nov  6 01:38:37 2016
@@ -3238,23 +3238,6 @@ void IEEEFloat::initFromAPInt(const fltS
   llvm_unreachable(nullptr);
 }
 
-IEEEFloat IEEEFloat::getAllOnesValue(unsigned BitWidth) {
-  switch (BitWidth) {
-  case 16:
-    return IEEEFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
-  case 32:
-    return IEEEFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth));
-  case 64:
-    return IEEEFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth));
-  case 80:
-    return IEEEFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
-  case 128:
-    return IEEEFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
-  default:
-    llvm_unreachable("Unknown floating bit width");
-  }
-}
-
 /// Make this number the largest magnitude normal number in the given
 /// semantics.
 void IEEEFloat::makeLargest(bool Negative) {
@@ -3902,6 +3885,18 @@ DoubleAPFloat &DoubleAPFloat::operator=(
 
 } // End detail namespace
 
+APFloat::Storage::Storage(IEEEFloat F, const fltSemantics &Semantics) {
+  if (usesLayout<IEEEFloat>(Semantics)) {
+    new (&IEEE) IEEEFloat(std::move(F));
+  } else if (usesLayout<DoubleAPFloat>(Semantics)) {
+    new (&Double)
+        DoubleAPFloat(Semantics, APFloat(std::move(F), F.getSemantics()),
+                      APFloat(IEEEdouble));
+  } else {
+    llvm_unreachable("Unexpected semantics");
+  }
+}
+
 APFloat::opStatus APFloat::convertFromString(StringRef Str, roundingMode RM) {
   return getIEEE().convertFromString(Str, RM);
 }
@@ -3925,16 +3920,39 @@ APFloat::opStatus APFloat::convert(const
     assert(&ToSemantics == &PPCDoubleDouble);
     auto Ret = U.IEEE.convert(PPCDoubleDoubleImpl, RM, losesInfo);
     *this = APFloat(
-        DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)));
+        DoubleAPFloat(PPCDoubleDouble, std::move(*this), APFloat(IEEEdouble)),
+        ToSemantics);
     return Ret;
   } else if (usesLayout<DoubleAPFloat>(getSemantics()) &&
              usesLayout<IEEEFloat>(ToSemantics)) {
     auto Ret = getIEEE().convert(ToSemantics, RM, losesInfo);
-    *this = APFloat(std::move(getIEEE()));
+    *this = APFloat(std::move(getIEEE()), ToSemantics);
     return Ret;
   } else {
     llvm_unreachable("Unexpected semantics");
   }
 }
 
+APFloat APFloat::getAllOnesValue(unsigned BitWidth, bool isIEEE) {
+  if (isIEEE) {
+    switch (BitWidth) {
+    case 16:
+      return APFloat(IEEEhalf, APInt::getAllOnesValue(BitWidth));
+    case 32:
+      return APFloat(IEEEsingle, APInt::getAllOnesValue(BitWidth));
+    case 64:
+      return APFloat(IEEEdouble, APInt::getAllOnesValue(BitWidth));
+    case 80:
+      return APFloat(x87DoubleExtended, APInt::getAllOnesValue(BitWidth));
+    case 128:
+      return APFloat(IEEEquad, APInt::getAllOnesValue(BitWidth));
+    default:
+      llvm_unreachable("Unknown floating bit width");
+    }
+  } else {
+    assert(BitWidth == 128);
+    return APFloat(PPCDoubleDouble, APInt::getAllOnesValue(BitWidth));
+  }
+}
+
 } // End llvm namespace

Modified: llvm/trunk/unittests/ADT/APFloatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/APFloatTest.cpp?rev=286060&r1=286059&r2=286060&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/APFloatTest.cpp (original)
+++ llvm/trunk/unittests/ADT/APFloatTest.cpp Sun Nov  6 01:38:37 2016
@@ -1527,6 +1527,34 @@ TEST(APFloatTest, PPCDoubleDouble) {
   // 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") +
+                  APFloat(APFloat::PPCDoubleDouble, "1.0");
+    EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
+
+    Result = APFloat(APFloat::PPCDoubleDouble, "1.0") -
+             APFloat(APFloat::PPCDoubleDouble, "1.0");
+    EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
+
+    Result = APFloat(APFloat::PPCDoubleDouble, "1.0") *
+             APFloat(APFloat::PPCDoubleDouble, "1.0");
+    EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
+
+    Result = APFloat(APFloat::PPCDoubleDouble, "1.0") /
+             APFloat(APFloat::PPCDoubleDouble, "1.0");
+    EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
+
+    int Exp;
+    Result = frexp(APFloat(APFloat::PPCDoubleDouble, "1.0"), Exp,
+                   APFloat::rmNearestTiesToEven);
+    EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
+
+    Result = scalbn(APFloat(APFloat::PPCDoubleDouble, "1.0"), 1,
+                    APFloat::rmNearestTiesToEven);
+    EXPECT_EQ(&APFloat::PPCDoubleDouble, &Result.getSemantics());
+  }
 }
 
 TEST(APFloatTest, isNegative) {




More information about the llvm-commits mailing list