[libc] [llvm] [reland][libc][NFC] Refactor FPBits and remove LongDoubleBits specialization (PR #78447)

Clement Courbet via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 17 06:48:12 PST 2024


================
@@ -171,68 +171,98 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
     return StorageType(1) << position;
   }
 
+  template <typename T> struct Opaque {
+    using value_type = T;
+    LIBC_INLINE constexpr explicit Opaque(T value) : value(value) {}
+    LIBC_INLINE constexpr Opaque(const Opaque &value) = default;
+
+    LIBC_INLINE constexpr explicit operator T() const { return value; }
+
+  private:
+    T value;
+  };
+
   // An opaque type to store a floating point exponent.
   // We define special values but it is valid to create arbitrary values as long
   // as they are in the range [MIN, MAX].
-  enum class Exponent : int32_t {
-    MIN = 1 - EXP_BIAS,
-    ZERO = 0,
-    MAX = EXP_BIAS,
+  struct Exponent : public Opaque<int32_t> {
+    using UP = Opaque<int32_t>;
+    using UP::UP;
+    LIBC_INLINE
+    static constexpr auto MIN() { return Exponent{1 - EXP_BIAS}; }
+    LIBC_INLINE static constexpr auto ZERO() { return Exponent{0}; }
+    LIBC_INLINE static constexpr auto MAX() { return Exponent{EXP_BIAS}; }
   };
 
   // An opaque type to store a floating point biased exponent.
   // We define special values but it is valid to create arbitrary values as long
   // as they are in the range [BITS_ALL_ZEROES, BITS_ALL_ONES].
   // Values greater than BITS_ALL_ONES are truncated.
-  enum class BiasedExponent : uint32_t {
+  struct BiasedExponent : public Opaque<uint32_t> {
+    using UP = Opaque<uint32_t>;
+    using UP::UP;
+
+    LIBC_INLINE constexpr BiasedExponent(Exponent exp)
+        : UP(static_cast<int32_t>(exp) + EXP_BIAS) {}
     // The exponent value for denormal numbers.
-    BITS_ALL_ZEROES = 0,
+    LIBC_INLINE static constexpr auto BITS_ALL_ZEROES() {
+      return BiasedExponent{uint32_t(0)};
+    }
     // The exponent value for infinity.
-    BITS_ALL_ONES = 2 * EXP_BIAS + 1,
+    LIBC_INLINE static constexpr auto BITS_ALL_ONES() {
+      return BiasedExponent{uint32_t(2 * EXP_BIAS + 1)};
+    }
   };
 
-  LIBC_INLINE static constexpr BiasedExponent biased(Exponent value) {
-    return static_cast<BiasedExponent>(static_cast<int32_t>(value) + EXP_BIAS);
-  }
-
   // An opaque type to store a floating point significand.
   // We define special values but it is valid to create arbitrary values as long
   // as they are in the range [BITS_ALL_ZEROES, BITS_ALL_ONES].
   // Note that the semantics of the Significand are implementation dependent.
   // Values greater than BITS_ALL_ONES are truncated.
-  enum class Significand : StorageType {
-    ZERO = 0,
-    LSB = 1,
-    MSB = bit_at(SIG_LEN - 1),
+  struct Significand : public Opaque<StorageType> {
+    using UP = Opaque<StorageType>;
+    using UP::UP;
+
+    LIBC_INLINE static constexpr auto ZERO() {
+      return Significand{StorageType(0)};
+    }
+    LIBC_INLINE static constexpr auto LSB() {
+      return Significand{StorageType(1)};
+    }
+    LIBC_INLINE static constexpr auto MSB() {
+      return Significand{StorageType(bit_at(SIG_LEN - 1))};
+    }
     // Aliases
-    BITS_ALL_ZEROES = ZERO,
-    BITS_ALL_ONES = SIG_MASK,
+    LIBC_INLINE static constexpr auto BITS_ALL_ZEROES() { return ZERO(); }
+    LIBC_INLINE static constexpr auto BITS_ALL_ONES() {
+      return Significand{SIG_MASK};
+    }
   };
 
-  template <typename T>
-  LIBC_INLINE static constexpr auto storage_cast(T value) {
-    return static_cast<StorageType>(value);
+  template <typename To, typename T>
+  LIBC_INLINE static constexpr To as(Opaque<T> opaque) {
+    return To(static_cast<T>(opaque));
   }
 
   LIBC_INLINE friend constexpr Significand operator|(const Significand a,
                                                      const Significand b) {
-    return Significand{storage_cast(storage_cast(a) | storage_cast(b))};
+    return Significand{StorageType(as<StorageType>(a) | as<StorageType>(b))};
   }
   LIBC_INLINE friend constexpr Significand operator^(const Significand a,
                                                      const Significand b) {
-    return Significand{storage_cast(storage_cast(a) ^ storage_cast(b))};
+    return Significand{StorageType(as<StorageType>(a) ^ as<StorageType>(b))};
   }
   LIBC_INLINE friend constexpr Significand operator>>(const Significand a,
                                                       int shift) {
-    return Significand{storage_cast(storage_cast(a) >> shift)};
+    return Significand{StorageType(as<StorageType>(a) >> shift)};
   }
----------------
legrosbuffle wrote:

Operations can now be friend function in `Significand`.

https://github.com/llvm/llvm-project/pull/78447


More information about the llvm-commits mailing list