[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