[libc-commits] [libc] [libc] `FPRep` builders return `FPRep` instead of raw `StorageType` (PR #78588)

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Thu Jan 18 06:43:18 PST 2024


https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/78588

None

>From 49ba96c8aa51fb56a5bf96a1e97fef48bcc42f09 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 18 Jan 2024 14:42:54 +0000
Subject: [PATCH] [libc] `FPRep` builders return `FPRep` instead of raw
 `StorageType`

---
 libc/src/__support/FPUtil/FPBits.h            |  68 ++++----
 .../test/src/__support/FPUtil/fpbits_test.cpp | 163 +++++++++---------
 2 files changed, 120 insertions(+), 111 deletions(-)

diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 3ee6289b749648..5df49350e3744e 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -332,7 +332,10 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
       mask_trailing_ones<StorageType, FRACTION_LEN>();
 
   // The floating point number representation as an unsigned integer.
-  StorageType bits = 0;
+  StorageType bits;
+
+  LIBC_INLINE constexpr FPRepBase() : bits(0) {}
+  LIBC_INLINE constexpr FPRepBase(StorageType value) : bits(value) {}
 
 public:
   LIBC_INLINE constexpr Sign sign() const {
@@ -418,6 +421,7 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
   using UP::exp_bits;
   using UP::exp_sig_bits;
   using UP::sig_bits;
+  using UP::UP;
 
 public:
   LIBC_INLINE constexpr bool is_nan() const {
@@ -450,37 +454,35 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
     return is_finite() && !is_subnormal();
   }
 
-  LIBC_INLINE static constexpr StorageType zero(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep zero(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType one(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep one(Sign sign = Sign::POS) {
     return encode(sign, Exponent::ZERO(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType
-  min_subnormal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep min_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::LSB());
   }
-  LIBC_INLINE static constexpr StorageType
-  max_subnormal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep max_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(),
                   Significand::BITS_ALL_ONES());
   }
-  LIBC_INLINE static constexpr StorageType min_normal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep min_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MIN(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType max_normal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep max_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MAX(), Significand::BITS_ALL_ONES());
   }
-  LIBC_INLINE static constexpr StorageType inf(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep inf(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType build_nan(Sign sign = Sign::POS,
-                                                     StorageType v = 0) {
+  LIBC_INLINE static constexpr FPRep build_nan(Sign sign = Sign::POS,
+                                               StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   (v ? Significand(v) : (Significand::MSB() >> 1)));
   }
-  LIBC_INLINE static constexpr StorageType
-  build_quiet_nan(Sign sign = Sign::POS, StorageType v = 0) {
+  LIBC_INLINE static constexpr FPRep build_quiet_nan(Sign sign = Sign::POS,
+                                                     StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   Significand::MSB() | Significand(v));
   }
@@ -507,6 +509,7 @@ struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
   using typename UP::BiasedExponent;
   using typename UP::Significand;
   using UP::encode;
+  using UP::UP;
 
 public:
   // The x86 80 bit float represents the leading digit of the mantissa
@@ -570,38 +573,36 @@ struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
     return get_implicit_bit();
   }
 
-  LIBC_INLINE static constexpr StorageType zero(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep zero(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO());
   }
-  LIBC_INLINE static constexpr StorageType one(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep one(Sign sign = Sign::POS) {
     return encode(sign, Exponent::ZERO(), Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType
-  min_subnormal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep min_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(), Significand::LSB());
   }
-  LIBC_INLINE static constexpr StorageType
-  max_subnormal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep max_subnormal(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ZEROES(),
                   Significand::BITS_ALL_ONES() ^ Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType min_normal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep min_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MIN(), Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType max_normal(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep max_normal(Sign sign = Sign::POS) {
     return encode(sign, Exponent::MAX(), Significand::BITS_ALL_ONES());
   }
-  LIBC_INLINE static constexpr StorageType inf(Sign sign = Sign::POS) {
+  LIBC_INLINE static constexpr FPRep inf(Sign sign = Sign::POS) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(), Significand::MSB());
   }
-  LIBC_INLINE static constexpr StorageType build_nan(Sign sign = Sign::POS,
-                                                     StorageType v = 0) {
+  LIBC_INLINE static constexpr FPRep build_nan(Sign sign = Sign::POS,
+                                               StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   Significand::MSB() |
                       (v ? Significand(v) : (Significand::MSB() >> 2)));
   }
-  LIBC_INLINE static constexpr StorageType
-  build_quiet_nan(Sign sign = Sign::POS, StorageType v = 0) {
+  LIBC_INLINE static constexpr FPRep build_quiet_nan(Sign sign = Sign::POS,
+                                                     StorageType v = 0) {
     return encode(sign, BiasedExponent::BITS_ALL_ONES(),
                   Significand::MSB() | (Significand::MSB() >> 1) |
                       Significand(v));
@@ -671,14 +672,15 @@ template <typename T> struct FPBits : public internal::FPRep<get_fp_type<T>()> {
 
   using UP::bits;
   using UP::EXP_LEN;
-  using UP::UP;
 
   // Constants.
   static constexpr int MAX_BIASED_EXPONENT = (1 << EXP_LEN) - 1;
-  static constexpr StorageType MIN_NORMAL = UP::min_normal(Sign::POS);
-  static constexpr StorageType MAX_NORMAL = UP::max_normal(Sign::POS);
-  static constexpr StorageType MIN_SUBNORMAL = UP::min_subnormal(Sign::POS);
-  static constexpr StorageType MAX_SUBNORMAL = UP::max_subnormal(Sign::POS);
+  static constexpr StorageType MIN_NORMAL = UP::min_normal(Sign::POS).uintval();
+  static constexpr StorageType MAX_NORMAL = UP::max_normal(Sign::POS).uintval();
+  static constexpr StorageType MIN_SUBNORMAL =
+      UP::min_subnormal(Sign::POS).uintval();
+  static constexpr StorageType MAX_SUBNORMAL =
+      UP::max_subnormal(Sign::POS).uintval();
 
   // Constructors.
   LIBC_INLINE constexpr FPBits() = default;
@@ -687,6 +689,8 @@ template <typename T> struct FPBits : public internal::FPRep<get_fp_type<T>()> {
     using Unqual = typename cpp::remove_cv_t<XType>;
     if constexpr (cpp::is_same_v<Unqual, T>) {
       bits = cpp::bit_cast<StorageType>(x);
+    } else if constexpr (cpp::is_same_v<Unqual, UP>) {
+      bits = x.uintval();
     } else if constexpr (cpp::is_same_v<Unqual, StorageType>) {
       bits = x;
     } else {
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index f0b155085dabf5..8f062da6bf5963 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -13,21 +13,23 @@
 using LIBC_NAMESPACE::fputil::FPBits;
 using LIBC_NAMESPACE::fputil::Sign;
 
+#define EXPECT_REP_EQ(A, REP) EXPECT_EQ(A, REP.uintval())
+
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary16) {
   using LIBC_NAMESPACE::fputil::FPType;
   using LIBC_NAMESPACE::fputil::internal::FPRep;
   using Rep = FPRep<FPType::IEEE754_Binary16>;
   using u16 = uint16_t;
 
-  EXPECT_EQ(u16(0b0'00000'0000000000), Rep::zero());
-  EXPECT_EQ(u16(0b0'01111'0000000000), Rep::one());
-  EXPECT_EQ(u16(0b0'00000'0000000001), Rep::min_subnormal());
-  EXPECT_EQ(u16(0b0'00000'1111111111), Rep::max_subnormal());
-  EXPECT_EQ(u16(0b0'00001'0000000000), Rep::min_normal());
-  EXPECT_EQ(u16(0b0'11110'1111111111), Rep::max_normal());
-  EXPECT_EQ(u16(0b0'11111'0000000000), Rep::inf());
-  EXPECT_EQ(u16(0b0'11111'0100000000), Rep::build_nan());
-  EXPECT_EQ(u16(0b0'11111'1000000000), Rep::build_quiet_nan());
+  EXPECT_REP_EQ(u16(0b0'00000'0000000000), Rep::zero());
+  EXPECT_REP_EQ(u16(0b0'01111'0000000000), Rep::one());
+  EXPECT_REP_EQ(u16(0b0'00000'0000000001), Rep::min_subnormal());
+  EXPECT_REP_EQ(u16(0b0'00000'1111111111), Rep::max_subnormal());
+  EXPECT_REP_EQ(u16(0b0'00001'0000000000), Rep::min_normal());
+  EXPECT_REP_EQ(u16(0b0'11110'1111111111), Rep::max_normal());
+  EXPECT_REP_EQ(u16(0b0'11111'0000000000), Rep::inf());
+  EXPECT_REP_EQ(u16(0b0'11111'0100000000), Rep::build_nan());
+  EXPECT_REP_EQ(u16(0b0'11111'1000000000), Rep::build_quiet_nan());
 }
 
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary32) {
@@ -36,15 +38,18 @@ TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary32) {
   using Rep = FPRep<FPType::IEEE754_Binary32>;
   using u32 = uint32_t;
 
-  EXPECT_EQ(u32(0b0'00000000'00000000000000000000000), Rep::zero());
-  EXPECT_EQ(u32(0b0'01111111'00000000000000000000000), Rep::one());
-  EXPECT_EQ(u32(0b0'00000000'00000000000000000000001), Rep::min_subnormal());
-  EXPECT_EQ(u32(0b0'00000000'11111111111111111111111), Rep::max_subnormal());
-  EXPECT_EQ(u32(0b0'00000001'00000000000000000000000), Rep::min_normal());
-  EXPECT_EQ(u32(0b0'11111110'11111111111111111111111), Rep::max_normal());
-  EXPECT_EQ(u32(0b0'11111111'00000000000000000000000), Rep::inf());
-  EXPECT_EQ(u32(0b0'11111111'01000000000000000000000), Rep::build_nan());
-  EXPECT_EQ(u32(0b0'11111111'10000000000000000000000), Rep::build_quiet_nan());
+  EXPECT_REP_EQ(u32(0b0'00000000'00000000000000000000000), Rep::zero());
+  EXPECT_REP_EQ(u32(0b0'01111111'00000000000000000000000), Rep::one());
+  EXPECT_REP_EQ(u32(0b0'00000000'00000000000000000000001),
+                Rep::min_subnormal());
+  EXPECT_REP_EQ(u32(0b0'00000000'11111111111111111111111),
+                Rep::max_subnormal());
+  EXPECT_REP_EQ(u32(0b0'00000001'00000000000000000000000), Rep::min_normal());
+  EXPECT_REP_EQ(u32(0b0'11111110'11111111111111111111111), Rep::max_normal());
+  EXPECT_REP_EQ(u32(0b0'11111111'00000000000000000000000), Rep::inf());
+  EXPECT_REP_EQ(u32(0b0'11111111'01000000000000000000000), Rep::build_nan());
+  EXPECT_REP_EQ(u32(0b0'11111111'10000000000000000000000),
+                Rep::build_quiet_nan());
 }
 
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary64) {
@@ -53,31 +58,31 @@ TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary64) {
   using Rep = FPRep<FPType::IEEE754_Binary64>;
   using u64 = uint64_t;
 
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'00000000000'0000000000000000000000000000000000000000000000000000),
       Rep::zero());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'01111111111'0000000000000000000000000000000000000000000000000000),
       Rep::one());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'00000000000'0000000000000000000000000000000000000000000000000001),
       Rep::min_subnormal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'00000000000'1111111111111111111111111111111111111111111111111111),
       Rep::max_subnormal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'00000000001'0000000000000000000000000000000000000000000000000000),
       Rep::min_normal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'11111111110'1111111111111111111111111111111111111111111111111111),
       Rep::max_normal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'11111111111'0000000000000000000000000000000000000000000000000000),
       Rep::inf());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'11111111111'0100000000000000000000000000000000000000000000000000),
       Rep::build_nan());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u64(0b0'11111111111'1000000000000000000000000000000000000000000000000000),
       Rep::build_quiet_nan());
 }
@@ -90,44 +95,87 @@ static constexpr UInt128 u128(uint64_t hi, uint64_t lo) {
 #endif
 }
 
+TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary128) {
+  using LIBC_NAMESPACE::fputil::FPType;
+  using LIBC_NAMESPACE::fputil::internal::FPRep;
+  using Rep = FPRep<FPType::IEEE754_Binary128>;
+
+  EXPECT_REP_EQ(
+      u128(0b0'000000000000000'000000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000000),
+      Rep::zero());
+  EXPECT_REP_EQ(
+      u128(0b0'011111111111111'000000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000000),
+      Rep::one());
+  EXPECT_REP_EQ(
+      u128(0b0'000000000000000'000000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000001),
+      Rep::min_subnormal());
+  EXPECT_REP_EQ(
+      u128(0b0'000000000000000'111111111111111111111111111111111111111111111111,
+           0b1111111111111111111111111111111111111111111111111111111111111111),
+      Rep::max_subnormal());
+  EXPECT_REP_EQ(
+      u128(0b0'000000000000001'000000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000000),
+      Rep::min_normal());
+  EXPECT_REP_EQ(
+      u128(0b0'111111111111110'111111111111111111111111111111111111111111111111,
+           0b1111111111111111111111111111111111111111111111111111111111111111),
+      Rep::max_normal());
+  EXPECT_REP_EQ(
+      u128(0b0'111111111111111'000000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000000),
+      Rep::inf());
+  EXPECT_REP_EQ(
+      u128(0b0'111111111111111'010000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000000),
+      Rep::build_nan());
+  EXPECT_REP_EQ(
+      u128(0b0'111111111111111'100000000000000000000000000000000000000000000000,
+           0b0000000000000000000000000000000000000000000000000000000000000000),
+      Rep::build_quiet_nan());
+}
+
 TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) {
   using LIBC_NAMESPACE::fputil::FPType;
   using LIBC_NAMESPACE::fputil::internal::FPRep;
   using Rep = FPRep<FPType::X86_Binary80>;
 
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'000000000000000,
            0b0000000000000000000000000000000000000000000000000000000000000000),
       Rep::zero());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'011111111111111,
            0b1000000000000000000000000000000000000000000000000000000000000000),
       Rep::one());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'000000000000000,
            0b0000000000000000000000000000000000000000000000000000000000000001),
       Rep::min_subnormal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'000000000000000,
            0b0111111111111111111111111111111111111111111111111111111111111111),
       Rep::max_subnormal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'000000000000001,
            0b1000000000000000000000000000000000000000000000000000000000000000),
       Rep::min_normal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'111111111111110,
            0b1111111111111111111111111111111111111111111111111111111111111111),
       Rep::max_normal());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'111111111111111,
            0b1000000000000000000000000000000000000000000000000000000000000000),
       Rep::inf());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'111111111111111,
            0b1010000000000000000000000000000000000000000000000000000000000000),
       Rep::build_nan());
-  EXPECT_EQ(
+  EXPECT_REP_EQ(
       u128(0b0'111111111111111,
            0b1100000000000000000000000000000000000000000000000000000000000000),
       Rep::build_quiet_nan());
@@ -183,49 +231,6 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) {
       0b1000000000000000000000000000000000000000000000000000000000000000));
 }
 
-TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary128) {
-  using LIBC_NAMESPACE::fputil::FPType;
-  using LIBC_NAMESPACE::fputil::internal::FPRep;
-  using Rep = FPRep<FPType::IEEE754_Binary128>;
-
-  EXPECT_EQ(
-      u128(0b0'000000000000000'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
-      Rep::zero());
-  EXPECT_EQ(
-      u128(0b0'011111111111111'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
-      Rep::one());
-  EXPECT_EQ(
-      u128(0b0'000000000000000'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000001),
-      Rep::min_subnormal());
-  EXPECT_EQ(
-      u128(0b0'000000000000000'111111111111111111111111111111111111111111111111,
-           0b1111111111111111111111111111111111111111111111111111111111111111),
-      Rep::max_subnormal());
-  EXPECT_EQ(
-      u128(0b0'000000000000001'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
-      Rep::min_normal());
-  EXPECT_EQ(
-      u128(0b0'111111111111110'111111111111111111111111111111111111111111111111,
-           0b1111111111111111111111111111111111111111111111111111111111111111),
-      Rep::max_normal());
-  EXPECT_EQ(
-      u128(0b0'111111111111111'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
-      Rep::inf());
-  EXPECT_EQ(
-      u128(0b0'111111111111111'010000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
-      Rep::build_nan());
-  EXPECT_EQ(
-      u128(0b0'111111111111111'100000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
-      Rep::build_quiet_nan());
-}
-
 TEST(LlvmLibcFPBitsTest, FloatType) {
   using FloatBits = FPBits<float>;
 



More information about the libc-commits mailing list