[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