[PATCH] D151923: [APFloat] Add APFloat semantic support for TF32

2023-06-22 Thread Jeremy Furtek via Phabricator via cfe-commits
jfurtek updated this revision to Diff 533726.
jfurtek added a comment.

- Fix comment and clang-formatting
- Another clang-format fix
- Rebase, clang-format...


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151923/new/

https://reviews.llvm.org/D151923

Files:
  clang/lib/AST/MicrosoftMangle.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -682,6 +682,26 @@
 EXPECT_TRUE(T.isDenormal());
 EXPECT_EQ(fcPosSubnormal, T.classify());
   }
+
+  // Test TF32
+  {
+const char *MinNormalStr = "1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), MinNormalStr).isDenormal());
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), 0).isDenormal());
+
+APFloat Val2(APFloat::FloatTF32(), 2);
+APFloat T(APFloat::FloatTF32(), MinNormalStr);
+T.divide(Val2, rdmd);
+EXPECT_TRUE(T.isDenormal());
+EXPECT_EQ(fcPosSubnormal, T.classify());
+
+const char *NegMinNormalStr = "-1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), NegMinNormalStr).isDenormal());
+APFloat NegT(APFloat::FloatTF32(), NegMinNormalStr);
+NegT.divide(Val2, rdmd);
+EXPECT_TRUE(NegT.isDenormal());
+EXPECT_EQ(fcNegSubnormal, NegT.classify());
+  }
 }
 
 TEST(APFloatTest, IsSmallestNormalized) {
@@ -1350,6 +1370,16 @@
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), false, true, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, false, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, true,  0xaaULL },
+{0x3fe00ULL, APFloat::FloatTF32(), false, false,  0xULL },
+{0x7fe00ULL, APFloat::FloatTF32(), false,  true,  0xULL },
+{0x3feaaULL, APFloat::FloatTF32(), false, false,0xaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,   0xdaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,  0xfdaaULL },
+{0x3fd00ULL, APFloat::FloatTF32(),  true, false,  0xULL },
+{0x7fd00ULL, APFloat::FloatTF32(),  true,  true,  0xULL },
+{0x3fcaaULL, APFloat::FloatTF32(),  true, false,0xaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0xfaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0x1aaULL },
   // clang-format on
   };
 
@@ -1780,6 +1810,8 @@
 APFloat::getLargest(APFloat::Float8E5M2FNUZ()).convertToDouble());
   EXPECT_EQ(
   30, APFloat::getLargest(APFloat::Float8E4M3B11FNUZ()).convertToDouble());
+  EXPECT_EQ(3.40116213421e+38f,
+APFloat::getLargest(APFloat::FloatTF32()).convertToFloat());
 }
 
 TEST(APFloatTest, getSmallest) {
@@ -1831,6 +1863,13 @@
   EXPECT_TRUE(test.isFiniteNonZero());
   EXPECT_TRUE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+  test = APFloat::getSmallest(APFloat::FloatTF32(), true);
+  expected = APFloat(APFloat::FloatTF32(), "-0x0.004p-126");
+  EXPECT_TRUE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_TRUE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
 }
 
 TEST(APFloatTest, getSmallestNormalized) {
@@ -1905,6 +1944,14 @@
   EXPECT_FALSE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
   EXPECT_TRUE(test.isSmallestNormalized());
+
+  test = APFloat::getSmallestNormalized(APFloat::FloatTF32(), false);
+  expected = APFloat(APFloat::FloatTF32(), "0x1p-126");
+  EXPECT_FALSE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_FALSE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
+  EXPECT_TRUE(test.isSmallestNormalized());
 }
 
 TEST(APFloatTest, getZero) {
@@ -1936,7 +1983,9 @@
   {&APFloat::Float8E4M3FNUZ(), false, false, {0, 0}, 1},
   {&APFloat::Float8E4M3FNUZ(), true, false, {0, 0}, 1},
   {&APFloat::Float8E4M3B11FNUZ(), false, false, {0, 0}, 1},
-  {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1}};
+  {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1},
+  {&APFloat::FloatTF32(), false, true, {0, 0}, 1},
+  {&APFloat::FloatTF32(), true, true, {0x4ULL, 0}, 1}};
   const unsigned NumGetZeroTests = std::size(GetZeroTest);
   for (unsigned i = 0; i < NumGetZeroTests; ++i) {
 APFloat test = APFloat::getZero(*GetZeroTest[i].semantics,
@@ -6229,6 +6278,34 @@
   EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
 }
 
+TEST(APFloatTest, FloatTF32ToDouble) {
+  APFloat One(APFloat::FloatTF32(), "1.0");
+  EXPECT_EQ(1.0, One.convertToDouble());
+  APFloat PosL

[PATCH] D151923: [APFloat] Add APFloat semantic support for TF32

2023-06-01 Thread Jeremy Furtek via Phabricator via cfe-commits
jfurtek created this revision.
Herald added subscribers: bzcheeseman, rriddle, hiraditya.
Herald added a project: All.
jfurtek requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, stephenneuendorffer.
Herald added projects: clang, LLVM.

This diff adds APFloat support for a semantic that matches the TF32 data type
used by some accelerators (most notably GPUs from both NVIDIA and AMD).

For more information on the TF32 data type, see 
https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/.
Some intrinsics that support the TF32 data type were added in 
https://reviews.llvm.org/D122044.

For some discussion on supporting common semantics in `APFloat`, see similar
efforts for 8-bit formats at https://reviews.llvm.org/D146441, as well as
https://discourse.llvm.org/t/rfc-adding-the-amd-graphcore-maybe-others-float8-formats-to-apfloat/67969.

A subsequent diff will extend MLIR to use this data type. (Those changes are
not part of this diff to simplify the review process.)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151923

Files:
  clang/lib/AST/MicrosoftMangle.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -682,6 +682,27 @@
 EXPECT_TRUE(T.isDenormal());
 EXPECT_EQ(fcPosSubnormal, T.classify());
   }
+
+  // Test TF32
+  {
+const char *MinNormalStr = "1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), MinNormalStr).isDenormal());
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), 0).isDenormal());
+
+APFloat Val2(APFloat::FloatTF32(), 2);
+APFloat T(APFloat::FloatTF32(), MinNormalStr);
+T.divide(Val2, rdmd);
+EXPECT_TRUE(T.isDenormal());
+EXPECT_EQ(fcPosSubnormal, T.classify());
+
+
+const char *NegMinNormalStr = "-1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), NegMinNormalStr).isDenormal());
+APFloat NegT(APFloat::FloatTF32(), NegMinNormalStr);
+NegT.divide(Val2, rdmd);
+EXPECT_TRUE(NegT.isDenormal());
+EXPECT_EQ(fcNegSubnormal, NegT.classify());
+  }
 }
 
 TEST(APFloatTest, IsSmallestNormalized) {
@@ -1350,6 +1371,16 @@
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), false, true, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, false, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, true,  0xaaULL },
+{0x3fe00ULL, APFloat::FloatTF32(), false, false,  0xULL },
+{0x7fe00ULL, APFloat::FloatTF32(), false,  true,  0xULL },
+{0x3feaaULL, APFloat::FloatTF32(), false, false,0xaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,   0xdaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,  0xfdaaULL },
+{0x3fd00ULL, APFloat::FloatTF32(),  true, false,  0xULL },
+{0x7fd00ULL, APFloat::FloatTF32(),  true,  true,  0xULL },
+{0x3fcaaULL, APFloat::FloatTF32(),  true, false,0xaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0xfaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0x1aaULL },
   // clang-format on
   };
 
@@ -1780,6 +1811,7 @@
 APFloat::getLargest(APFloat::Float8E5M2FNUZ()).convertToDouble());
   EXPECT_EQ(
   30, APFloat::getLargest(APFloat::Float8E4M3B11FNUZ()).convertToDouble());
+  EXPECT_EQ(3.40116213421e+38f, APFloat::getLargest(APFloat::FloatTF32()).convertToFloat());
 }
 
 TEST(APFloatTest, getSmallest) {
@@ -1831,6 +1863,14 @@
   EXPECT_TRUE(test.isFiniteNonZero());
   EXPECT_TRUE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+  test = APFloat::getSmallest(APFloat::FloatTF32(), true);
+  expected = APFloat(APFloat::FloatTF32(), "-0x0.004p-126");
+  EXPECT_TRUE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_TRUE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
 }
 
 TEST(APFloatTest, getSmallestNormalized) {
@@ -1905,6 +1945,14 @@
   EXPECT_FALSE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
   EXPECT_TRUE(test.isSmallestNormalized());
+
+  test = APFloat::getSmallestNormalized(APFloat::FloatTF32(), false);
+  expected = APFloat(APFloat::FloatTF32(), "0x1p-126");
+  EXPECT_FALSE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_FALSE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
+  EXPECT_TRUE(test.isSmallestNormalized());
 }
 
 TEST(APFloatTest, getZero) {
@@ -1936,7 +1984,9 @@
   {&APFloat::Float8E4M3FNUZ(), fa

[PATCH] D151923: [APFloat] Add APFloat semantic support for TF32

2023-06-01 Thread Jeremy Furtek via Phabricator via cfe-commits
jfurtek added a comment.

In D151923#4389405 , @mehdi_amini 
wrote:

> I think this LG, but David had to update clang/lib/AST/MicrosoftMangle.cpp 
> when some other float format was added, you don't need this here?

I did update that file - it is part of this diff. (I used that diff as a 
template - otherwise I probably would have missed that change...)

The associated MLIR changes are done - just haven't submitted the diff yet.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151923/new/

https://reviews.llvm.org/D151923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D151923: [APFloat] Add APFloat semantic support for TF32

2023-06-02 Thread Jeremy Furtek via Phabricator via cfe-commits
jfurtek updated this revision to Diff 527968.
jfurtek added a comment.

- Fix comment and clang-formatting


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151923/new/

https://reviews.llvm.org/D151923

Files:
  clang/lib/AST/MicrosoftMangle.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -682,6 +682,27 @@
 EXPECT_TRUE(T.isDenormal());
 EXPECT_EQ(fcPosSubnormal, T.classify());
   }
+
+  // Test TF32
+  {
+const char *MinNormalStr = "1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), MinNormalStr).isDenormal());
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), 0).isDenormal());
+
+APFloat Val2(APFloat::FloatTF32(), 2);
+APFloat T(APFloat::FloatTF32(), MinNormalStr);
+T.divide(Val2, rdmd);
+EXPECT_TRUE(T.isDenormal());
+EXPECT_EQ(fcPosSubnormal, T.classify());
+
+
+const char *NegMinNormalStr = "-1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), NegMinNormalStr).isDenormal());
+APFloat NegT(APFloat::FloatTF32(), NegMinNormalStr);
+NegT.divide(Val2, rdmd);
+EXPECT_TRUE(NegT.isDenormal());
+EXPECT_EQ(fcNegSubnormal, NegT.classify());
+  }
 }
 
 TEST(APFloatTest, IsSmallestNormalized) {
@@ -1350,6 +1371,16 @@
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), false, true, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, false, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, true,  0xaaULL },
+{0x3fe00ULL, APFloat::FloatTF32(), false, false,  0xULL },
+{0x7fe00ULL, APFloat::FloatTF32(), false,  true,  0xULL },
+{0x3feaaULL, APFloat::FloatTF32(), false, false,0xaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,   0xdaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,  0xfdaaULL },
+{0x3fd00ULL, APFloat::FloatTF32(),  true, false,  0xULL },
+{0x7fd00ULL, APFloat::FloatTF32(),  true,  true,  0xULL },
+{0x3fcaaULL, APFloat::FloatTF32(),  true, false,0xaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0xfaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0x1aaULL },
   // clang-format on
   };
 
@@ -1780,6 +1811,8 @@
 APFloat::getLargest(APFloat::Float8E5M2FNUZ()).convertToDouble());
   EXPECT_EQ(
   30, APFloat::getLargest(APFloat::Float8E4M3B11FNUZ()).convertToDouble());
+  EXPECT_EQ(3.40116213421e+38f,
+APFloat::getLargest(APFloat::FloatTF32()).convertToFloat());
 }
 
 TEST(APFloatTest, getSmallest) {
@@ -1831,6 +1864,14 @@
   EXPECT_TRUE(test.isFiniteNonZero());
   EXPECT_TRUE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+  test = APFloat::getSmallest(APFloat::FloatTF32(), true);
+  expected = APFloat(APFloat::FloatTF32(), "-0x0.004p-126");
+  EXPECT_TRUE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_TRUE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
 }
 
 TEST(APFloatTest, getSmallestNormalized) {
@@ -1905,6 +1946,14 @@
   EXPECT_FALSE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
   EXPECT_TRUE(test.isSmallestNormalized());
+
+  test = APFloat::getSmallestNormalized(APFloat::FloatTF32(), false);
+  expected = APFloat(APFloat::FloatTF32(), "0x1p-126");
+  EXPECT_FALSE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_FALSE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
+  EXPECT_TRUE(test.isSmallestNormalized());
 }
 
 TEST(APFloatTest, getZero) {
@@ -1936,7 +1985,9 @@
   {&APFloat::Float8E4M3FNUZ(), false, false, {0, 0}, 1},
   {&APFloat::Float8E4M3FNUZ(), true, false, {0, 0}, 1},
   {&APFloat::Float8E4M3B11FNUZ(), false, false, {0, 0}, 1},
-  {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1}};
+  {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1},
+  {&APFloat::FloatTF32(), false, true, {0, 0}, 1},
+  {&APFloat::FloatTF32(), true, true, {0x4ULL, 0}, 1}};
   const unsigned NumGetZeroTests = std::size(GetZeroTest);
   for (unsigned i = 0; i < NumGetZeroTests; ++i) {
 APFloat test = APFloat::getZero(*GetZeroTest[i].semantics,
@@ -6229,6 +6280,35 @@
   EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
 }
 
+TEST(APFloatTest, FloatTF32ToDouble) {
+  APFloat One(APFloat::FloatTF32(), "1.0");
+  EXPECT_EQ(1.0, One.convertToDouble());
+  APFloat PosLargest = APFloat::getLargest(APFloat::FloatTF32()

[PATCH] D151923: [APFloat] Add APFloat semantic support for TF32

2023-06-02 Thread Jeremy Furtek via Phabricator via cfe-commits
jfurtek added inline comments.



Comment at: llvm/include/llvm/ADT/APFloat.h:190
+// greater throughput than single precision (32-bit) formats.
+S_FloatTF32,
 

majnemer wrote:
> Hmm,  this says improved precision than half but the semantics you gave say 
> 11 digits? Does NVIDIA document how many bits we should expect?
This was a mistake on my part - the **range** is better than FP16, not the 
**precision**. Updated the comment to reflect this.

The blog post linked in the description provides details on the current format 
only - I agree that the PTX description seems intentionally vague.



Comment at: llvm/lib/Support/APFloat.cpp:141
 4, -10, 4, 8, fltNonfiniteBehavior::NanOnly, fltNanEncoding::NegativeZero};
+static constexpr fltSemantics semFloatTF32 = {127, -126, 11, 19};
 static constexpr fltSemantics semX87DoubleExtended = {16383, -16382, 64, 80};

majnemer wrote:
> NVIDIA's 
> [docs](https://docs.nvidia.com/cuda/parallel-thread-execution/#alternate-floating-point-data-formats)
>  say:
> > This data format is a special 32-bit floating point format supported by the 
> > matrix multiply-and-accumulate instructions, with the same range as .f32 
> > and reduced precision (>=10 bits). The internal layout of tf32 format is 
> > implementation defined. PTX facilitates conversion from single precision 
> > .f32 type to tf32 format. A register variable containing tf32 data must be 
> > declared with .b32 type.
> 
> As written, it's at least 11 bits but it can change over time. Will we need 
> corresponding flavors of this for future architectures over time?
If it changes, we would need to create a different float semantic to represent 
the new format (i.e. perhaps `TF32v2` or something like that).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151923/new/

https://reviews.llvm.org/D151923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D151923: [APFloat] Add APFloat semantic support for TF32

2023-06-05 Thread Jeremy Furtek via Phabricator via cfe-commits
jfurtek updated this revision to Diff 528567.
jfurtek added a comment.

- Another clang-format fix


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151923/new/

https://reviews.llvm.org/D151923

Files:
  clang/lib/AST/MicrosoftMangle.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -682,6 +682,27 @@
 EXPECT_TRUE(T.isDenormal());
 EXPECT_EQ(fcPosSubnormal, T.classify());
   }
+
+  // Test TF32
+  {
+const char *MinNormalStr = "1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), MinNormalStr).isDenormal());
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), 0).isDenormal());
+
+APFloat Val2(APFloat::FloatTF32(), 2);
+APFloat T(APFloat::FloatTF32(), MinNormalStr);
+T.divide(Val2, rdmd);
+EXPECT_TRUE(T.isDenormal());
+EXPECT_EQ(fcPosSubnormal, T.classify());
+
+
+const char *NegMinNormalStr = "-1.17549435082228750797e-38";
+EXPECT_FALSE(APFloat(APFloat::FloatTF32(), NegMinNormalStr).isDenormal());
+APFloat NegT(APFloat::FloatTF32(), NegMinNormalStr);
+NegT.divide(Val2, rdmd);
+EXPECT_TRUE(NegT.isDenormal());
+EXPECT_EQ(fcNegSubnormal, NegT.classify());
+  }
 }
 
 TEST(APFloatTest, IsSmallestNormalized) {
@@ -1350,6 +1371,16 @@
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), false, true, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, false, 0xaaULL },
 {   0x80ULL, APFloat::Float8E4M3B11FNUZ(), true, true,  0xaaULL },
+{0x3fe00ULL, APFloat::FloatTF32(), false, false,  0xULL },
+{0x7fe00ULL, APFloat::FloatTF32(), false,  true,  0xULL },
+{0x3feaaULL, APFloat::FloatTF32(), false, false,0xaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,   0xdaaULL },
+{0x3ffaaULL, APFloat::FloatTF32(), false, false,  0xfdaaULL },
+{0x3fd00ULL, APFloat::FloatTF32(),  true, false,  0xULL },
+{0x7fd00ULL, APFloat::FloatTF32(),  true,  true,  0xULL },
+{0x3fcaaULL, APFloat::FloatTF32(),  true, false,0xaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0xfaaULL },
+{0x3fdaaULL, APFloat::FloatTF32(),  true, false,   0x1aaULL },
   // clang-format on
   };
 
@@ -1780,6 +1811,8 @@
 APFloat::getLargest(APFloat::Float8E5M2FNUZ()).convertToDouble());
   EXPECT_EQ(
   30, APFloat::getLargest(APFloat::Float8E4M3B11FNUZ()).convertToDouble());
+  EXPECT_EQ(3.40116213421e+38f,
+APFloat::getLargest(APFloat::FloatTF32()).convertToFloat());
 }
 
 TEST(APFloatTest, getSmallest) {
@@ -1831,6 +1864,13 @@
   EXPECT_TRUE(test.isFiniteNonZero());
   EXPECT_TRUE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+  test = APFloat::getSmallest(APFloat::FloatTF32(), true);
+  expected = APFloat(APFloat::FloatTF32(), "-0x0.004p-126");
+  EXPECT_TRUE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_TRUE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
 }
 
 TEST(APFloatTest, getSmallestNormalized) {
@@ -1905,6 +1945,14 @@
   EXPECT_FALSE(test.isDenormal());
   EXPECT_TRUE(test.bitwiseIsEqual(expected));
   EXPECT_TRUE(test.isSmallestNormalized());
+
+  test = APFloat::getSmallestNormalized(APFloat::FloatTF32(), false);
+  expected = APFloat(APFloat::FloatTF32(), "0x1p-126");
+  EXPECT_FALSE(test.isNegative());
+  EXPECT_TRUE(test.isFiniteNonZero());
+  EXPECT_FALSE(test.isDenormal());
+  EXPECT_TRUE(test.bitwiseIsEqual(expected));
+  EXPECT_TRUE(test.isSmallestNormalized());
 }
 
 TEST(APFloatTest, getZero) {
@@ -1936,7 +1984,9 @@
   {&APFloat::Float8E4M3FNUZ(), false, false, {0, 0}, 1},
   {&APFloat::Float8E4M3FNUZ(), true, false, {0, 0}, 1},
   {&APFloat::Float8E4M3B11FNUZ(), false, false, {0, 0}, 1},
-  {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1}};
+  {&APFloat::Float8E4M3B11FNUZ(), true, false, {0, 0}, 1},
+  {&APFloat::FloatTF32(), false, true, {0, 0}, 1},
+  {&APFloat::FloatTF32(), true, true, {0x4ULL, 0}, 1}};
   const unsigned NumGetZeroTests = std::size(GetZeroTest);
   for (unsigned i = 0; i < NumGetZeroTests; ++i) {
 APFloat test = APFloat::getZero(*GetZeroTest[i].semantics,
@@ -6229,6 +6279,35 @@
   EXPECT_TRUE(std::isnan(QNaN.convertToDouble()));
 }
 
+TEST(APFloatTest, FloatTF32ToDouble) {
+  APFloat One(APFloat::FloatTF32(), "1.0");
+  EXPECT_EQ(1.0, One.convertToDouble());
+  APFloat PosLargest = APFloat::getLargest(APFloat::FloatTF32(), false);