[libc-commits] [libc] 6666e0d - [libc] Make FPBits a union.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Tue Apr 13 09:27:32 PDT 2021


Author: Siva Chandra Reddy
Date: 2021-04-13T09:21:35-07:00
New Revision: 6666e0d7a29c639df7a1652b6d3bf16f28edd45a

URL: https://github.com/llvm/llvm-project/commit/6666e0d7a29c639df7a1652b6d3bf16f28edd45a
DIFF: https://github.com/llvm/llvm-project/commit/6666e0d7a29c639df7a1652b6d3bf16f28edd45a.diff

LOG: [libc] Make FPBits a union.

This helps us avoid the uncomfortable reinterpret-casts. Avoiding the
reinterpret casts prevents us from tripping the sanitizers as well.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D100360

Added: 
    

Modified: 
    libc/fuzzing/math/Compare.h
    libc/fuzzing/math/RemQuoDiff.h
    libc/src/math/generic/fmaf.cpp
    libc/test/src/math/LdExpTest.h
    libc/test/src/math/NextAfterTest.h
    libc/test/src/math/RoundToIntegerTest.h
    libc/test/src/math/sqrt_test.cpp
    libc/test/src/math/sqrtf_test.cpp
    libc/test/src/math/sqrtl_test.cpp
    libc/utils/FPUtil/BasicOperations.h
    libc/utils/FPUtil/DivisionAndRemainderOperations.h
    libc/utils/FPUtil/FPBits.h
    libc/utils/FPUtil/Hypot.h
    libc/utils/FPUtil/LongDoubleBitsX86.h
    libc/utils/FPUtil/ManipulationFunctions.h
    libc/utils/FPUtil/NearestIntegerOperations.h
    libc/utils/FPUtil/NextAfterLongDoubleX86.h
    libc/utils/FPUtil/NormalFloat.h
    libc/utils/FPUtil/Sqrt.h
    libc/utils/FPUtil/SqrtLongDoubleX86.h
    libc/utils/FPUtil/TestHelpers.cpp
    libc/utils/FPUtil/TestHelpers.h
    libc/utils/MPFRWrapper/MPFRUtils.cpp

Removed: 
    


################################################################################
diff  --git a/libc/fuzzing/math/Compare.h b/libc/fuzzing/math/Compare.h
index 11d54650f66f8..7e7b8da59adf1 100644
--- a/libc/fuzzing/math/Compare.h
+++ b/libc/fuzzing/math/Compare.h
@@ -23,7 +23,7 @@ ValuesEqual(T x1, T x2) {
     return bits2.isNaN() && bits2.isNaN();
 
   // For all other values, we want the values to be bitwise equal.
-  return bits1.bitsAsUInt() == bits2.bitsAsUInt();
+  return bits1.uintval() == bits2.uintval();
 }
 
 template <typename T>

diff  --git a/libc/fuzzing/math/RemQuoDiff.h b/libc/fuzzing/math/RemQuoDiff.h
index df719faa83c12..1a50ca2e6ba3e 100644
--- a/libc/fuzzing/math/RemQuoDiff.h
+++ b/libc/fuzzing/math/RemQuoDiff.h
@@ -43,6 +43,6 @@ void RemQuoDiff(RemQuoFunc<T> func1, RemQuoFunc<T> func2, const uint8_t *data,
 
   __llvm_libc::fputil::FPBits<T> bits1(remainder1);
   __llvm_libc::fputil::FPBits<T> bits2(remainder2);
-  if (bits1.bitsAsUInt() != bits2.bitsAsUInt())
+  if (bits1.uintval() != bits2.uintval())
     __builtin_trap();
 }

diff  --git a/libc/src/math/generic/fmaf.cpp b/libc/src/math/generic/fmaf.cpp
index c2ab7e7c130c4..845655dcb5270 100644
--- a/libc/src/math/generic/fmaf.cpp
+++ b/libc/src/math/generic/fmaf.cpp
@@ -44,17 +44,17 @@ LLVM_LIBC_FUNCTION(float, fmaf, (float x, float y, float z)) {
     // bit of sum, so that the sticky bits used when rounding sum to float are
     // correct (when it matters).
     fputil::FPBits<double> t(
-        (bit_prod.exponent >= bitz.exponent)
-            ? ((static_cast<double>(bit_sum) - bit_prod) - bitz)
-            : ((static_cast<double>(bit_sum) - bitz) - bit_prod));
+        (bit_prod.encoding.exponent >= bitz.encoding.exponent)
+            ? ((double(bit_sum) - double(bit_prod)) - double(bitz))
+            : ((double(bit_sum) - double(bitz)) - double(bit_prod)));
 
     // Update sticky bits if t != 0.0 and the least (52 - 23 - 1 = 28) bits are
     // zero.
-    if (!t.isZero() && ((bit_sum.mantissa & 0xfff'ffffULL) == 0)) {
-      if (bit_sum.sign != t.sign) {
-        ++bit_sum.mantissa;
-      } else if (bit_sum.mantissa) {
-        --bit_sum.mantissa;
+    if (!t.isZero() && ((bit_sum.encoding.mantissa & 0xfff'ffffULL) == 0)) {
+      if (bit_sum.encoding.sign != t.encoding.sign) {
+        ++bit_sum.encoding.mantissa;
+      } else if (bit_sum.encoding.mantissa) {
+        --bit_sum.encoding.mantissa;
       }
     }
   }

diff  --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h
index c4f18657a3399..a2c1b54b1822f 100644
--- a/libc/test/src/math/LdExpTest.h
+++ b/libc/test/src/math/LdExpTest.h
@@ -121,7 +121,7 @@ class LdExpTestTemplate : public __llvm_libc::testing::Test {
     FPBits resultBits(result);
     ASSERT_FALSE(resultBits.isZero());
     // Verify that the result is indeed subnormal.
-    ASSERT_EQ(resultBits.exponent, uint16_t(0));
+    ASSERT_EQ(resultBits.encoding.exponent, uint16_t(0));
     // But if the exp is so less that normalization leads to zero, then
     // the result should be zero.
     result = func(x, -FPBits::maxExponent - int(mantissaWidth) - 5);

diff  --git a/libc/test/src/math/NextAfterTest.h b/libc/test/src/math/NextAfterTest.h
index c7e520175d1fe..8ba3f3096a55b 100644
--- a/libc/test/src/math/NextAfterTest.h
+++ b/libc/test/src/math/NextAfterTest.h
@@ -163,25 +163,31 @@ class NextAfterTestTemplate : public __llvm_libc::testing::Test {
     result = func(x, 0);
     FPBits xBits = FPBits(x);
     FPBits resultBits = FPBits(result);
-    ASSERT_EQ(resultBits.exponent, uint16_t(xBits.exponent - 1));
-    ASSERT_EQ(resultBits.mantissa, (UIntType(1) << MantissaWidth::value) - 1);
+    ASSERT_EQ(resultBits.encoding.exponent,
+              uint16_t(xBits.encoding.exponent - 1));
+    ASSERT_EQ(resultBits.encoding.mantissa,
+              (UIntType(1) << MantissaWidth::value) - 1);
 
     result = func(x, T(33.0));
     resultBits = FPBits(result);
-    ASSERT_EQ(resultBits.exponent, xBits.exponent);
-    ASSERT_EQ(resultBits.mantissa, xBits.mantissa + UIntType(1));
+    ASSERT_EQ(resultBits.encoding.exponent, xBits.encoding.exponent);
+    ASSERT_EQ(resultBits.encoding.mantissa,
+              xBits.encoding.mantissa + UIntType(1));
 
     x = -x;
 
     result = func(x, 0);
     resultBits = FPBits(result);
-    ASSERT_EQ(resultBits.exponent, uint16_t(xBits.exponent - 1));
-    ASSERT_EQ(resultBits.mantissa, (UIntType(1) << MantissaWidth::value) - 1);
+    ASSERT_EQ(resultBits.encoding.exponent,
+              uint16_t(xBits.encoding.exponent - 1));
+    ASSERT_EQ(resultBits.encoding.mantissa,
+              (UIntType(1) << MantissaWidth::value) - 1);
 
     result = func(x, T(-33.0));
     resultBits = FPBits(result);
-    ASSERT_EQ(resultBits.exponent, xBits.exponent);
-    ASSERT_EQ(resultBits.mantissa, xBits.mantissa + UIntType(1));
+    ASSERT_EQ(resultBits.encoding.exponent, xBits.encoding.exponent);
+    ASSERT_EQ(resultBits.encoding.mantissa,
+              xBits.encoding.mantissa + UIntType(1));
   }
 };
 

diff  --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h
index 63b04845f8fc4..0b83b9a1ed5c2 100644
--- a/libc/test/src/math/RoundToIntegerTest.h
+++ b/libc/test/src/math/RoundToIntegerTest.h
@@ -135,9 +135,9 @@ class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test {
     // We start with 1.0 so that the implicit bit for x86 long doubles
     // is set.
     FPBits bits(F(1.0));
-    bits.exponent = exponentLimit + FPBits::exponentBias;
-    bits.sign = 1;
-    bits.mantissa = 0;
+    bits.encoding.exponent = exponentLimit + FPBits::exponentBias;
+    bits.encoding.sign = 1;
+    bits.encoding.mantissa = 0;
 
     F x = bits;
     long mpfrResult;
@@ -199,10 +199,10 @@ class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test {
     // We start with 1.0 so that the implicit bit for x86 long doubles
     // is set.
     FPBits bits(F(1.0));
-    bits.exponent = exponentLimit + FPBits::exponentBias;
-    bits.sign = 1;
-    bits.mantissa = UIntType(0x1)
-                    << (__llvm_libc::fputil::MantissaWidth<F>::value - 1);
+    bits.encoding.exponent = exponentLimit + FPBits::exponentBias;
+    bits.encoding.sign = 1;
+    bits.encoding.mantissa =
+        UIntType(0x1) << (__llvm_libc::fputil::MantissaWidth<F>::value - 1);
 
     F x = bits;
     if (TestModes) {

diff  --git a/libc/test/src/math/sqrt_test.cpp b/libc/test/src/math/sqrt_test.cpp
index a224ff9da22fd..0be62d4e41ec1 100644
--- a/libc/test/src/math/sqrt_test.cpp
+++ b/libc/test/src/math/sqrt_test.cpp
@@ -37,7 +37,7 @@ TEST(LlvmLibcSqrtTest, SpecialValues) {
 TEST(LlvmLibcSqrtTest, DenormalValues) {
   for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) {
     FPBits denormal(0.0);
-    denormal.mantissa = mant;
+    denormal.encoding.mantissa = mant;
 
     ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, double(denormal),
                       __llvm_libc::sqrt(denormal), 0.5);

diff  --git a/libc/test/src/math/sqrtf_test.cpp b/libc/test/src/math/sqrtf_test.cpp
index 6242e25102a0b..91f4a91633fce 100644
--- a/libc/test/src/math/sqrtf_test.cpp
+++ b/libc/test/src/math/sqrtf_test.cpp
@@ -37,7 +37,7 @@ TEST(LlvmLibcSqrtfTest, SpecialValues) {
 TEST(LlvmLibcSqrtfTest, DenormalValues) {
   for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) {
     FPBits denormal(0.0f);
-    denormal.mantissa = mant;
+    denormal.encoding.mantissa = mant;
 
     ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, float(denormal),
                       __llvm_libc::sqrtf(denormal), 0.5);

diff  --git a/libc/test/src/math/sqrtl_test.cpp b/libc/test/src/math/sqrtl_test.cpp
index 37d706c8682e4..1701bfdbc67b9 100644
--- a/libc/test/src/math/sqrtl_test.cpp
+++ b/libc/test/src/math/sqrtl_test.cpp
@@ -37,7 +37,7 @@ TEST(LlvmLibcSqrtlTest, SpecialValues) {
 TEST(LlvmLibcSqrtlTest, DenormalValues) {
   for (UIntType mant = 1; mant < HiddenBit; mant <<= 1) {
     FPBits denormal(0.0L);
-    denormal.mantissa = mant;
+    denormal.encoding.mantissa = mant;
 
     ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, static_cast<long double>(denormal),
                       __llvm_libc::sqrtl(denormal), 0.5);

diff  --git a/libc/utils/FPUtil/BasicOperations.h b/libc/utils/FPUtil/BasicOperations.h
index 5bf3effc1c01d..248f120a89cea 100644
--- a/libc/utils/FPUtil/BasicOperations.h
+++ b/libc/utils/FPUtil/BasicOperations.h
@@ -20,7 +20,7 @@ template <typename T,
           cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
 static inline T abs(T x) {
   FPBits<T> bits(x);
-  bits.sign = 0;
+  bits.encoding.sign = 0;
   return T(bits);
 }
 
@@ -33,11 +33,11 @@ static inline T fmin(T x, T y) {
     return y;
   } else if (bity.isNaN()) {
     return x;
-  } else if (bitx.sign != bity.sign) {
+  } else if (bitx.encoding.sign != bity.encoding.sign) {
     // To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and
     // y has 
diff erent signs and both are not NaNs, we return the number
     // with negative sign.
-    return (bitx.sign ? x : y);
+    return (bitx.encoding.sign ? x : y);
   } else {
     return (x < y ? x : y);
   }
@@ -52,11 +52,11 @@ static inline T fmax(T x, T y) {
     return y;
   } else if (bity.isNaN()) {
     return x;
-  } else if (bitx.sign != bity.sign) {
+  } else if (bitx.encoding.sign != bity.encoding.sign) {
     // To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and
     // y has 
diff erent signs and both are not NaNs, we return the number
     // with positive sign.
-    return (bitx.sign ? y : x);
+    return (bitx.encoding.sign ? y : x);
   } else {
     return (x > y ? x : y);
   }

diff  --git a/libc/utils/FPUtil/DivisionAndRemainderOperations.h b/libc/utils/FPUtil/DivisionAndRemainderOperations.h
index b4732c7c5230c..5a1c6566b28d5 100644
--- a/libc/utils/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/utils/FPUtil/DivisionAndRemainderOperations.h
@@ -43,12 +43,12 @@ static inline T remquo(T x, T y, int &q) {
     return x;
   }
 
-  bool resultSign = (xbits.sign == ybits.sign ? false : true);
+  bool resultSign = (xbits.encoding.sign == ybits.encoding.sign ? false : true);
 
   // Once we know the sign of the result, we can just operate on the absolute
   // values. The correct sign can be applied to the result after the result
   // is evaluated.
-  xbits.sign = ybits.sign = 0;
+  xbits.encoding.sign = ybits.encoding.sign = 0;
 
   NormalFloat<T> normalx(xbits), normaly(ybits);
   int exp = normalx.exponent - normaly.exponent;

diff  --git a/libc/utils/FPUtil/FPBits.h b/libc/utils/FPUtil/FPBits.h
index 02c0dc880579e..b2c1e578125f6 100644
--- a/libc/utils/FPUtil/FPBits.h
+++ b/libc/utils/FPUtil/FPBits.h
@@ -57,7 +57,7 @@ template <> struct FPUIntType<long double> { using Type = __uint128_t; };
 // floating numbers. On x86 platforms however, the 'long double' type maps to
 // an x87 floating point format. This format is an IEEE 754 extension format.
 // It is handled as an explicit specialization of this class.
-template <typename T> struct __attribute__((packed)) FPBits {
+template <typename T> union FPBits {
   static_assert(cpp::IsFloatingPointType<T>::Value,
                 "FPBits instantiated with invalid type.");
 
@@ -66,9 +66,18 @@ template <typename T> struct __attribute__((packed)) FPBits {
   // type is provided for such reinterpretations.
   using UIntType = typename FPUIntType<T>::Type;
 
-  UIntType mantissa : MantissaWidth<T>::value;
-  uint16_t exponent : ExponentWidth<T>::value;
-  uint8_t sign : 1;
+  struct __attribute__((packed)) {
+    UIntType mantissa : MantissaWidth<T>::value;
+    uint16_t exponent : ExponentWidth<T>::value;
+    uint8_t sign : 1;
+  } encoding;
+  UIntType integer;
+  T val;
+
+  static_assert(sizeof(encoding) == sizeof(UIntType),
+                "Encoding and integral representation have 
diff erent sizes.");
+  static_assert(sizeof(integer) == sizeof(UIntType),
+                "Integral representation and value type have 
diff erent sizes.");
 
   static constexpr int exponentBias = (1 << (ExponentWidth<T>::value - 1)) - 1;
   static constexpr int maxExponent = (1 << ExponentWidth<T>::value) - 1;
@@ -84,60 +93,56 @@ template <typename T> struct __attribute__((packed)) FPBits {
   // We don't want accidental type promotions/conversions so we require exact
   // type match.
   template <typename XType,
-            cpp::EnableIfType<cpp::IsSame<T, XType>::Value ||
-                                  (cpp::IsIntegral<XType>::Value &&
-                                   (sizeof(XType) == sizeof(UIntType))),
-                              int> = 0>
-  explicit FPBits(XType x) {
-    *this = *reinterpret_cast<FPBits<T> *>(&x);
-  }
+            cpp::EnableIfType<cpp::IsSame<T, XType>::Value, int> = 0>
+  explicit FPBits(XType x) : val(x) {}
 
-  operator T() { return *reinterpret_cast<T *>(this); }
+  template <typename XType,
+            cpp::EnableIfType<cpp::IsSame<XType, UIntType>::Value, int> = 0>
+  explicit FPBits(XType x) : integer(x) {}
 
-  int getExponent() const { return int(exponent) - exponentBias; }
+  FPBits() : integer(0) {}
 
-  bool isZero() const { return mantissa == 0 && exponent == 0; }
+  operator T() { return val; }
 
-  bool isInf() const { return mantissa == 0 && exponent == maxExponent; }
+  UIntType uintval() const { return integer; }
 
-  bool isNaN() const { return exponent == maxExponent && mantissa != 0; }
+  int getExponent() const { return int(encoding.exponent) - exponentBias; }
 
-  bool isInfOrNaN() const { return exponent == maxExponent; }
+  bool isZero() const {
+    return encoding.mantissa == 0 && encoding.exponent == 0;
+  }
 
-  // Methods below this are used by tests.
-  // The to and from integer bits converters are only used in tests. Hence,
-  // the potential software implementations of UIntType will not slow real
-  // code.
+  bool isInf() const {
+    return encoding.mantissa == 0 && encoding.exponent == maxExponent;
+  }
 
-  UIntType bitsAsUInt() const {
-    return *reinterpret_cast<const UIntType *>(this);
+  bool isNaN() const {
+    return encoding.exponent == maxExponent && encoding.mantissa != 0;
   }
 
-  static FPBits<T> zero() { return FPBits(T(0.0)); }
+  bool isInfOrNaN() const { return encoding.exponent == maxExponent; }
+
+  static FPBits<T> zero() { return FPBits(); }
 
   static FPBits<T> negZero() {
-    FPBits<T> bits(T(0.0));
-    bits.sign = 1;
-    return bits;
+    return FPBits(UIntType(1) << (sizeof(UIntType) * 8 - 1));
   }
 
   static FPBits<T> inf() {
-    FPBits<T> bits(T(0.0));
-    bits.exponent = maxExponent;
+    FPBits<T> bits;
+    bits.encoding.exponent = maxExponent;
     return bits;
   }
 
   static FPBits<T> negInf() {
-    FPBits<T> bits(T(0.0));
-    bits.exponent = maxExponent;
-    bits.sign = 1;
+    FPBits<T> bits = inf();
+    bits.encoding.sign = 1;
     return bits;
   }
 
   static T buildNaN(UIntType v) {
-    FPBits<T> bits(T(0.0));
-    bits.exponent = maxExponent;
-    bits.mantissa = v;
+    FPBits<T> bits = inf();
+    bits.encoding.mantissa = v;
     return bits;
   }
 };

diff  --git a/libc/utils/FPUtil/Hypot.h b/libc/utils/FPUtil/Hypot.h
index 6795f9dcb3ae0..3585304b8508f 100644
--- a/libc/utils/FPUtil/Hypot.h
+++ b/libc/utils/FPUtil/Hypot.h
@@ -139,26 +139,27 @@ static inline T hypot(T x, T y) {
   DUIntType a_mant_sq, b_mant_sq;
   bool sticky_bits;
 
-  if ((x_bits.exponent >= y_bits.exponent + MantissaWidth<T>::value + 2) ||
+  if ((x_bits.encoding.exponent >=
+       y_bits.encoding.exponent + MantissaWidth<T>::value + 2) ||
       (y == 0)) {
     return abs(x);
-  } else if ((y_bits.exponent >=
-              x_bits.exponent + MantissaWidth<T>::value + 2) ||
+  } else if ((y_bits.encoding.exponent >=
+              x_bits.encoding.exponent + MantissaWidth<T>::value + 2) ||
              (x == 0)) {
-    y_bits.sign = 0;
+    y_bits.encoding.sign = 0;
     return abs(y);
   }
 
   if (x >= y) {
-    a_exp = x_bits.exponent;
-    a_mant = x_bits.mantissa;
-    b_exp = y_bits.exponent;
-    b_mant = y_bits.mantissa;
+    a_exp = x_bits.encoding.exponent;
+    a_mant = x_bits.encoding.mantissa;
+    b_exp = y_bits.encoding.exponent;
+    b_mant = y_bits.encoding.mantissa;
   } else {
-    a_exp = y_bits.exponent;
-    a_mant = y_bits.mantissa;
-    b_exp = x_bits.exponent;
-    b_mant = x_bits.mantissa;
+    a_exp = y_bits.encoding.exponent;
+    a_mant = y_bits.encoding.mantissa;
+    b_exp = x_bits.encoding.exponent;
+    b_mant = x_bits.encoding.mantissa;
   }
 
   out_exp = a_exp;

diff  --git a/libc/utils/FPUtil/LongDoubleBitsX86.h b/libc/utils/FPUtil/LongDoubleBitsX86.h
index c05166021ec59..7fd025a2f5907 100644
--- a/libc/utils/FPUtil/LongDoubleBitsX86.h
+++ b/libc/utils/FPUtil/LongDoubleBitsX86.h
@@ -28,7 +28,7 @@ template <> struct Padding<4> { static constexpr unsigned value = 16; };
 // x86_64 padding.
 template <> struct Padding<8> { static constexpr unsigned value = 48; };
 
-template <> struct __attribute__((packed)) FPBits<long double> {
+template <> union FPBits<long double> {
   using UIntType = __uint128_t;
 
   static constexpr int exponentBias = 0x3FFF;
@@ -43,102 +43,97 @@ template <> struct __attribute__((packed)) FPBits<long double> {
       ((UIntType(maxExponent) - 1) << (MantissaWidth<long double>::value + 1)) |
       (UIntType(1) << MantissaWidth<long double>::value) | maxSubnormal;
 
-  UIntType mantissa : MantissaWidth<long double>::value;
-  uint8_t implicitBit : 1;
-  uint16_t exponent : ExponentWidth<long double>::value;
-  uint8_t sign : 1;
-  uint64_t padding : Padding<sizeof(uintptr_t)>::value;
+  struct __attribute__((packed)) {
+    UIntType mantissa : MantissaWidth<long double>::value;
+    uint8_t implicitBit : 1;
+    uint16_t exponent : ExponentWidth<long double>::value;
+    uint8_t sign : 1;
+    uint64_t padding : Padding<sizeof(uintptr_t)>::value;
+  } encoding;
+  UIntType integer;
+  long double val;
+
+  FPBits() : integer(0) {}
 
   template <typename XType,
             cpp::EnableIfType<cpp::IsSame<long double, XType>::Value, int> = 0>
-  explicit FPBits<long double>(XType x) {
-    *this = *reinterpret_cast<FPBits<long double> *>(&x);
-  }
+  explicit FPBits<long double>(XType x) : val(x) {}
+
+  template <typename XType,
+            cpp::EnableIfType<cpp::IsSame<XType, UIntType>::Value, int> = 0>
+  explicit FPBits(XType x) : integer(x) {}
+
+  operator long double() { return val; }
 
-  operator long double() { return *reinterpret_cast<long double *>(this); }
+  UIntType uintval() {
+    // We zero the padding bits as they can contain garbage.
+    static constexpr UIntType mask =
+        (UIntType(1) << (sizeof(long double) * 8 -
+                         Padding<sizeof(uintptr_t)>::value)) -
+        1;
+    return integer & mask;
+  }
 
   int getExponent() const {
-    if (exponent == 0)
+    if (encoding.exponent == 0)
       return int(1) - exponentBias;
-    return int(exponent) - exponentBias;
+    return int(encoding.exponent) - exponentBias;
   }
 
   bool isZero() const {
-    return exponent == 0 && mantissa == 0 && implicitBit == 0;
+    return encoding.exponent == 0 && encoding.mantissa == 0 &&
+           encoding.implicitBit == 0;
   }
 
   bool isInf() const {
-    return exponent == maxExponent && mantissa == 0 && implicitBit == 1;
+    return encoding.exponent == maxExponent && encoding.mantissa == 0 &&
+           encoding.implicitBit == 1;
   }
 
   bool isNaN() const {
-    if (exponent == maxExponent) {
-      return (implicitBit == 0) || mantissa != 0;
-    } else if (exponent != 0) {
-      return implicitBit == 0;
+    if (encoding.exponent == maxExponent) {
+      return (encoding.implicitBit == 0) || encoding.mantissa != 0;
+    } else if (encoding.exponent != 0) {
+      return encoding.implicitBit == 0;
     }
     return false;
   }
 
   bool isInfOrNaN() const {
-    return (exponent == maxExponent) || (exponent != 0 && implicitBit == 0);
+    return (encoding.exponent == maxExponent) ||
+           (encoding.exponent != 0 && encoding.implicitBit == 0);
   }
 
   // Methods below this are used by tests.
 
-  template <typename XType,
-            cpp::EnableIfType<cpp::IsSame<UIntType, XType>::Value, int> = 0>
-  explicit FPBits<long double>(XType x) {
-    // The last 4 bytes of v are ignored in case of i386.
-    *this = *reinterpret_cast<FPBits<long double> *>(&x);
-  }
-
-  UIntType bitsAsUInt() const {
-    // We cannot just return the bits as is as it will lead to reading
-    // out of bounds in case of i386. So, we first copy the wider value
-    // before returning the value. This makes the last 4 bytes are always
-    // zero in case i386.
-    UIntType result = UIntType(0);
-    *reinterpret_cast<FPBits<long double> *>(&result) = *this;
-
-    // Even though we zero out |result| before copying the long double value,
-    // there can be garbage bits in the padding. So, we zero the padding bits
-    // in |result|.
-    static constexpr UIntType mask =
-        (UIntType(1) << (sizeof(long double) * 8 -
-                         Padding<sizeof(uintptr_t)>::value)) -
-        1;
-    return result & mask;
-  }
-
   static FPBits<long double> zero() { return FPBits<long double>(0.0l); }
 
   static FPBits<long double> negZero() {
     FPBits<long double> bits(0.0l);
-    bits.sign = 1;
+    bits.encoding.sign = 1;
     return bits;
   }
 
   static FPBits<long double> inf() {
     FPBits<long double> bits(0.0l);
-    bits.exponent = maxExponent;
-    bits.implicitBit = 1;
+    bits.encoding.exponent = maxExponent;
+    bits.encoding.implicitBit = 1;
     return bits;
   }
 
   static FPBits<long double> negInf() {
     FPBits<long double> bits(0.0l);
-    bits.exponent = maxExponent;
-    bits.implicitBit = 1;
-    bits.sign = 1;
+    bits.encoding.exponent = maxExponent;
+    bits.encoding.implicitBit = 1;
+    bits.encoding.sign = 1;
     return bits;
   }
 
   static long double buildNaN(UIntType v) {
     FPBits<long double> bits(0.0l);
-    bits.exponent = maxExponent;
-    bits.implicitBit = 1;
-    bits.mantissa = v;
+    bits.encoding.exponent = maxExponent;
+    bits.encoding.implicitBit = 1;
+    bits.encoding.mantissa = v;
     return bits;
   }
 };

diff  --git a/libc/utils/FPUtil/ManipulationFunctions.h b/libc/utils/FPUtil/ManipulationFunctions.h
index f230a462ee4b7..ef8a3775df7bc 100644
--- a/libc/utils/FPUtil/ManipulationFunctions.h
+++ b/libc/utils/FPUtil/ManipulationFunctions.h
@@ -47,13 +47,13 @@ static inline T modf(T x, T &iptr) {
     return x;
   } else if (bits.isInf()) {
     iptr = x;
-    return bits.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
+    return bits.encoding.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
   } else {
     iptr = trunc(x);
     if (x == iptr) {
       // If x is already an integer value, then return zero with the right
       // sign.
-      return bits.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
+      return bits.encoding.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
     } else {
       return x - iptr;
     }
@@ -64,7 +64,7 @@ template <typename T,
           cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
 static inline T copysign(T x, T y) {
   FPBits<T> xbits(x);
-  xbits.sign = FPBits<T>(y).sign;
+  xbits.encoding.sign = FPBits<T>(y).encoding.sign;
   return xbits;
 }
 
@@ -131,11 +131,11 @@ static inline T ldexp(T x, int exp) {
   // calculating the limit.
   int expLimit = FPBits<T>::maxExponent + MantissaWidth<T>::value + 1;
   if (exp > expLimit)
-    return bits.sign ? FPBits<T>::negInf() : FPBits<T>::inf();
+    return bits.encoding.sign ? FPBits<T>::negInf() : FPBits<T>::inf();
 
   // Similarly on the negative side we return zero early if |exp| is too small.
   if (exp < -expLimit)
-    return bits.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
+    return bits.encoding.sign ? FPBits<T>::negZero() : FPBits<T>::zero();
 
   // For all other values, NormalFloat to T conversion handles it the right way.
   NormalFloat<T> normal(bits);
@@ -158,7 +158,7 @@ static inline T nextafter(T from, T to) {
     return to;
 
   using UIntType = typename FPBits<T>::UIntType;
-  auto intVal = fromBits.bitsAsUInt();
+  UIntType intVal = fromBits.uintval();
   UIntType signMask = (UIntType(1) << (sizeof(T) * 8 - 1));
   if (from != T(0.0)) {
     if ((from < to) == (from > T(0.0))) {
@@ -167,7 +167,7 @@ static inline T nextafter(T from, T to) {
       --intVal;
     }
   } else {
-    intVal = (toBits.bitsAsUInt() & signMask) + UIntType(1);
+    intVal = (UIntType(toBits) & signMask) + UIntType(1);
   }
 
   return *reinterpret_cast<T *>(&intVal);

diff  --git a/libc/utils/FPUtil/NearestIntegerOperations.h b/libc/utils/FPUtil/NearestIntegerOperations.h
index 004f269009d4f..7bb79bee377f6 100644
--- a/libc/utils/FPUtil/NearestIntegerOperations.h
+++ b/libc/utils/FPUtil/NearestIntegerOperations.h
@@ -43,14 +43,14 @@ static inline T trunc(T x) {
 
   // If the exponent is such that abs(x) is less than 1, then return 0.
   if (exponent <= -1) {
-    if (bits.sign)
+    if (bits.encoding.sign)
       return T(-0.0);
     else
       return T(0.0);
   }
 
   int trimSize = MantissaWidth<T>::value - exponent;
-  bits.mantissa = (bits.mantissa >> trimSize) << trimSize;
+  bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
   return bits;
 }
 
@@ -63,7 +63,7 @@ static inline T ceil(T x) {
   if (bits.isInfOrNaN() || bits.isZero())
     return x;
 
-  bool isNeg = bits.sign;
+  bool isNeg = bits.encoding.sign;
   int exponent = bits.getExponent();
 
   // If the exponent is greater than the most negative mantissa
@@ -79,7 +79,7 @@ static inline T ceil(T x) {
   }
 
   uint32_t trimSize = MantissaWidth<T>::value - exponent;
-  bits.mantissa = (bits.mantissa >> trimSize) << trimSize;
+  bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
   T truncValue = T(bits);
 
   // If x is already an integer, return it.
@@ -97,7 +97,7 @@ template <typename T,
           cpp::EnableIfType<cpp::IsFloatingPointType<T>::Value, int> = 0>
 static inline T floor(T x) {
   FPBits<T> bits(x);
-  if (bits.sign) {
+  if (bits.encoding.sign) {
     return -ceil(-x);
   } else {
     return trunc(x);
@@ -114,7 +114,7 @@ static inline T round(T x) {
   if (bits.isInfOrNaN() || bits.isZero())
     return x;
 
-  bool isNeg = bits.sign;
+  bool isNeg = bits.encoding.sign;
   int exponent = bits.getExponent();
 
   // If the exponent is greater than the most negative mantissa
@@ -139,8 +139,8 @@ static inline T round(T x) {
   }
 
   uint32_t trimSize = MantissaWidth<T>::value - exponent;
-  bool halfBitSet = bits.mantissa & (UIntType(1) << (trimSize - 1));
-  bits.mantissa = (bits.mantissa >> trimSize) << trimSize;
+  bool halfBitSet = bits.encoding.mantissa & (UIntType(1) << (trimSize - 1));
+  bits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
   T truncValue = T(bits);
 
   // If x is already an integer, return it.
@@ -166,7 +166,7 @@ static inline T roundUsingCurrentRoundingMode(T x) {
   if (bits.isInfOrNaN() || bits.isZero())
     return x;
 
-  bool isNeg = bits.sign;
+  bool isNeg = bits.encoding.sign;
   int exponent = bits.getExponent();
   int roundingMode = getRound();
 
@@ -184,7 +184,7 @@ static inline T roundUsingCurrentRoundingMode(T x) {
     case FE_TOWARDZERO:
       return isNeg ? T(-0.0) : T(0.0);
     case FE_TONEAREST:
-      if (exponent <= -2 || bits.mantissa == 0)
+      if (exponent <= -2 || bits.encoding.mantissa == 0)
         return isNeg ? T(-0.0) : T(0.0); // abs(x) <= 0.5
       else
         return isNeg ? T(-1.0) : T(1.0); // abs(x) > 0.5
@@ -195,19 +195,19 @@ static inline T roundUsingCurrentRoundingMode(T x) {
 
   uint32_t trimSize = MantissaWidth<T>::value - exponent;
   FPBits<T> newBits = bits;
-  newBits.mantissa = (bits.mantissa >> trimSize) << trimSize;
+  newBits.encoding.mantissa = (bits.encoding.mantissa >> trimSize) << trimSize;
   T truncValue = T(newBits);
 
   // If x is already an integer, return it.
   if (truncValue == x)
     return x;
 
-  UIntType trimValue = bits.mantissa & ((UIntType(1) << trimSize) - 1);
+  UIntType trimValue = bits.encoding.mantissa & ((UIntType(1) << trimSize) - 1);
   UIntType halfValue = (UIntType(1) << (trimSize - 1));
   // If exponent is 0, trimSize will be equal to the mantissa width, and
   // truncIsOdd` will not be correct. So, we handle it as a special case
   // below.
-  UIntType truncIsOdd = newBits.mantissa & (UIntType(1) << trimSize);
+  UIntType truncIsOdd = newBits.encoding.mantissa & (UIntType(1) << trimSize);
 
   switch (roundingMode) {
   case FE_DOWNWARD:
@@ -255,18 +255,18 @@ static inline I roundedFloatToSignedInteger(F x) {
 
   if (bits.isInfOrNaN()) {
     setDomainErrorAndRaiseInvalid();
-    return bits.sign ? IntegerMin : IntegerMax;
+    return bits.encoding.sign ? IntegerMin : IntegerMax;
   }
 
   int exponent = bits.getExponent();
   constexpr int exponentLimit = sizeof(I) * 8 - 1;
   if (exponent > exponentLimit) {
     setDomainErrorAndRaiseInvalid();
-    return bits.sign ? IntegerMin : IntegerMax;
+    return bits.encoding.sign ? IntegerMin : IntegerMax;
   } else if (exponent == exponentLimit) {
-    if (bits.sign == 0 || bits.mantissa != 0) {
+    if (bits.encoding.sign == 0 || bits.encoding.mantissa != 0) {
       setDomainErrorAndRaiseInvalid();
-      return bits.sign ? IntegerMin : IntegerMax;
+      return bits.encoding.sign ? IntegerMin : IntegerMax;
     }
     // If the control reaches here, then it means that the rounded
     // value is the most negative number for the signed integer type I.

diff  --git a/libc/utils/FPUtil/NextAfterLongDoubleX86.h b/libc/utils/FPUtil/NextAfterLongDoubleX86.h
index e1555b795e160..6ae6dfb9f29f7 100644
--- a/libc/utils/FPUtil/NextAfterLongDoubleX86.h
+++ b/libc/utils/FPUtil/NextAfterLongDoubleX86.h
@@ -30,15 +30,15 @@ static inline long double nextafter(long double from, long double to) {
     return to;
 
   // Convert pseudo subnormal number to normal number.
-  if (fromBits.implicitBit == 1 && fromBits.exponent == 0) {
-    fromBits.exponent = 1;
+  if (fromBits.encoding.implicitBit == 1 && fromBits.encoding.exponent == 0) {
+    fromBits.encoding.exponent = 1;
   }
 
   using UIntType = FPBits::UIntType;
   constexpr UIntType signVal = (UIntType(1) << 79);
   constexpr UIntType mantissaMask =
       (UIntType(1) << MantissaWidth<long double>::value) - 1;
-  auto intVal = fromBits.bitsAsUInt();
+  UIntType intVal = fromBits.uintval();
   if (from < 0.0l) {
     if (from > to) {
       if (intVal == (signVal + FPBits::maxSubnormal)) {
@@ -46,11 +46,11 @@ static inline long double nextafter(long double from, long double to) {
         // dealing with the implicit bit.
         intVal = signVal + FPBits::minNormal;
       } else if ((intVal & mantissaMask) == mantissaMask) {
-        fromBits.mantissa = 0;
+        fromBits.encoding.mantissa = 0;
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
         // it will never overflow "beyond" infinity.
-        ++fromBits.exponent;
+        ++fromBits.encoding.exponent;
         return fromBits;
       } else {
         ++intVal;
@@ -61,10 +61,10 @@ static inline long double nextafter(long double from, long double to) {
         // dealing with the implicit bit.
         intVal = signVal + FPBits::maxSubnormal;
       } else if ((intVal & mantissaMask) == 0) {
-        fromBits.mantissa = mantissaMask;
+        fromBits.encoding.mantissa = mantissaMask;
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
-        --fromBits.exponent;
+        --fromBits.encoding.exponent;
         return fromBits;
       } else {
         --intVal;
@@ -80,10 +80,10 @@ static inline long double nextafter(long double from, long double to) {
       if (intVal == FPBits::minNormal) {
         intVal = FPBits::maxSubnormal;
       } else if ((intVal & mantissaMask) == 0) {
-        fromBits.mantissa = mantissaMask;
+        fromBits.encoding.mantissa = mantissaMask;
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
-        --fromBits.exponent;
+        --fromBits.encoding.exponent;
         return fromBits;
       } else {
         --intVal;
@@ -92,11 +92,11 @@ static inline long double nextafter(long double from, long double to) {
       if (intVal == FPBits::maxSubnormal) {
         intVal = FPBits::minNormal;
       } else if ((intVal & mantissaMask) == mantissaMask) {
-        fromBits.mantissa = 0;
+        fromBits.encoding.mantissa = 0;
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
         // it will never overflow "beyond" infinity.
-        ++fromBits.exponent;
+        ++fromBits.encoding.exponent;
         return fromBits;
       } else {
         ++intVal;

diff  --git a/libc/utils/FPUtil/NormalFloat.h b/libc/utils/FPUtil/NormalFloat.h
index f71951941d81b..79e3d3448f52f 100644
--- a/libc/utils/FPUtil/NormalFloat.h
+++ b/libc/utils/FPUtil/NormalFloat.h
@@ -97,7 +97,7 @@ template <typename T> struct NormalFloat {
     }
 
     FPBits<T> result(T(0.0));
-    result.sign = sign;
+    result.encoding.sign = sign;
 
     constexpr int subnormalExponent = -FPBits<T>::exponentBias + 1;
     if (exponent < subnormalExponent) {
@@ -110,36 +110,36 @@ template <typename T> struct NormalFloat {
         const UIntType shiftOutMask = (UIntType(1) << shift) - 1;
         const UIntType shiftOutValue = mantissa & shiftOutMask;
         const UIntType halfwayValue = UIntType(1) << (shift - 1);
-        result.exponent = 0;
-        result.mantissa = mantissa >> shift;
-        UIntType newMantissa = result.mantissa;
+        result.encoding.exponent = 0;
+        result.encoding.mantissa = mantissa >> shift;
+        UIntType newMantissa = result.encoding.mantissa;
         if (shiftOutValue > halfwayValue) {
           newMantissa += 1;
         } else if (shiftOutValue == halfwayValue) {
           // Round to even.
-          if (result.mantissa & 0x1)
+          if (result.encoding.mantissa & 0x1)
             newMantissa += 1;
         }
-        result.mantissa = newMantissa;
+        result.encoding.mantissa = newMantissa;
         // Adding 1 to mantissa can lead to overflow. This can only happen if
         // mantissa was all ones (0b111..11). For such a case, we will carry
         // the overflow into the exponent.
         if (newMantissa == one)
-          result.exponent = 1;
+          result.encoding.exponent = 1;
         return result;
       } else {
         return result;
       }
     }
 
-    result.exponent = exponent + FPBits<T>::exponentBias;
-    result.mantissa = mantissa;
+    result.encoding.exponent = exponent + FPBits<T>::exponentBias;
+    result.encoding.mantissa = mantissa;
     return result;
   }
 
 private:
   void initFromBits(FPBits<T> bits) {
-    sign = bits.sign;
+    sign = bits.encoding.sign;
 
     if (bits.isInfOrNaN() || bits.isZero()) {
       // Ignore special bit patterns. Implementations deal with them separately
@@ -150,13 +150,13 @@ template <typename T> struct NormalFloat {
     }
 
     // Normalize subnormal numbers.
-    if (bits.exponent == 0) {
-      unsigned shift = evaluateNormalizationShift(bits.mantissa);
-      mantissa = UIntType(bits.mantissa) << shift;
+    if (bits.encoding.exponent == 0) {
+      unsigned shift = evaluateNormalizationShift(bits.encoding.mantissa);
+      mantissa = UIntType(bits.encoding.mantissa) << shift;
       exponent = 1 - FPBits<T>::exponentBias - shift;
     } else {
-      exponent = bits.exponent - FPBits<T>::exponentBias;
-      mantissa = one | bits.mantissa;
+      exponent = bits.encoding.exponent - FPBits<T>::exponentBias;
+      mantissa = one | bits.encoding.mantissa;
     }
   }
 
@@ -172,7 +172,7 @@ template <typename T> struct NormalFloat {
 #if defined(__x86_64__) || defined(__i386__)
 template <>
 inline void NormalFloat<long double>::initFromBits(FPBits<long double> bits) {
-  sign = bits.sign;
+  sign = bits.encoding.sign;
 
   if (bits.isInfOrNaN() || bits.isZero()) {
     // Ignore special bit patterns. Implementations deal with them separately
@@ -182,24 +182,25 @@ inline void NormalFloat<long double>::initFromBits(FPBits<long double> bits) {
     return;
   }
 
-  if (bits.exponent == 0) {
-    if (bits.implicitBit == 0) {
+  if (bits.encoding.exponent == 0) {
+    if (bits.encoding.implicitBit == 0) {
       // Since we ignore zero value, the mantissa in this case is non-zero.
-      int normalizationShift = evaluateNormalizationShift(bits.mantissa);
+      int normalizationShift =
+          evaluateNormalizationShift(bits.encoding.mantissa);
       exponent = -16382 - normalizationShift;
-      mantissa = (bits.mantissa << normalizationShift);
+      mantissa = (bits.encoding.mantissa << normalizationShift);
     } else {
       exponent = -16382;
-      mantissa = one | bits.mantissa;
+      mantissa = one | bits.encoding.mantissa;
     }
   } else {
-    if (bits.implicitBit == 0) {
+    if (bits.encoding.implicitBit == 0) {
       // Invalid number so just store 0 similar to a NaN.
       exponent = 0;
       mantissa = 0;
     } else {
-      exponent = bits.exponent - 16383;
-      mantissa = one | bits.mantissa;
+      exponent = bits.encoding.exponent - 16383;
+      mantissa = one | bits.encoding.mantissa;
     }
   }
 }
@@ -213,7 +214,7 @@ template <> inline NormalFloat<long double>::operator long double() const {
   }
 
   FPBits<long double> result(0.0l);
-  result.sign = sign;
+  result.encoding.sign = sign;
 
   constexpr int subnormalExponent = -FPBits<long double>::exponentBias + 1;
   if (exponent < subnormalExponent) {
@@ -224,25 +225,25 @@ template <> inline NormalFloat<long double>::operator long double() const {
       const UIntType shiftOutMask = (UIntType(1) << shift) - 1;
       const UIntType shiftOutValue = mantissa & shiftOutMask;
       const UIntType halfwayValue = UIntType(1) << (shift - 1);
-      result.exponent = 0;
-      result.mantissa = mantissa >> shift;
-      UIntType newMantissa = result.mantissa;
+      result.encoding.exponent = 0;
+      result.encoding.mantissa = mantissa >> shift;
+      UIntType newMantissa = result.encoding.mantissa;
       if (shiftOutValue > halfwayValue) {
         newMantissa += 1;
       } else if (shiftOutValue == halfwayValue) {
         // Round to even.
-        if (result.mantissa & 0x1)
+        if (result.encoding.mantissa & 0x1)
           newMantissa += 1;
       }
-      result.mantissa = newMantissa;
+      result.encoding.mantissa = newMantissa;
       // Adding 1 to mantissa can lead to overflow. This can only happen if
       // mantissa was all ones (0b111..11). For such a case, we will carry
       // the overflow into the exponent and set the implicit bit to 1.
       if (newMantissa == one) {
-        result.exponent = 1;
-        result.implicitBit = 1;
+        result.encoding.exponent = 1;
+        result.encoding.implicitBit = 1;
       } else {
-        result.implicitBit = 0;
+        result.encoding.implicitBit = 0;
       }
       return result;
     } else {
@@ -250,9 +251,9 @@ template <> inline NormalFloat<long double>::operator long double() const {
     }
   }
 
-  result.exponent = biasedExponent;
-  result.mantissa = mantissa;
-  result.implicitBit = 1;
+  result.encoding.exponent = biasedExponent;
+  result.encoding.mantissa = mantissa;
+  result.encoding.implicitBit = 1;
   return result;
 }
 #endif

diff  --git a/libc/utils/FPUtil/Sqrt.h b/libc/utils/FPUtil/Sqrt.h
index a12cc42fa3408..097818ca03139 100644
--- a/libc/utils/FPUtil/Sqrt.h
+++ b/libc/utils/FPUtil/Sqrt.h
@@ -96,7 +96,7 @@ static inline T sqrt(T x) {
   FPBits<T> bits(x);
 
   if (bits.isInfOrNaN()) {
-    if (bits.sign && (bits.mantissa == 0)) {
+    if (bits.encoding.sign && (bits.encoding.mantissa == 0)) {
       // sqrt(-Inf) = NaN
       return FPBits<T>::buildNaN(One >> 1);
     } else {
@@ -108,15 +108,15 @@ static inline T sqrt(T x) {
     // sqrt(+0) = +0
     // sqrt(-0) = -0
     return x;
-  } else if (bits.sign) {
+  } else if (bits.encoding.sign) {
     // sqrt( negative numbers ) = NaN
     return FPBits<T>::buildNaN(One >> 1);
   } else {
     int xExp = bits.getExponent();
-    UIntType xMant = bits.mantissa;
+    UIntType xMant = bits.encoding.mantissa;
 
     // Step 1a: Normalize denormal input and append hiddent bit to the mantissa
-    if (bits.exponent == 0) {
+    if (bits.encoding.exponent == 0) {
       ++xExp; // let xExp be the correct exponent of One bit.
       internal::normalize<T>(xExp, xMant);
     } else {

diff  --git a/libc/utils/FPUtil/SqrtLongDoubleX86.h b/libc/utils/FPUtil/SqrtLongDoubleX86.h
index df80d7d932bac..8ea4ea5a9c470 100644
--- a/libc/utils/FPUtil/SqrtLongDoubleX86.h
+++ b/libc/utils/FPUtil/SqrtLongDoubleX86.h
@@ -51,7 +51,7 @@ template <> inline long double sqrt<long double, 0>(long double x) {
   FPBits<long double> bits(x);
 
   if (bits.isInfOrNaN()) {
-    if (bits.sign && (bits.mantissa == 0)) {
+    if (bits.encoding.sign && (bits.encoding.mantissa == 0)) {
       // sqrt(-Inf) = NaN
       return FPBits<long double>::buildNaN(One >> 1);
     } else {
@@ -63,17 +63,17 @@ template <> inline long double sqrt<long double, 0>(long double x) {
     // sqrt(+0) = +0
     // sqrt(-0) = -0
     return x;
-  } else if (bits.sign) {
+  } else if (bits.encoding.sign) {
     // sqrt( negative numbers ) = NaN
     return FPBits<long double>::buildNaN(One >> 1);
   } else {
     int xExp = bits.getExponent();
-    UIntType xMant = bits.mantissa;
+    UIntType xMant = bits.encoding.mantissa;
 
     // Step 1a: Normalize denormal input
-    if (bits.implicitBit) {
+    if (bits.encoding.implicitBit) {
       xMant |= One;
-    } else if (bits.exponent == 0) {
+    } else if (bits.encoding.exponent == 0) {
       internal::normalize<long double>(xExp, xMant);
     }
 
@@ -129,9 +129,9 @@ template <> inline long double sqrt<long double, 0>(long double x) {
 
     // Extract output
     FPBits<long double> out(0.0L);
-    out.exponent = xExp;
-    out.implicitBit = 1;
-    out.mantissa = (y & (One - 1));
+    out.encoding.exponent = xExp;
+    out.encoding.implicitBit = 1;
+    out.encoding.mantissa = (y & (One - 1));
 
     return out;
   }

diff  --git a/libc/utils/FPUtil/TestHelpers.cpp b/libc/utils/FPUtil/TestHelpers.cpp
index 71566ef99cf18..cfee2bd0e743c 100644
--- a/libc/utils/FPUtil/TestHelpers.cpp
+++ b/libc/utils/FPUtil/TestHelpers.cpp
@@ -40,7 +40,7 @@ describeValue(const char *label, ValType value,
   if (bits.isNaN()) {
     stream << "(NaN)";
   } else if (bits.isInf()) {
-    if (bits.sign)
+    if (bits.encoding.sign)
       stream << "(-Infinity)";
     else
       stream << "(+Infinity)";
@@ -50,12 +50,13 @@ describeValue(const char *label, ValType value,
     constexpr int mantissaWidthInHex =
         (fputil::MantissaWidth<ValType>::value - 1) / 4 + 1;
 
-    stream << "Sign: " << (bits.sign ? '1' : '0') << ", "
+    stream << "Sign: " << (bits.encoding.sign ? '1' : '0') << ", "
            << "Exponent: 0x"
-           << uintToHex<uint16_t>(bits.exponent, exponentWidthInHex) << ", "
+           << uintToHex<uint16_t>(bits.encoding.exponent, exponentWidthInHex)
+           << ", "
            << "Mantissa: 0x"
            << uintToHex<typename fputil::FPBits<ValType>::UIntType>(
-                  bits.mantissa, mantissaWidthInHex);
+                  bits.encoding.mantissa, mantissaWidthInHex);
   }
 
   stream << '\n';

diff  --git a/libc/utils/FPUtil/TestHelpers.h b/libc/utils/FPUtil/TestHelpers.h
index 48abed85f2762..c55f226cd9d72 100644
--- a/libc/utils/FPUtil/TestHelpers.h
+++ b/libc/utils/FPUtil/TestHelpers.h
@@ -41,13 +41,13 @@ class FPMatcher : public __llvm_libc::testing::Matcher<T> {
     fputil::FPBits<T> actualBits(actual), expectedBits(expected);
     if (Condition == __llvm_libc::testing::Cond_EQ)
       return (actualBits.isNaN() && expectedBits.isNaN()) ||
-             (actualBits.bitsAsUInt() == expectedBits.bitsAsUInt());
+             (actualBits.uintval() == expectedBits.uintval());
 
     // If condition == Cond_NE.
     if (actualBits.isNaN())
       return !expectedBits.isNaN();
     return expectedBits.isNaN() ||
-           (actualBits.bitsAsUInt() != expectedBits.bitsAsUInt());
+           (actualBits.uintval() != expectedBits.uintval());
   }
 
   void explainError(testutils::StreamWrapper &stream) override {

diff  --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index 314bece8df55e..7faf75ccde593 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -264,12 +264,12 @@ class MPFRNumber {
     mpfr_abs(mpfrInput.value, mpfrInput.value, MPFR_RNDN);
 
     // get eps(input)
-    int epsExponent = bits.exponent - fputil::FPBits<T>::exponentBias -
+    int epsExponent = bits.encoding.exponent - fputil::FPBits<T>::exponentBias -
                       fputil::MantissaWidth<T>::value;
-    if (bits.exponent == 0) {
+    if (bits.encoding.exponent == 0) {
       // correcting denormal exponent
       ++epsExponent;
-    } else if ((bits.mantissa == 0) && (bits.exponent > 1) &&
+    } else if ((bits.encoding.mantissa == 0) && (bits.encoding.exponent > 1) &&
                mpfr_less_p(value, mpfrInput.value)) {
       // when the input is exactly 2^n, distance (epsilon) between the input
       // and the next floating point number is 
diff erent from the distance to
@@ -567,7 +567,7 @@ bool compareUnaryOperationSingleOutput(Operation op, T input, T libcResult,
   // is rounded to the nearest even.
   MPFRNumber mpfrResult = unaryOperation(op, input);
   double ulp = mpfrResult.ulp(libcResult);
-  bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
+  bool bitsAreEven = ((FPBits<T>(libcResult).uintval() & 1) == 0);
   return (ulp < ulpError) ||
          ((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
 }
@@ -592,7 +592,7 @@ bool compareUnaryOperationTwoOutputs(Operation op, T input,
   if (mpfrIntResult != libcResult.i)
     return false;
 
-  bool bitsAreEven = ((FPBits<T>(libcResult.f).bitsAsUInt() & 1) == 0);
+  bool bitsAreEven = ((FPBits<T>(libcResult.f).uintval() & 1) == 0);
   return (ulp < ulpError) ||
          ((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
 }
@@ -624,7 +624,7 @@ bool compareBinaryOperationTwoOutputs(Operation op, const BinaryInput<T> &input,
     }
   }
 
-  bool bitsAreEven = ((FPBits<T>(libcResult.f).bitsAsUInt() & 1) == 0);
+  bool bitsAreEven = ((FPBits<T>(libcResult.f).uintval() & 1) == 0);
   return (ulp < ulpError) ||
          ((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
 }
@@ -645,7 +645,7 @@ bool compareBinaryOperationOneOutput(Operation op, const BinaryInput<T> &input,
   MPFRNumber mpfrResult = binaryOperationOneOutput(op, input.x, input.y);
   double ulp = mpfrResult.ulp(libcResult);
 
-  bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
+  bool bitsAreEven = ((FPBits<T>(libcResult).uintval() & 1) == 0);
   return (ulp < ulpError) ||
          ((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
 }
@@ -667,7 +667,7 @@ bool compareTernaryOperationOneOutput(Operation op,
       ternaryOperationOneOutput(op, input.x, input.y, input.z);
   double ulp = mpfrResult.ulp(libcResult);
 
-  bool bitsAreEven = ((FPBits<T>(libcResult).bitsAsUInt() & 1) == 0);
+  bool bitsAreEven = ((FPBits<T>(libcResult).uintval() & 1) == 0);
   return (ulp < ulpError) ||
          ((ulp == ulpError) && ((ulp != 0.5) || bitsAreEven));
 }


        


More information about the libc-commits mailing list