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

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 16 11:24:42 PST 2024


================
@@ -241,6 +347,213 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
   using UP::FRACTION_LEN;
   using UP::FRACTION_MASK;
   using UP::MANTISSA_PRECISION;
+
+protected:
+  using typename UP::BiasedExponent;
+  using typename UP::Exponent;
+  using typename UP::Significand;
+  using UP::biased;
+  using UP::encode;
+  using UP::exp_bits;
+  using UP::exp_sig_bits;
+  using UP::sig_bits;
+
+public:
+  LIBC_INLINE constexpr bool is_nan() const {
+    return exp_sig_bits() >
+           encode(BiasedExponent::BITS_ALL_ONES, Significand::ZERO);
+  }
+  LIBC_INLINE constexpr bool is_quiet_nan() const {
+    return exp_sig_bits() >=
+           encode(BiasedExponent::BITS_ALL_ONES, Significand::MSB);
+  }
+  LIBC_INLINE constexpr bool is_signaling_nan() const {
+    return is_nan() && !is_quiet_nan();
+  }
+  LIBC_INLINE constexpr bool is_inf() const {
+    return exp_sig_bits() ==
+           encode(BiasedExponent::BITS_ALL_ONES, Significand::ZERO);
+  }
+  LIBC_INLINE constexpr bool is_zero() const {
+    return exp_sig_bits() ==
+           encode(BiasedExponent::BITS_ALL_ZEROES, Significand::ZERO);
+  }
+  LIBC_INLINE constexpr bool is_finite() const {
+    return exp_bits() != encode(BiasedExponent::BITS_ALL_ONES);
+  }
+  LIBC_INLINE
+  constexpr bool is_subnormal() const {
+    return exp_bits() == encode(BiasedExponent::BITS_ALL_ZEROES);
+  }
+  LIBC_INLINE constexpr bool is_normal() const {
+    return is_finite() && !is_subnormal();
+  }
+
+  LIBC_INLINE static constexpr StorageType zero(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ZEROES, Significand::ZERO);
+  }
+  LIBC_INLINE static constexpr StorageType one(bool sign = false) {
+    return encode(sign, biased(Exponent::ZERO), Significand::ZERO);
+  }
+  LIBC_INLINE static constexpr StorageType min_subnormal(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ZEROES, Significand::LSB);
+  }
+  LIBC_INLINE static constexpr StorageType max_subnormal(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ZEROES,
+                  Significand::BITS_ALL_ONES);
+  }
+  LIBC_INLINE static constexpr StorageType min_normal(bool sign = false) {
+    return encode(sign, biased(Exponent::MIN), Significand::ZERO);
+  }
+  LIBC_INLINE static constexpr StorageType max_normal(bool sign = false) {
+    return encode(sign, biased(Exponent::MAX), Significand::BITS_ALL_ONES);
+  }
+  LIBC_INLINE static constexpr StorageType inf(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ONES, Significand::ZERO);
+  }
+  LIBC_INLINE static constexpr StorageType build_nan(bool sign = false,
+                                                     StorageType v = 0) {
+    return encode(sign, BiasedExponent::BITS_ALL_ONES,
+                  (v ? Significand{v} : (Significand::MSB >> 1)));
+  }
+  LIBC_INLINE static constexpr StorageType build_quiet_nan(bool sign = false,
+                                                           StorageType v = 0) {
+    return encode(sign, BiasedExponent::BITS_ALL_ONES,
+                  Significand::MSB | Significand{v});
+  }
+
+  // The function return mantissa with the implicit bit set iff the current
+  // value is a valid normal number.
+  LIBC_INLINE constexpr StorageType get_explicit_mantissa() {
+    if (is_subnormal())
+      return sig_bits();
+    return (StorageType(1) << UP::SIG_LEN) | sig_bits();
+  }
+};
+
+// Specialization for the X86 Extended Precision type.
+template <>
+struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
+  using UP = FPRepBase<FPType::X86_Binary80>;
+  using typename UP::StorageType;
+  using UP::FRACTION_LEN;
+  using UP::FRACTION_MASK;
+  using UP::MANTISSA_PRECISION;
+
+protected:
+  using typename UP::BiasedExponent;
+  using typename UP::Significand;
+  using UP::encode;
+
+public:
+  // The x86 80 bit float represents the leading digit of the mantissa
+  // explicitly. This is the mask for that bit.
+  static constexpr StorageType EXPLICIT_BIT_MASK = StorageType(1)
+                                                   << FRACTION_LEN;
+  // The X80 significand is made of an explicit bit and the fractional part.
+  static_assert((EXPLICIT_BIT_MASK & FRACTION_MASK) == 0,
+                "the explicit bit and the fractional part should not overlap");
+  static_assert((EXPLICIT_BIT_MASK | FRACTION_MASK) == SIG_MASK,
+                "the explicit bit and the fractional part should cover the "
+                "whole significand");
+
+  LIBC_INLINE constexpr bool is_nan() const {
+    // Most encoding forms from the table found in
+    // https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format
+    // are interpreted as NaN.
+    // More precisely :
+    // - Pseudo-Infinity
+    // - Pseudo Not a Number
+    // - Signalling Not a Number
+    // - Floating-point Indefinite
+    // - Quiet Not a Number
+    // - Unnormal
+    // This can be reduced to the following logic:
+    if (exp_bits() == encode(BiasedExponent::BITS_ALL_ONES))
+      return !is_inf();
+    if (exp_bits() != encode(BiasedExponent::BITS_ALL_ZEROES))
+      return (sig_bits() & encode(Significand::MSB)) == 0;
+    return false;
+  }
+  LIBC_INLINE constexpr bool is_quiet_nan() const {
+    return exp_sig_bits() >= encode(BiasedExponent::BITS_ALL_ONES,
+                                    Significand::MSB | (Significand::MSB >> 1));
+  }
+  LIBC_INLINE constexpr bool is_signaling_nan() const {
+    return is_nan() && !is_quiet_nan();
+  }
+  LIBC_INLINE constexpr bool is_inf() const {
+    return exp_sig_bits() ==
+           encode(BiasedExponent::BITS_ALL_ONES, Significand::MSB);
+  }
+  LIBC_INLINE constexpr bool is_zero() const {
+    return exp_sig_bits() ==
+           encode(BiasedExponent::BITS_ALL_ZEROES, Significand::ZERO);
+  }
+  LIBC_INLINE constexpr bool is_finite() const {
+    return !is_inf() && !is_nan();
+  }
+  LIBC_INLINE
+  constexpr bool is_subnormal() const {
+    return exp_sig_bits() >
+           encode(BiasedExponent::BITS_ALL_ZEROES, Significand::ZERO);
+  }
+  LIBC_INLINE constexpr bool is_normal() const {
+    const auto exp = exp_bits();
+    if (exp == encode(BiasedExponent::BITS_ALL_ZEROES) ||
+        exp == encode(BiasedExponent::BITS_ALL_ONES))
+      return false;
+    return get_implicit_bit();
+  }
+
+  LIBC_INLINE static constexpr StorageType zero(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ZEROES, Significand::ZERO);
+  }
+  LIBC_INLINE static constexpr StorageType one(bool sign = false) {
+    return encode(sign, biased(Exponent::ZERO), Significand::MSB);
+  }
+  LIBC_INLINE static constexpr StorageType min_subnormal(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ZEROES, Significand::LSB);
+  }
+  LIBC_INLINE static constexpr StorageType max_subnormal(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ZEROES,
+                  Significand::BITS_ALL_ONES ^ Significand::MSB);
+  }
+  LIBC_INLINE static constexpr StorageType min_normal(bool sign = false) {
+    return encode(sign, biased(Exponent::MIN), Significand::MSB);
+  }
+  LIBC_INLINE static constexpr StorageType max_normal(bool sign = false) {
+    return encode(sign, biased(Exponent::MAX), Significand::BITS_ALL_ONES);
+  }
+  LIBC_INLINE static constexpr StorageType inf(bool sign = false) {
+    return encode(sign, BiasedExponent::BITS_ALL_ONES, Significand::MSB);
+  }
+  LIBC_INLINE static constexpr StorageType build_nan(bool sign = false,
+                                                     StorageType v = 0) {
+    return encode(sign, BiasedExponent::BITS_ALL_ONES,
+                  Significand::MSB |
+                      (v ? Significand{v} : (Significand::MSB >> 2)));
----------------
nickdesaulniers wrote:

Seems resolved if we remove the `cpp::is_integral_v<T>` check from `BigInt::to` (added in 1ee6a1e38aa0c3773d892fcd01bb2af8e446e67f).

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


More information about the llvm-commits mailing list