[llvm] c162f08 - [APFloat] convertToDouble/Float can work on shorter types

Serge Pavlov via llvm-commits llvm-commits at lists.llvm.org
Thu May 20 21:39:32 PDT 2021


Author: Serge Pavlov
Date: 2021-05-21T11:02:51+07:00
New Revision: c162f086ba632ffaedfe92d63bf21571bc8ae4da

URL: https://github.com/llvm/llvm-project/commit/c162f086ba632ffaedfe92d63bf21571bc8ae4da
DIFF: https://github.com/llvm/llvm-project/commit/c162f086ba632ffaedfe92d63bf21571bc8ae4da.diff

LOG: [APFloat] convertToDouble/Float can work on shorter types

Previously APFloat::convertToDouble may be called only for APFloats that
were built using double semantics. Other semantics like single precision
were not allowed although corresponding numbers could be converted to
double without loss of precision. The similar restriction applied to
APFloat::convertToFloat.

With this change any APFloat that can be precisely represented by double
can be handled with convertToDouble. Behavior of convertToFloat was
updated similarly. It make the conversion operations more convenient and
adds support for formats like half and bfloat.

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

Added: 
    

Modified: 
    llvm/include/llvm/ADT/APFloat.h
    llvm/lib/Analysis/ConstantFolding.cpp
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/Core.cpp
    llvm/lib/Support/APFloat.cpp
    llvm/unittests/ADT/APFloatTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index 331dcd699c01..f493a03b4b87 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1132,8 +1132,20 @@ class APFloat : public APFloatBase {
   APInt bitcastToAPInt() const {
     APFLOAT_DISPATCH_ON_SEMANTICS(bitcastToAPInt());
   }
-  double convertToDouble() const { return getIEEE().convertToDouble(); }
-  float convertToFloat() const { return getIEEE().convertToFloat(); }
+
+  /// Converts this APFloat to host double value.
+  ///
+  /// \pre The APFloat must be built using semantics, that can be represented by
+  /// the host double type without loss of precision. It can be IEEEdouble and
+  /// shorter semantics, like IEEEsingle and others.
+  double convertToDouble() const;
+
+  /// Converts this APFloat to host float value.
+  ///
+  /// \pre The APFloat must be built using semantics, that can be represented by
+  /// the host float type without loss of precision. It can be IEEEsingle and
+  /// shorter semantics, like IEEEhalf.
+  float convertToFloat() const;
 
   bool operator==(const APFloat &RHS) const { return compare(RHS) == cmpEqual; }
 

diff  --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index d09e4b8d2084..62dbf9fc57a9 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -1794,10 +1794,7 @@ Constant *ConstantFoldSSEConvertToInt(const APFloat &Val, bool roundTowardZero,
 double getValueAsDouble(ConstantFP *Op) {
   Type *Ty = Op->getType();
 
-  if (Ty->isFloatTy())
-    return Op->getValueAPF().convertToFloat();
-
-  if (Ty->isDoubleTy())
+  if (Ty->isBFloatTy() || Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy())
     return Op->getValueAPF().convertToDouble();
 
   bool unused;

diff  --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 6bb858d8b4ad..27f6c1799447 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -953,9 +953,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
     switch (Op.getType()) {
     case MachineOperand::MO_FPImmediate: {
       APFloat APF = APFloat(Op.getFPImm()->getValueAPF());
-      if (Op.getFPImm()->getType()->isFloatTy()) {
-        OS << (double)APF.convertToFloat();
-      } else if (Op.getFPImm()->getType()->isDoubleTy()) {
+      Type *ImmTy = Op.getFPImm()->getType();
+      if (ImmTy->isBFloatTy() || ImmTy->isHalfTy() || ImmTy->isFloatTy() ||
+          ImmTy->isDoubleTy()) {
         OS << APF.convertToDouble();
       } else {
         // There is no good way to print long double.  Convert a copy to

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 9e2a462334bb..2abf17f5da3c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1368,7 +1368,7 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
       bool isInf = APF.isInfinity();
       bool isNaN = APF.isNaN();
       if (!isInf && !isNaN) {
-        double Val = isDouble ? APF.convertToDouble() : APF.convertToFloat();
+        double Val = APF.convertToDouble();
         SmallString<128> StrVal;
         APF.toString(StrVal, 6, 0, false);
         // Check to make sure that the stringized number is not some string like

diff  --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index e46bef165948..084cb8c71d16 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -1399,12 +1399,8 @@ double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *LosesInfo) {
   ConstantFP *cFP = unwrap<ConstantFP>(ConstantVal) ;
   Type *Ty = cFP->getType();
 
-  if (Ty->isFloatTy()) {
-    *LosesInfo = false;
-    return cFP->getValueAPF().convertToFloat();
-  }
-
-  if (Ty->isDoubleTy()) {
+  if (Ty->isHalfTy() || Ty->isBFloatTy() || Ty->isFloatTy() ||
+      Ty->isDoubleTy()) {
     *LosesInfo = false;
     return cFP->getValueAPF().convertToDouble();
   }

diff  --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 1069d1fb4603..7abca8391f70 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -66,6 +66,13 @@ namespace llvm {
 
     /* Number of bits actually used in the semantics. */
     unsigned int sizeInBits;
+
+    // Returns true if any number described by this semantics can be precisely
+    // represented by the specified semantics.
+    bool isRepresentableBy(const fltSemantics &S) const {
+      return maxExponent <= S.maxExponent && minExponent >= S.minExponent &&
+             precision <= S.precision;
+    }
   };
 
   static const fltSemantics semIEEEhalf = {15, -14, 11, 16};
@@ -4875,6 +4882,32 @@ APFloat::opStatus APFloat::convertToInteger(APSInt &result,
   return status;
 }
 
+double APFloat::convertToDouble() const {
+  if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEdouble)
+    return getIEEE().convertToDouble();
+  assert(getSemantics().isRepresentableBy(semIEEEdouble) &&
+         "Float semantics is not representable by IEEEdouble");
+  APFloat Temp = *this;
+  bool LosesInfo;
+  opStatus St = Temp.convert(semIEEEdouble, rmNearestTiesToEven, &LosesInfo);
+  assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision");
+  (void)St;
+  return Temp.getIEEE().convertToDouble();
+}
+
+float APFloat::convertToFloat() const {
+  if (&getSemantics() == (const llvm::fltSemantics *)&semIEEEsingle)
+    return getIEEE().convertToFloat();
+  assert(getSemantics().isRepresentableBy(semIEEEsingle) &&
+         "Float semantics is not representable by IEEEsingle");
+  APFloat Temp = *this;
+  bool LosesInfo;
+  opStatus St = Temp.convert(semIEEEsingle, rmNearestTiesToEven, &LosesInfo);
+  assert(!(St & opInexact) && !LosesInfo && "Unexpected imprecision");
+  (void)St;
+  return Temp.getIEEE().convertToFloat();
+}
+
 } // namespace llvm
 
 #undef APFLOAT_DISPATCH_ON_SEMANTICS

diff  --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 2088df0b4d3f..1683a9d67173 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -1271,8 +1271,10 @@ TEST(APFloatTest, makeNaN) {
 #ifdef GTEST_HAS_DEATH_TEST
 #ifndef NDEBUG
 TEST(APFloatTest, SemanticsDeath) {
-  EXPECT_DEATH(APFloat(APFloat::IEEEsingle(), 0).convertToDouble(), "Float semantics are not IEEEdouble");
-  EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(),  "Float semantics are not IEEEsingle");
+  EXPECT_DEATH(APFloat(APFloat::IEEEquad(), 0).convertToDouble(),
+               "Float semantics is not representable by IEEEdouble");
+  EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0).convertToFloat(),
+               "Float semantics is not representable by IEEEsingle");
 }
 #endif
 #endif
@@ -4709,4 +4711,259 @@ TEST(APFloatTest, x87Next) {
   F.next(false);
   EXPECT_TRUE(ilogb(F) == -1);
 }
+
+TEST(APFloatTest, ToDouble) {
+  APFloat DPosZero(0.0);
+  APFloat DPosZeroToDouble(DPosZero.convertToDouble());
+  EXPECT_TRUE(DPosZeroToDouble.isPosZero());
+  APFloat DNegZero(-0.0);
+  APFloat DNegZeroToDouble(DNegZero.convertToDouble());
+  EXPECT_TRUE(DNegZeroToDouble.isNegZero());
+
+  APFloat DOne(1.0);
+  EXPECT_EQ(1.0, DOne.convertToDouble());
+  APFloat DPosLargest = APFloat::getLargest(APFloat::IEEEdouble(), false);
+  EXPECT_EQ(std::numeric_limits<double>::max(), DPosLargest.convertToDouble());
+  APFloat DNegLargest = APFloat::getLargest(APFloat::IEEEdouble(), true);
+  EXPECT_EQ(-std::numeric_limits<double>::max(), DNegLargest.convertToDouble());
+  APFloat DPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEdouble(), false);
+  EXPECT_EQ(std::numeric_limits<double>::min(), DPosSmallest.convertToDouble());
+  APFloat DNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEdouble(), true);
+  EXPECT_EQ(-std::numeric_limits<double>::min(),
+            DNegSmallest.convertToDouble());
+
+  APFloat DSmallestDenorm = APFloat::getSmallest(APFloat::IEEEdouble(), false);
+  EXPECT_EQ(std::numeric_limits<double>::denorm_min(),
+            DSmallestDenorm.convertToDouble());
+  APFloat DLargestDenorm(APFloat::IEEEdouble(), "0x0.FFFFFFFFFFFFFp-1022");
+  EXPECT_EQ(/*0x0.FFFFFFFFFFFFFp-1022*/ 2.225073858507201e-308,
+            DLargestDenorm.convertToDouble());
+
+  APFloat DPosInf = APFloat::getInf(APFloat::IEEEdouble());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), DPosInf.convertToDouble());
+  APFloat DNegInf = APFloat::getInf(APFloat::IEEEdouble(), true);
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            DNegInf.convertToDouble());
+  APFloat DQNaN = APFloat::getQNaN(APFloat::IEEEdouble());
+  EXPECT_TRUE(std::isnan(DQNaN.convertToDouble()));
+
+  APFloat FPosZero(0.0F);
+  APFloat FPosZeroToDouble(FPosZero.convertToDouble());
+  EXPECT_TRUE(FPosZeroToDouble.isPosZero());
+  APFloat FNegZero(-0.0F);
+  APFloat FNegZeroToDouble(FNegZero.convertToDouble());
+  EXPECT_TRUE(FNegZeroToDouble.isNegZero());
+
+  APFloat FOne(1.0F);
+  EXPECT_EQ(1.0, FOne.convertToDouble());
+  APFloat FPosLargest = APFloat::getLargest(APFloat::IEEEsingle(), false);
+  EXPECT_EQ(std::numeric_limits<float>::max(), FPosLargest.convertToDouble());
+  APFloat FNegLargest = APFloat::getLargest(APFloat::IEEEsingle(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::max(), FNegLargest.convertToDouble());
+  APFloat FPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+  EXPECT_EQ(std::numeric_limits<float>::min(), FPosSmallest.convertToDouble());
+  APFloat FNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::min(), FNegSmallest.convertToDouble());
+
+  APFloat FSmallestDenorm = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+  EXPECT_EQ(std::numeric_limits<float>::denorm_min(),
+            FSmallestDenorm.convertToDouble());
+  APFloat FLargestDenorm(APFloat::IEEEdouble(), "0x0.FFFFFEp-126");
+  EXPECT_EQ(/*0x0.FFFFFEp-126*/ 1.1754942106924411e-38,
+            FLargestDenorm.convertToDouble());
+
+  APFloat FPosInf = APFloat::getInf(APFloat::IEEEsingle());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), FPosInf.convertToDouble());
+  APFloat FNegInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            FNegInf.convertToDouble());
+  APFloat FQNaN = APFloat::getQNaN(APFloat::IEEEsingle());
+  EXPECT_TRUE(std::isnan(FQNaN.convertToDouble()));
+
+  APFloat HPosZero = APFloat::getZero(APFloat::IEEEhalf());
+  APFloat HPosZeroToDouble(HPosZero.convertToDouble());
+  EXPECT_TRUE(HPosZeroToDouble.isPosZero());
+  APFloat HNegZero = APFloat::getZero(APFloat::IEEEhalf(), true);
+  APFloat HNegZeroToDouble(HNegZero.convertToDouble());
+  EXPECT_TRUE(HNegZeroToDouble.isNegZero());
+
+  APFloat HOne(APFloat::IEEEhalf(), "1.0");
+  EXPECT_EQ(1.0, HOne.convertToDouble());
+  APFloat HPosLargest = APFloat::getLargest(APFloat::IEEEhalf(), false);
+  EXPECT_EQ(65504.0, HPosLargest.convertToDouble());
+  APFloat HNegLargest = APFloat::getLargest(APFloat::IEEEhalf(), true);
+  EXPECT_EQ(-65504.0, HNegLargest.convertToDouble());
+  APFloat HPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEhalf(), false);
+  EXPECT_EQ(/*0x1.p-14*/ 6.103515625e-05, HPosSmallest.convertToDouble());
+  APFloat HNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEhalf(), true);
+  EXPECT_EQ(/*-0x1.p-14*/ -6.103515625e-05, HNegSmallest.convertToDouble());
+
+  APFloat HSmallestDenorm = APFloat::getSmallest(APFloat::IEEEhalf(), false);
+  EXPECT_EQ(/*0x1.p-24*/ 5.960464477539063e-08,
+            HSmallestDenorm.convertToDouble());
+  APFloat HLargestDenorm(APFloat::IEEEhalf(), "0x1.FFCp-14");
+  EXPECT_EQ(/*0x1.FFCp-14*/ 0.00012201070785522461,
+            HLargestDenorm.convertToDouble());
+
+  APFloat HPosInf = APFloat::getInf(APFloat::IEEEhalf());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), HPosInf.convertToDouble());
+  APFloat HNegInf = APFloat::getInf(APFloat::IEEEhalf(), true);
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            HNegInf.convertToDouble());
+  APFloat HQNaN = APFloat::getQNaN(APFloat::IEEEhalf());
+  EXPECT_TRUE(std::isnan(HQNaN.convertToDouble()));
+
+  APFloat BPosZero = APFloat::getZero(APFloat::IEEEhalf());
+  APFloat BPosZeroToDouble(BPosZero.convertToDouble());
+  EXPECT_TRUE(BPosZeroToDouble.isPosZero());
+  APFloat BNegZero = APFloat::getZero(APFloat::IEEEhalf(), true);
+  APFloat BNegZeroToDouble(BNegZero.convertToDouble());
+  EXPECT_TRUE(BNegZeroToDouble.isNegZero());
+
+  APFloat BOne(APFloat::BFloat(), "1.0");
+  EXPECT_EQ(1.0, BOne.convertToDouble());
+  APFloat BPosLargest = APFloat::getLargest(APFloat::BFloat(), false);
+  EXPECT_EQ(/*0x1.FEp127*/ 3.3895313892515355e+38,
+            BPosLargest.convertToDouble());
+  APFloat BNegLargest = APFloat::getLargest(APFloat::BFloat(), true);
+  EXPECT_EQ(/*-0x1.FEp127*/ -3.3895313892515355e+38,
+            BNegLargest.convertToDouble());
+  APFloat BPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::BFloat(), false);
+  EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38,
+            BPosSmallest.convertToDouble());
+  APFloat BNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::BFloat(), true);
+  EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38,
+            BNegSmallest.convertToDouble());
+
+  APFloat BSmallestDenorm = APFloat::getSmallest(APFloat::BFloat(), false);
+  EXPECT_EQ(/*0x1.p-133*/ 9.183549615799121e-41,
+            BSmallestDenorm.convertToDouble());
+  APFloat BLargestDenorm(APFloat::BFloat(), "0x1.FCp-127");
+  EXPECT_EQ(/*0x1.FCp-127*/ 1.1663108012064884e-38,
+            BLargestDenorm.convertToDouble());
+
+  APFloat BPosInf = APFloat::getInf(APFloat::BFloat());
+  EXPECT_EQ(std::numeric_limits<double>::infinity(), BPosInf.convertToDouble());
+  APFloat BNegInf = APFloat::getInf(APFloat::BFloat(), true);
+  EXPECT_EQ(-std::numeric_limits<double>::infinity(),
+            BNegInf.convertToDouble());
+  APFloat BQNaN = APFloat::getQNaN(APFloat::BFloat());
+  EXPECT_TRUE(std::isnan(BQNaN.convertToDouble()));
+}
+
+TEST(APFloatTest, ToFloat) {
+  APFloat FPosZero(0.0F);
+  APFloat FPosZeroToFloat(FPosZero.convertToFloat());
+  EXPECT_TRUE(FPosZeroToFloat.isPosZero());
+  APFloat FNegZero(-0.0F);
+  APFloat FNegZeroToFloat(FNegZero.convertToFloat());
+  EXPECT_TRUE(FNegZeroToFloat.isNegZero());
+
+  APFloat FOne(1.0F);
+  EXPECT_EQ(1.0F, FOne.convertToFloat());
+  APFloat FPosLargest = APFloat::getLargest(APFloat::IEEEsingle(), false);
+  EXPECT_EQ(std::numeric_limits<float>::max(), FPosLargest.convertToFloat());
+  APFloat FNegLargest = APFloat::getLargest(APFloat::IEEEsingle(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::max(), FNegLargest.convertToFloat());
+  APFloat FPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+  EXPECT_EQ(std::numeric_limits<float>::min(), FPosSmallest.convertToFloat());
+  APFloat FNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::min(), FNegSmallest.convertToFloat());
+
+  APFloat FSmallestDenorm = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+  EXPECT_EQ(std::numeric_limits<float>::denorm_min(),
+            FSmallestDenorm.convertToFloat());
+  APFloat FLargestDenorm(APFloat::IEEEsingle(), "0x1.FFFFFEp-126");
+  EXPECT_EQ(/*0x1.FFFFFEp-126*/ 2.3509885615147286e-38F,
+            FLargestDenorm.convertToFloat());
+
+  APFloat FPosInf = APFloat::getInf(APFloat::IEEEsingle());
+  EXPECT_EQ(std::numeric_limits<float>::infinity(), FPosInf.convertToFloat());
+  APFloat FNegInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::infinity(), FNegInf.convertToFloat());
+  APFloat FQNaN = APFloat::getQNaN(APFloat::IEEEsingle());
+  EXPECT_TRUE(std::isnan(FQNaN.convertToFloat()));
+
+  APFloat HPosZero = APFloat::getZero(APFloat::IEEEhalf());
+  APFloat HPosZeroToFloat(HPosZero.convertToFloat());
+  EXPECT_TRUE(HPosZeroToFloat.isPosZero());
+  APFloat HNegZero = APFloat::getZero(APFloat::IEEEhalf(), true);
+  APFloat HNegZeroToFloat(HNegZero.convertToFloat());
+  EXPECT_TRUE(HNegZeroToFloat.isNegZero());
+
+  APFloat HOne(APFloat::IEEEhalf(), "1.0");
+  EXPECT_EQ(1.0F, HOne.convertToFloat());
+  APFloat HPosLargest = APFloat::getLargest(APFloat::IEEEhalf(), false);
+  EXPECT_EQ(/*0x1.FFCp15*/ 65504.0F, HPosLargest.convertToFloat());
+  APFloat HNegLargest = APFloat::getLargest(APFloat::IEEEhalf(), true);
+  EXPECT_EQ(/*-0x1.FFCp15*/ -65504.0F, HNegLargest.convertToFloat());
+  APFloat HPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEhalf(), false);
+  EXPECT_EQ(/*0x1.p-14*/ 6.103515625e-05F, HPosSmallest.convertToFloat());
+  APFloat HNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::IEEEhalf(), true);
+  EXPECT_EQ(/*-0x1.p-14*/ -6.103515625e-05F, HNegSmallest.convertToFloat());
+
+  APFloat HSmallestDenorm = APFloat::getSmallest(APFloat::IEEEhalf(), false);
+  EXPECT_EQ(/*0x1.p-24*/ 5.960464477539063e-08F,
+            HSmallestDenorm.convertToFloat());
+  APFloat HLargestDenorm(APFloat::IEEEhalf(), "0x1.FFCp-14");
+  EXPECT_EQ(/*0x1.FFCp-14*/ 0.00012201070785522461F,
+            HLargestDenorm.convertToFloat());
+
+  APFloat HPosInf = APFloat::getInf(APFloat::IEEEhalf());
+  EXPECT_EQ(std::numeric_limits<float>::infinity(), HPosInf.convertToFloat());
+  APFloat HNegInf = APFloat::getInf(APFloat::IEEEhalf(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::infinity(), HNegInf.convertToFloat());
+  APFloat HQNaN = APFloat::getQNaN(APFloat::IEEEhalf());
+  EXPECT_TRUE(std::isnan(HQNaN.convertToFloat()));
+
+  APFloat BPosZero = APFloat::getZero(APFloat::BFloat());
+  APFloat BPosZeroToDouble(BPosZero.convertToFloat());
+  EXPECT_TRUE(BPosZeroToDouble.isPosZero());
+  APFloat BNegZero = APFloat::getZero(APFloat::BFloat(), true);
+  APFloat BNegZeroToDouble(BNegZero.convertToFloat());
+  EXPECT_TRUE(BNegZeroToDouble.isNegZero());
+
+  APFloat BOne(APFloat::BFloat(), "1.0");
+  EXPECT_EQ(1.0F, BOne.convertToFloat());
+  APFloat BPosLargest = APFloat::getLargest(APFloat::BFloat(), false);
+  EXPECT_EQ(/*0x1.FEp127*/ 3.3895313892515355e+38F,
+            BPosLargest.convertToFloat());
+  APFloat BNegLargest = APFloat::getLargest(APFloat::BFloat(), true);
+  EXPECT_EQ(/*-0x1.FEp127*/ -3.3895313892515355e+38F,
+            BNegLargest.convertToFloat());
+  APFloat BPosSmallest =
+      APFloat::getSmallestNormalized(APFloat::BFloat(), false);
+  EXPECT_EQ(/*0x1.p-126*/ 1.1754943508222875e-38F,
+            BPosSmallest.convertToFloat());
+  APFloat BNegSmallest =
+      APFloat::getSmallestNormalized(APFloat::BFloat(), true);
+  EXPECT_EQ(/*-0x1.p-126*/ -1.1754943508222875e-38F,
+            BNegSmallest.convertToFloat());
+
+  APFloat BSmallestDenorm = APFloat::getSmallest(APFloat::BFloat(), false);
+  EXPECT_EQ(/*0x1.p-133*/ 9.183549615799121e-41F,
+            BSmallestDenorm.convertToFloat());
+  APFloat BLargestDenorm(APFloat::BFloat(), "0x1.FCp-127");
+  EXPECT_EQ(/*0x1.FCp-127*/ 1.1663108012064884e-38F,
+            BLargestDenorm.convertToFloat());
+
+  APFloat BPosInf = APFloat::getInf(APFloat::BFloat());
+  EXPECT_EQ(std::numeric_limits<float>::infinity(), BPosInf.convertToFloat());
+  APFloat BNegInf = APFloat::getInf(APFloat::BFloat(), true);
+  EXPECT_EQ(-std::numeric_limits<float>::infinity(), BNegInf.convertToFloat());
+  APFloat BQNaN = APFloat::getQNaN(APFloat::BFloat());
+  EXPECT_TRUE(std::isnan(BQNaN.convertToFloat()));
+}
 }


        


More information about the llvm-commits mailing list