[libc-commits] [libc] Revert "[libc] Remove unnecessary `FPBits` functions and properties" (PR #79118)

via libc-commits libc-commits at lists.llvm.org
Tue Jan 23 02:51:23 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Guillaume Chatelet (gchatelet)

<details>
<summary>Changes</summary>

Reverts llvm/llvm-project#<!-- -->79113
It broke aarch64 build bot machines.

---

Patch is 99.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/79118.diff


68 Files Affected:

- (modified) libc/fuzzing/stdlib/strtofloat_fuzz.cpp (+1-1) 
- (modified) libc/src/__support/FPUtil/DivisionAndRemainderOperations.h (+1-1) 
- (modified) libc/src/__support/FPUtil/FPBits.h (+42-9) 
- (modified) libc/src/__support/FPUtil/Hypot.h (+2-2) 
- (modified) libc/src/__support/FPUtil/ManipulationFunctions.h (+14-10) 
- (modified) libc/src/__support/FPUtil/NormalFloat.h (+1-1) 
- (modified) libc/src/__support/FPUtil/dyadic_float.h (+1-1) 
- (modified) libc/src/__support/FPUtil/except_value_utils.h (+4-2) 
- (modified) libc/src/__support/FPUtil/generic/FMA.h (+6-4) 
- (modified) libc/src/__support/FPUtil/generic/FMod.h (+1-1) 
- (modified) libc/src/__support/FPUtil/generic/sqrt.h (+7-11) 
- (modified) libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h (+3-5) 
- (modified) libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h (+31-27) 
- (modified) libc/src/__support/common.h (+1) 
- (modified) libc/src/__support/str_to_float.h (+2-2) 
- (modified) libc/src/math/generic/acosf.cpp (+1-1) 
- (modified) libc/src/math/generic/acoshf.cpp (+1-1) 
- (modified) libc/src/math/generic/asinf.cpp (+1-1) 
- (modified) libc/src/math/generic/atanhf.cpp (+2-2) 
- (modified) libc/src/math/generic/cosf.cpp (+1-1) 
- (modified) libc/src/math/generic/coshf.cpp (+3-3) 
- (modified) libc/src/math/generic/exp.cpp (+2-2) 
- (modified) libc/src/math/generic/exp10.cpp (+2-2) 
- (modified) libc/src/math/generic/exp10f_impl.h (+3-3) 
- (modified) libc/src/math/generic/exp2.cpp (+2-2) 
- (modified) libc/src/math/generic/exp2f_impl.h (+3-3) 
- (modified) libc/src/math/generic/expf.cpp (+2-2) 
- (modified) libc/src/math/generic/expm1.cpp (+2-2) 
- (modified) libc/src/math/generic/expm1f.cpp (+2-2) 
- (modified) libc/src/math/generic/log.cpp (+5-6) 
- (modified) libc/src/math/generic/log10.cpp (+5-6) 
- (modified) libc/src/math/generic/log10f.cpp (+3-5) 
- (modified) libc/src/math/generic/log1p.cpp (+3-4) 
- (modified) libc/src/math/generic/log1pf.cpp (+2-2) 
- (modified) libc/src/math/generic/log2.cpp (+5-6) 
- (modified) libc/src/math/generic/log2f.cpp (+3-5) 
- (modified) libc/src/math/generic/logf.cpp (+4-5) 
- (modified) libc/src/math/generic/powf.cpp (+6-7) 
- (modified) libc/src/math/generic/sincosf.cpp (+1-3) 
- (modified) libc/src/math/generic/sinf.cpp (+1-1) 
- (modified) libc/src/math/generic/sinhf.cpp (+3-3) 
- (modified) libc/src/math/generic/tanf.cpp (+1-1) 
- (modified) libc/test/UnitTest/FPMatcher.h (+20-20) 
- (modified) libc/test/src/__support/FPUtil/fpbits_test.cpp (+48-33) 
- (modified) libc/test/src/math/FDimTest.h (+1-1) 
- (modified) libc/test/src/math/FmaTest.h (+16-21) 
- (modified) libc/test/src/math/HypotTest.h (+20-23) 
- (modified) libc/test/src/math/ILogbTest.h (+11-11) 
- (modified) libc/test/src/math/LdExpTest.h (+1-1) 
- (modified) libc/test/src/math/NextAfterTest.h (+5-5) 
- (modified) libc/test/src/math/RIntTest.h (+9-12) 
- (modified) libc/test/src/math/RemQuoTest.h (+11-14) 
- (modified) libc/test/src/math/RoundToIntegerTest.h (+9-13) 
- (modified) libc/test/src/math/differential_testing/BinaryOpSingleOutputDiff.h (+6-10) 
- (modified) libc/test/src/math/differential_testing/SingleInputSingleOutputDiff.h (+3-4) 
- (modified) libc/test/src/math/smoke/FDimTest.h (+1-1) 
- (modified) libc/test/src/math/smoke/FmaTest.h (+7-9) 
- (modified) libc/test/src/math/smoke/HypotTest.h (+10-10) 
- (modified) libc/test/src/math/smoke/ILogbTest.h (+9-9) 
- (modified) libc/test/src/math/smoke/LdExpTest.h (+1-1) 
- (modified) libc/test/src/math/smoke/NextAfterTest.h (+6-8) 
- (modified) libc/test/src/math/smoke/NextTowardTest.h (+10-12) 
- (modified) libc/test/src/math/smoke/RIntTest.h (+1-1) 
- (modified) libc/test/src/math/smoke/RemQuoTest.h (+1-1) 
- (modified) libc/test/src/math/smoke/RoundToIntegerTest.h (+9-13) 
- (modified) libc/test/src/stdio/sprintf_test.cpp (+11-21) 
- (modified) libc/test/src/stdio/sscanf_test.cpp (+8-13) 
- (modified) libc/utils/MPFRWrapper/MPFRUtils.cpp (+1-1) 


``````````diff
diff --git a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
index b773043bda67d8a..affef6fcf549e08 100644
--- a/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
+++ b/libc/fuzzing/stdlib/strtofloat_fuzz.cpp
@@ -28,7 +28,7 @@ using LIBC_NAMESPACE::fputil::FPBits;
 // exponent. Subnormals have a lower effective precision since they don't
 // necessarily use all of the bits of the mantissa.
 template <typename F> inline constexpr int effective_precision(int exponent) {
-  const int full_precision = FPBits<F>::FRACTION_LEN + 1;
+  const int full_precision = FPBits<F>::MANTISSA_PRECISION;
 
   // This is intended to be 0 when the exponent is the lowest normal and
   // increase as the exponent's magnitude increases.
diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
index ef9593a42b00557..1798310c3e31e30 100644
--- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
@@ -31,7 +31,7 @@ LIBC_INLINE T remquo(T x, T y, int &q) {
   if (ybits.is_nan())
     return y;
   if (xbits.is_inf() || ybits.is_zero())
-    return FPBits<T>::build_quiet_nan(fputil::Sign::POS, 1).get_val();
+    return FPBits<T>::build_quiet_nan(1);
 
   if (xbits.is_zero()) {
     q = 0;
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 0a79b505ecbe1c2..2465158bb2cdfc7 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -390,7 +390,7 @@ struct FPRepSem : public FPStorage<fp_type> {
     return exp_bits() == encode(BiasedExp::BITS_ALL_ZEROES());
   }
   LIBC_INLINE constexpr bool is_normal() const {
-    return is_finite() && !is_subnormal();
+    return is_finite() && !UP::is_subnormal();
   }
   // Returns the mantissa with the implicit bit set iff the current
   // value is a valid normal number.
@@ -556,14 +556,6 @@ struct FPRep : public FPRepSem<fp_type, RetT> {
   using UP::FRACTION_MASK;
   using UP::SIGN_MASK;
 
-  // Comparison
-  LIBC_INLINE constexpr friend bool operator==(FPRep a, FPRep b) {
-    return a.uintval() == b.uintval();
-  }
-  LIBC_INLINE constexpr friend bool operator!=(FPRep a, FPRep b) {
-    return a.uintval() != b.uintval();
-  }
-
   // Representation
   LIBC_INLINE constexpr StorageType uintval() const { return bits & FP_MASK; }
   LIBC_INLINE constexpr void set_uintval(StorageType value) {
@@ -706,6 +698,16 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
   using UP::bits;
 
   // Constants.
+  LIBC_INLINE_VAR static constexpr uint32_t MANTISSA_PRECISION =
+      UP::FRACTION_LEN + 1;
+  LIBC_INLINE_VAR static constexpr StorageType MIN_NORMAL =
+      UP::min_normal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MAX_NORMAL =
+      UP::max_normal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MIN_SUBNORMAL =
+      UP::min_subnormal(Sign::POS).uintval();
+  LIBC_INLINE_VAR static constexpr StorageType MAX_SUBNORMAL =
+      UP::max_subnormal(Sign::POS).uintval();
   LIBC_INLINE_VAR static constexpr int MAX_BIASED_EXPONENT =
       (1 << UP::EXP_LEN) - 1;
 
@@ -729,6 +731,37 @@ struct FPBits final : public internal::FPRep<get_fp_type<T>(), FPBits<T>> {
 
   LIBC_INLINE constexpr explicit operator T() const { return get_val(); }
 
+  // Methods below this are used by tests.
+  // TODO: inline and remove.
+  LIBC_INLINE static constexpr T one(Sign sign = Sign::POS) {
+    return T(UP::one(sign));
+  }
+  LIBC_INLINE static constexpr T zero(Sign sign = Sign::POS) {
+    return T(UP::zero(sign));
+  }
+  LIBC_INLINE static constexpr T inf(Sign sign = Sign::POS) {
+    return T(UP::inf(sign));
+  }
+  LIBC_INLINE static constexpr T min_normal() {
+    return T(UP::min_normal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T max_normal() {
+    return T(UP::max_normal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T min_denormal() {
+    return T(UP::min_subnormal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T max_denormal() {
+    return T(UP::max_subnormal(Sign::POS));
+  }
+  LIBC_INLINE static constexpr T build_nan(StorageType v) {
+    return T(UP::build_nan(Sign::POS, v));
+  }
+  LIBC_INLINE static constexpr T build_quiet_nan(StorageType v,
+                                                 Sign sign = Sign::POS) {
+    return T(UP::build_quiet_nan(sign, v));
+  }
+
   // TODO: Use an uint32_t for 'biased_exp'.
   LIBC_INLINE static constexpr FPBits<T>
   create_value(Sign sign, StorageType biased_exp, StorageType mantissa) {
diff --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index 82237dec09e42e3..c38a40dfb08984a 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -197,7 +197,7 @@ LIBC_INLINE T hypot(T x, T y) {
         if (int round_mode = quick_get_round();
             round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
           return T(FPBits_t::inf());
-        return T(FPBits_t::max_normal());
+        return T(FPBits_t(FPBits_t::MAX_NORMAL));
       }
     } else {
       // For denormal result, we simply move the leading bit of the result to
@@ -254,7 +254,7 @@ LIBC_INLINE T hypot(T x, T y) {
     if (out_exp >= FPBits_t::MAX_BIASED_EXPONENT) {
       if (round_mode == FE_TONEAREST || round_mode == FE_UPWARD)
         return T(FPBits_t::inf());
-      return T(FPBits_t::max_normal());
+      return T(FPBits_t(FPBits_t::MAX_NORMAL));
     }
   }
 
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index d7114625a9b3141..81c8281f3c7bbee 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -108,7 +108,7 @@ LIBC_INLINE T logb(T x) {
     return x;
   } else if (bits.is_inf()) {
     // Return positive infinity.
-    return T(FPBits<T>::inf());
+    return T(FPBits<T>::inf(Sign::POS));
   }
 
   NormalFloat<T> normal(bits);
@@ -127,7 +127,7 @@ LIBC_INLINE T ldexp(T x, int exp) {
   // that adding |exp| to it does not lead to integer rollover. But, if |exp|
   // value is larger the exponent range for type T, then we can return infinity
   // early. Because the result of the ldexp operation can be a subnormal number,
-  // we need to accommodate the (mantissaWidth + 1) worth of shift in
+  // we need to accommodate the (mantissaWidht + 1) worth of shift in
   // calculating the limit.
   int exp_limit = FPBits<T>::MAX_BIASED_EXPONENT + FPBits<T>::FRACTION_LEN + 1;
   if (exp > exp_limit)
@@ -164,22 +164,26 @@ LIBC_INLINE T nextafter(T from, U to) {
     return static_cast<T>(to);
 
   using StorageType = typename FPBits<T>::StorageType;
-  if (from != T(0)) {
-    if ((static_cast<U>(from) < to) == (from > T(0))) {
-      from_bits = FPBits<T>(StorageType(from_bits.uintval() + 1));
+  StorageType int_val = from_bits.uintval();
+  if (from != FPBits<T>::zero()) {
+    if ((static_cast<U>(from) < to) == (from > FPBits<T>::zero())) {
+      ++int_val;
     } else {
-      from_bits = FPBits<T>(StorageType(from_bits.uintval() - 1));
+      --int_val;
     }
   } else {
-    from_bits = FPBits<T>::min_subnormal(to_bits.sign());
+    int_val = FPBits<T>::MIN_SUBNORMAL;
+    if (to_bits.is_neg())
+      int_val |= FPBits<T>::SIGN_MASK;
   }
 
-  if (from_bits.is_subnormal())
+  StorageType exponent_bits = int_val & FPBits<T>::EXP_MASK;
+  if (exponent_bits == StorageType(0))
     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
-  else if (from_bits.is_inf())
+  else if (exponent_bits == FPBits<T>::EXP_MASK)
     raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
 
-  return from_bits.get_val();
+  return cpp::bit_cast<T>(int_val);
 }
 
 } // namespace fputil
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index fa4da33b5b17fae..cfa9e1417510559 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -215,7 +215,7 @@ template <> LIBC_INLINE NormalFloat<long double>::operator long double() const {
   // Max exponent is of the form 0xFF...E. That is why -2 and not -1.
   constexpr int MAX_EXPONENT_VALUE = (1 << LDBits::EXP_LEN) - 2;
   if (biased_exponent > MAX_EXPONENT_VALUE) {
-    return LDBits::inf(sign).get_val();
+    return LDBits::inf(sign);
   }
 
   FPBits<long double> result(0.0l);
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 888d7ffec241ea4..5449f5561d56968 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -93,7 +93,7 @@ template <size_t Bits> struct DyadicFloat {
       return 0.0;
 
     // Assume that it is normalized, and output is also normal.
-    constexpr uint32_t PRECISION = FPBits<T>::FRACTION_LEN + 1;
+    constexpr uint32_t PRECISION = FPBits<T>::MANTISSA_PRECISION;
     using output_bits_t = typename FPBits<T>::StorageType;
 
     int exp_hi = exponent + static_cast<int>((Bits - 1) + FPBits<T>::EXP_BIAS);
diff --git a/libc/src/__support/FPUtil/except_value_utils.h b/libc/src/__support/FPUtil/except_value_utils.h
index 1e0381194009d55..89849540315f64d 100644
--- a/libc/src/__support/FPUtil/except_value_utils.h
+++ b/libc/src/__support/FPUtil/except_value_utils.h
@@ -102,13 +102,15 @@ template <typename T, size_t N> struct ExceptValues {
 // Helper functions to set results for exceptional cases.
 template <typename T> LIBC_INLINE T round_result_slightly_down(T value_rn) {
   volatile T tmp = value_rn;
-  tmp -= FPBits<T>::min_normal().get_val();
+  const T MIN_NORMAL = FPBits<T>::min_normal();
+  tmp = tmp - MIN_NORMAL;
   return tmp;
 }
 
 template <typename T> LIBC_INLINE T round_result_slightly_up(T value_rn) {
   volatile T tmp = value_rn;
-  tmp += FPBits<T>::min_normal().get_val();
+  const T MIN_NORMAL = FPBits<T>::min_normal();
+  tmp = tmp + MIN_NORMAL;
   return tmp;
 }
 
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 5c36463ea50213e..6285cac1983d1e9 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -130,9 +130,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
     return x * y + z;
 
   // Extract mantissa and append hidden leading bits.
-  UInt128 x_mant = x_bits.get_explicit_mantissa();
-  UInt128 y_mant = y_bits.get_explicit_mantissa();
-  UInt128 z_mant = z_bits.get_explicit_mantissa();
+  UInt128 x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL;
 
   // If the exponent of the product x*y > the exponent of z, then no extra
   // precision beside the entire product x*y is needed.  On the other hand, when
@@ -255,7 +255,9 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
     if ((round_mode == FE_TOWARDZERO) ||
         (round_mode == FE_UPWARD && prod_sign.is_neg()) ||
         (round_mode == FE_DOWNWARD && prod_sign.is_pos())) {
-      return FPBits::max_normal(prod_sign).get_val();
+      result = FPBits::MAX_NORMAL;
+      return prod_sign.is_neg() ? -cpp::bit_cast<double>(result)
+                                : cpp::bit_cast<double>(result);
     }
     return static_cast<double>(FPBits::inf(prod_sign));
   }
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 18355b801dbc7c9..f4000b97751efc4 100644
--- a/libc/src/__support/FPUtil/generic/FMod.h
+++ b/libc/src/__support/FPUtil/generic/FMod.h
@@ -124,7 +124,7 @@ template <typename T> struct FModExceptionalInputHandler {
 
   LIBC_INLINE static bool pre_check(T x, T y, T &out) {
     using FPB = fputil::FPBits<T>;
-    const T quiet_nan = FPB::build_quiet_nan().get_val();
+    const T quiet_nan = FPB::build_quiet_nan(0);
     FPB sx(x), sy(y);
     if (LIBC_LIKELY(!sy.is_zero() && !sy.is_inf_or_nan() &&
                     !sx.is_inf_or_nan())) {
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index 0a0690ec1463b9d..21ae9d081d3f12e 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -71,19 +71,15 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
     return x86::sqrt(x);
   } else {
     // IEEE floating points formats.
-    using Sign = fputil::Sign;
-    using FPBits_t = typename fputil::FPBits<T>;
-    using StorageType = typename FPBits_t::StorageType;
-    constexpr StorageType ONE = StorageType(1) << FPBits_t::FRACTION_LEN;
-    constexpr auto FLT_NAN =
-        FPBits_t::build_quiet_nan(Sign::POS, ONE >> 1).get_val();
+    using StorageType = typename FPBits<T>::StorageType;
+    constexpr StorageType ONE = StorageType(1) << FPBits<T>::FRACTION_LEN;
 
-    FPBits_t bits(x);
+    FPBits<T> bits(x);
 
     if (bits.is_inf_or_nan()) {
       if (bits.is_neg() && (bits.get_mantissa() == 0)) {
         // sqrt(-Inf) = NaN
-        return FLT_NAN;
+        return FPBits<T>::build_quiet_nan(ONE >> 1);
       } else {
         // sqrt(NaN) = NaN
         // sqrt(+Inf) = +Inf
@@ -95,7 +91,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
       return x;
     } else if (bits.is_neg()) {
       // sqrt( negative numbers ) = NaN
-      return FLT_NAN;
+      return FPBits<T>::build_quiet_nan(ONE >> 1);
     } else {
       int x_exp = bits.get_exponent();
       StorageType x_mant = bits.get_mantissa();
@@ -149,10 +145,10 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
       }
 
       // Remove hidden bit and append the exponent field.
-      x_exp = ((x_exp >> 1) + FPBits_t::EXP_BIAS);
+      x_exp = ((x_exp >> 1) + FPBits<T>::EXP_BIAS);
 
       y = (y - ONE) |
-          (static_cast<StorageType>(x_exp) << FPBits_t::FRACTION_LEN);
+          (static_cast<StorageType>(x_exp) << FPBits<T>::FRACTION_LEN);
 
       switch (quick_get_round()) {
       case FE_TONEAREST:
diff --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index b0a3776029ca78a..4f8d136938f56e7 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -38,16 +38,14 @@ LIBC_INLINE long double sqrt(long double x);
 LIBC_INLINE long double sqrt(long double x) {
   using LDBits = FPBits<long double>;
   using StorageType = typename LDBits::StorageType;
-  using Sign = fputil::Sign;
   constexpr StorageType ONE = StorageType(1) << int(LDBits::FRACTION_LEN);
-  constexpr auto LDNAN = LDBits::build_quiet_nan(Sign::POS, ONE >> 1).get_val();
 
-  LDBits bits(x);
+  FPBits<long double> bits(x);
 
   if (bits.is_inf_or_nan()) {
     if (bits.is_neg() && (bits.get_mantissa() == 0)) {
       // sqrt(-Inf) = NaN
-      return LDNAN;
+      return LDBits::build_quiet_nan(ONE >> 1);
     } else {
       // sqrt(NaN) = NaN
       // sqrt(+Inf) = +Inf
@@ -59,7 +57,7 @@ LIBC_INLINE long double sqrt(long double x) {
     return x;
   } else if (bits.is_neg()) {
     // sqrt( negative numbers ) = NaN
-    return LDNAN;
+    return LDBits::build_quiet_nan(ONE >> 1);
   } else {
     int x_exp = bits.get_explicit_exponent();
     StorageType x_mant = bits.get_mantissa();
diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
index d1c76ba954b9304..512f5de4e7931ac 100644
--- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
@@ -43,18 +43,16 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
   }
 
   using StorageType = FPBits::StorageType;
-
+  constexpr StorageType SIGN_VAL = (StorageType(1) << 79);
   constexpr StorageType FRACTION_MASK = FPBits::FRACTION_MASK;
-  // StorageType int_val = from_bits.uintval();
-  if (from == 0.0l) { // +0.0 / -0.0
-    from_bits = FPBits::min_subnormal(from > to ? Sign::NEG : Sign::POS);
-  } else if (from < 0.0l) {
-    if (to < from) { // toward -inf
-      if (from_bits == FPBits::max_subnormal(Sign::NEG)) {
+  StorageType int_val = from_bits.uintval();
+  if (from < 0.0l) {
+    if (from > to) {
+      if (int_val == (SIGN_VAL + FPBits::MAX_SUBNORMAL)) {
         // We deal with normal/subnormal boundary separately to avoid
         // dealing with the implicit bit.
-        from_bits = FPBits::min_normal(Sign::NEG);
-      } else if (from_bits.get_mantissa() == FRACTION_MASK) {
+        int_val = SIGN_VAL + FPBits::MIN_NORMAL;
+      } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) {
         from_bits.set_mantissa(0);
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
@@ -64,40 +62,45 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() + 1));
+        ++int_val;
       }
-    } else { // toward +inf
-      if (from_bits == FPBits::min_normal(Sign::NEG)) {
+    } else {
+      if (int_val == (SIGN_VAL + FPBits::MIN_NORMAL)) {
         // We deal with normal/subnormal boundary separately to avoid
         // dealing with the implicit bit.
-        from_bits = FPBits::max_subnormal(Sign::NEG);
-      } else if (from_bits.get_mantissa() == 0) {
+        int_val = SIGN_VAL + FPBits::MAX_SUBNORMAL;
+      } else if ((int_val & FRACTION_MASK) == 0) {
         from_bits.set_mantissa(FRACTION_MASK);
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() - 1));
+        --int_val;
       }
     }
+  } else if (from == 0.0l) {
+    if (from > to)
+      int_val = SIGN_VAL + 1;
+    else
+      int_val = 1;
   } else {
-    if (to < from) { // toward -inf
-      if (from_bits == FPBits::min_normal(Sign::POS)) {
-        from_bits = FPBits::max_subnormal(Sign::POS);
-      } else if (from_bits.get_mantissa() == 0) {
+    if (from > to) {
+      if (int_val == FPBits::MIN_NORMAL) {
+        int_val = FPBits::MAX_SUBNORMAL;
+      } else if ((int_val & FRACTION_MASK) == 0) {
         from_bits.set_mantissa(FRACTION_MASK);
         // from == 0 is handled separately so decrementing the exponent will not
         // lead to underflow.
         from_bits.set_biased_exponent(from_bits.get_biased_exponent() - 1);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() - 1));
+        --int_val;
       }
-    } else { // toward +inf
-      if (from_bits == FPBits::max_subnormal(Sign::POS)) {
-        from_bits = FPBits::min_normal(Sign::POS);
-      } else if (from_bits.get_mantissa() == FRACTION_MASK) {
+    } else {
+      if (int_val == FPBits::MAX_SUBNORMAL) {
+        int_val = FPBits::MIN_NORMAL;
+      } else if ((int_val & FRACTION_MASK) == FRACTION_MASK) {
         from_bits.set_mantissa(0);
         // Incrementing exponent might overflow the value to infinity,
         // which is what is expected. Since NaNs are handling separately,
@@ -107,15 +110,16 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
           raise_except_if_required(FE_OVERFLOW | FE_INEXACT);
         return from_bits.get_val();
       } else {
-        from_bits = FPBits(StorageType(from_bits.uintval() + 1));
+        ++int_val;
       }
     }
   }
 
-  if (!from_bits.get_implicit_bit())
+  StorageType implicit_bit = int_val & (StorageType(1) << FPBits::FRACTION_LEN);
+  if (implicit_bit == StorageType(0))
     raise_except_if_required(FE_UNDERFLOW | FE_INEXACT);
 
-  return from_bits.get_val();
+  return cpp::bit_cast<long double>(int_val);
 }
 
 } // namespace fputil
diff --git a/libc/src/__support/common.h b/libc/src/__support/common.h
index a153dfc363d7374..53951dc131c28b6 100644
--- a/libc/src/__support/common.h
+++ b/libc/src/__support/common.h
@@ -2...
[truncated]

``````````

</details>


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


More information about the libc-commits mailing list