[llvm] [APFloat] Allow lossless conversions to PPCDoubleDouble (PR #228810)

Eric Ross via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 19:39:20 PDT 2026


https://github.com/ZERICO2005 created https://github.com/llvm/llvm-project/pull/228810

The conversion from `IEEEdouble` to `PPCDoubleDouble` is lossless, since the `double` value is just stored in the high-double of the `PPCDoubleDouble` type. Updated the behavior of `isLosslesslyConvertibleTo` so that any type that can losslessly convert to `IEEEdouble` can also losslessly convert to `PPCDoubleDouble`.


>From 3972f56c10ed72125e832047632ee9afa51b2b24 Mon Sep 17 00:00:00 2001
From: zerico <zerico2005 at gmail.com>
Date: Sat, 3 Oct 2026 20:36:07 -0600
Subject: [PATCH] [APFloat] Allow lossless conversions to PPC double-double

---
 llvm/lib/Support/APFloat.cpp       | 14 ++++++++++----
 llvm/unittests/ADT/APFloatTest.cpp | 30 ++++++++++++++++++++++++++++--
 2 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 3d1932454761f1..7323f5c37675c5 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -236,17 +236,23 @@ bool APFloatBase::isRepresentableBy(const fltSemantics &A,
 }
 
 bool APFloatBase::isLosslesslyConvertibleTo(const fltSemantics &From,
-                                            const fltSemantics &To,
+                                            const fltSemantics &InitialTo,
                                             bool IgnoreNaNs) {
-  if (&From == &To)
+  if (&From == &InitialTo)
     return true;
 
   // PPC double-double cannot be described by a conventional exponent range
   // and precision. In particular, converting it to another semantics drops
-  // its low double, so conservatively reject conversions involving it.
-  if (&From == &semPPCDoubleDouble || &To == &semPPCDoubleDouble)
+  // its low double, so conservatively reject conversions from it.
+  if (&From == &semPPCDoubleDouble)
     return false;
 
+  // Converting to PPC double-double is lossless exactly when the value fits
+  // in its high double. In other words, the conversion is lossless if the
+  // conversion to IEEEdouble is lossless.
+  const fltSemantics &To =
+      &InitialTo == &semPPCDoubleDouble ? semIEEEdouble : InitialTo;
+
   if (!isRepresentableBy(From, To))
     return false;
 
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 40a121232fd29e..1577a92b31bf97 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -143,6 +143,17 @@ TEST(APFloatTest, IsLosslesslyConvertibleToKnownWiderSemantics) {
       {APFloat::S_Float6E2M3FN, APFloat::S_IEEEhalf, false},
       {APFloat::S_Float4E2M1FN, APFloat::S_IEEEhalf, false},
       {APFloat::S_x87DoubleExtended, APFloat::S_IEEEquad, true},
+      // Anything that fits in a double fits in PPC double-double's high
+      // double, so the conversion will be lossless.
+      {APFloat::S_IEEEhalf, APFloat::S_PPCDoubleDouble, true},
+      {APFloat::S_BFloat, APFloat::S_PPCDoubleDouble, true},
+      {APFloat::S_IEEEsingle, APFloat::S_PPCDoubleDouble, true},
+      {APFloat::S_IEEEdouble, APFloat::S_PPCDoubleDouble, true},
+      {APFloat::S_Float8E5M2, APFloat::S_PPCDoubleDouble, true},
+      {APFloat::S_Float8E5M2FNUZ, APFloat::S_PPCDoubleDouble, false},
+      {APFloat::S_Float8E4M3FN, APFloat::S_PPCDoubleDouble, false},
+      {APFloat::S_Float8E8M0FNU, APFloat::S_PPCDoubleDouble, false},
+      {APFloat::S_Float4E2M1FN, APFloat::S_PPCDoubleDouble, false},
   };
 
   for (const TestCase &Case : Cases) {
@@ -182,12 +193,27 @@ TEST(APFloatTest, IsLosslesslyConvertibleToRejectsInformationLoss) {
   EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(NarrowNanOnly,
                                                       WiderFiniteOnly, true));
 
-  // PPC double-double's low component is not described by its fltSemantics
-  // exponent and precision fields, so only identity is known to be lossless.
+  // Converting from PPC double-double drops its low component, which is not
+  // described by its fltSemantics exponent and precision fields, so only
+  // identity is known to be lossless.
   EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(
       APFloat::PPCDoubleDouble(), APFloat::IEEEquad(), true));
+  EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(
+      APFloat::PPCDoubleDouble(), APFloat::IEEEdouble(), true));
+
+  // Converting to PPC double-double is only lossless for sources that fit
+  // in its high double, because converting back recovers just that double.
   EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(
       APFloat::IEEEquad(), APFloat::PPCDoubleDouble(), true));
+  EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(
+      APFloat::x87DoubleExtended(), APFloat::PPCDoubleDouble(), true));
+
+  // A source IEEE signaling NaN is quieted by the conversion, so a double
+  // source needs IgnoreNaNs even though its value range fits exactly.
+  EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(
+      APFloat::IEEEdouble(), APFloat::PPCDoubleDouble(), false));
+  EXPECT_FALSE(APFloatBase::isLosslesslyConvertibleTo(
+      APFloat::IEEEsingle(), APFloat::PPCDoubleDouble(), false));
 }
 
 TEST(APFloatTest, LosslessConversionsPreserveRepresentativeValues) {



More information about the llvm-commits mailing list