[llvm] 6a932c6 - [APFloat][NFC] Generalize bitcast to also cover x87 semantics (#209781)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 30 04:25:58 PDT 2026
Author: janr-bay
Date: 2026-07-30T13:25:53+02:00
New Revision: 6a932c6041a58a1c352ea65c94810a13d3b453d0
URL: https://github.com/llvm/llvm-project/commit/6a932c6041a58a1c352ea65c94810a13d3b453d0
DIFF: https://github.com/llvm/llvm-project/commit/6a932c6041a58a1c352ea65c94810a13d3b453d0.diff
LOG: [APFloat][NFC] Generalize bitcast to also cover x87 semantics (#209781)
This removes the special case code for bitcasting APInt to a float with
x87 semantics in convertF80LongDoubleAPFloatToAPInt. This makes it
consistent with previous removal of special cases and will remove one
more small obstacle to making APFloat extensible.
Added:
Modified:
llvm/lib/Support/APFloat.cpp
llvm/unittests/ADT/APFloatTest.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp
index 1755f47256e6e..be255bd19964b 100644
--- a/llvm/lib/Support/APFloat.cpp
+++ b/llvm/lib/Support/APFloat.cpp
@@ -3378,34 +3378,8 @@ hash_code hash_value(const IEEEFloat &Arg) {
// the actual IEEE respresentations. We compensate for that here.
APInt IEEEFloat::convertF80LongDoubleAPFloatToAPInt() const {
- assert(semantics ==
- (const llvm::fltSemantics *)&APFloatBase::semX87DoubleExtended);
- assert(partCount()==2);
-
- uint64_t myexponent, mysignificand;
-
- if (isFiniteNonZero()) {
- myexponent = exponent+16383; //bias
- mysignificand = significandParts()[0];
- if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL))
- myexponent = 0; // denormal
- } else if (category==fcZero) {
- myexponent = 0;
- mysignificand = 0;
- } else if (category==fcInfinity) {
- myexponent = 0x7fff;
- mysignificand = 0x8000000000000000ULL;
- } else {
- assert(category == fcNaN && "Unknown category");
- myexponent = 0x7fff;
- mysignificand = significandParts()[0];
- }
-
- uint64_t words[2];
- words[0] = mysignificand;
- words[1] = ((uint64_t)(sign & 1) << 15) |
- (myexponent & 0x7fffLL);
- return APInt(80, words);
+ assert(partCount() == 2);
+ return convertIEEEFloatToAPInt<APFloatBase::semX87DoubleExtended>();
}
APInt IEEEFloat::convertPPCDoubleDoubleLegacyAPFloatToAPInt() const {
@@ -3457,10 +3431,11 @@ APInt IEEEFloat::convertPPCDoubleDoubleLegacyAPFloatToAPInt() const {
template <const fltSemantics &S>
APInt IEEEFloat::convertIEEEFloatToAPInt() const {
assert(semantics == &S);
- constexpr unsigned int trailing_significand_bits = S.precision - 1;
- constexpr int integer_bit_part = trailing_significand_bits / integerPartWidth;
- constexpr integerPart integer_bit =
- integerPart{1} << (trailing_significand_bits % integerPartWidth);
+ constexpr unsigned int trailing_significand_bits =
+ S.precision - 1 + S.hasExplicitIntegerBit;
+ constexpr int integer_bit_part = (S.precision - 1) / integerPartWidth;
+ constexpr integerPart integer_bit = integerPart{1}
+ << ((S.precision - 1) % integerPartWidth);
constexpr uint64_t significand_mask = integer_bit - 1;
constexpr unsigned int exponent_bits =
S.sizeInBits - (S.hasSignedRepr ? 1 : 0) - trailing_significand_bits;
@@ -3491,6 +3466,9 @@ APInt IEEEFloat::convertIEEEFloatToAPInt() const {
llvm_unreachable("semantics don't support inf!");
myexponent = ::exponentInf(S) + bias;
mysignificand.fill(0);
+ if constexpr (S.hasExplicitIntegerBit) {
+ mysignificand[0] = integerPart{1} << (trailing_significand_bits - 1);
+ }
} else {
assert(category == fcNaN && "Unknown category!");
if (S.nonFiniteBehavior == fltNonfiniteBehavior::FiniteOnly)
@@ -3502,9 +3480,11 @@ APInt IEEEFloat::convertIEEEFloatToAPInt() const {
std::array<uint64_t, (S.sizeInBits + 63) / 64> words;
auto words_iter =
std::copy_n(mysignificand.begin(), mysignificand.size(), words.begin());
- if constexpr (significand_mask != 0 || trailing_significand_bits == 0) {
- // Clear the integer bit.
- words[mysignificand.size() - 1] &= significand_mask;
+ if constexpr (!S.hasExplicitIntegerBit) {
+ if constexpr (significand_mask != 0 || trailing_significand_bits == 0) {
+ // Clear the integer bit.
+ words[mysignificand.size() - 1] &= significand_mask;
+ }
}
std::fill(words_iter, words.end(), uint64_t{0});
constexpr size_t last_word = words.size() - 1;
diff --git a/llvm/unittests/ADT/APFloatTest.cpp b/llvm/unittests/ADT/APFloatTest.cpp
index 2f6abc10b3a8f..55d39e7f0a414 100644
--- a/llvm/unittests/ADT/APFloatTest.cpp
+++ b/llvm/unittests/ADT/APFloatTest.cpp
@@ -7508,6 +7508,19 @@ TEST(APFloatTest, x87Bits) {
makeX87Bits(false, bias * 2 - 1, 1, 0));
EXPECT_TRUE((pseudoDenormal * scale).bitwiseIsEqual(makeX87(1.0)));
}
+
+ // Test pseudodenormal with non-zero significand
+ {
+ APFloat pseudoDenormal(S, makeX87Bits(false, 0, 1, 0x7FFF000000000000ull));
+ EXPECT_TRUE(pseudoDenormal.isFinite());
+ EXPECT_FALSE(pseudoDenormal.isDenormal());
+ EXPECT_TRUE(pseudoDenormal.isNormal());
+
+ // Verify the round-trip produces the normalized form
+ APInt result = pseudoDenormal.bitcastToAPInt();
+ APInt expected(80, {0xFFFF000000000000ull, 0x0001ull});
+ EXPECT_EQ(expected, result);
+ }
}
static bool isBitcastRoundtripSafe(APFloat value) {
More information about the llvm-commits
mailing list