[libc-commits] [libc] [libc] Fix is_subnormal for Intel Extended Precision (PR #78592)
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Thu Jan 18 11:18:33 PST 2024
https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/78592
>From 0ce391137b360970401761aa9ea9ce9e1294cfbc Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 18 Jan 2024 14:57:42 +0000
Subject: [PATCH 1/2] [libc] Fix is_subnormal for Intel Extended Precision
Also turn a set of `get_biased_exponent() == 0` into `is_subnormal()` which is clearer.
---
libc/src/__support/FPUtil/FPBits.h | 3 +--
libc/src/__support/FPUtil/NormalFloat.h | 4 ++--
libc/src/__support/FPUtil/generic/FMA.h | 6 +++---
libc/src/__support/FPUtil/generic/sqrt.h | 2 +-
.../__support/FPUtil/generic/sqrt_80_bit_long_double.h | 2 +-
libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h | 2 +-
libc/utils/MPFRWrapper/MPFRUtils.cpp | 8 ++++----
7 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 3ee6289b749648..e6c0f91c878f75 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -559,8 +559,7 @@ struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
}
LIBC_INLINE
constexpr bool is_subnormal() const {
- return exp_sig_bits() >
- encode(BiasedExponent::BITS_ALL_ZEROES(), Significand::ZERO());
+ return exp_bits() == encode(BiasedExponent::BITS_ALL_ZEROES());
}
LIBC_INLINE constexpr bool is_normal() const {
const auto exp = exp_bits();
diff --git a/libc/src/__support/FPUtil/NormalFloat.h b/libc/src/__support/FPUtil/NormalFloat.h
index 8b1612e1b47c61..e7abc53ce6129c 100644
--- a/libc/src/__support/FPUtil/NormalFloat.h
+++ b/libc/src/__support/FPUtil/NormalFloat.h
@@ -153,7 +153,7 @@ template <typename T> struct NormalFloat {
}
// Normalize subnormal numbers.
- if (bits.get_biased_exponent() == 0) {
+ if (bits.is_subnormal()) {
unsigned shift = evaluate_normalization_shift(bits.get_mantissa());
mantissa = StorageType(bits.get_mantissa()) << shift;
exponent = 1 - FPBits<T>::EXP_BIAS - shift;
@@ -186,7 +186,7 @@ NormalFloat<long double>::init_from_bits(FPBits<long double> bits) {
return;
}
- if (bits.get_biased_exponent() == 0) {
+ if (bits.is_subnormal()) {
if (bits.get_implicit_bit() == 0) {
// Since we ignore zero value, the mantissa in this case is non-zero.
int normalization_shift =
diff --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 9c67c645d5243d..6285cac1983d1e 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -104,15 +104,15 @@ template <> LIBC_INLINE double fma<double>(double x, double y, double z) {
int z_exp = 0;
// Normalize denormal inputs.
- if (LIBC_UNLIKELY(FPBits(x).get_biased_exponent() == 0)) {
+ if (LIBC_UNLIKELY(FPBits(x).is_subnormal())) {
x_exp -= 52;
x *= 0x1.0p+52;
}
- if (LIBC_UNLIKELY(FPBits(y).get_biased_exponent() == 0)) {
+ if (LIBC_UNLIKELY(FPBits(y).is_subnormal())) {
y_exp -= 52;
y *= 0x1.0p+52;
}
- if (LIBC_UNLIKELY(FPBits(z).get_biased_exponent() == 0)) {
+ if (LIBC_UNLIKELY(FPBits(z).is_subnormal())) {
z_exp -= 52;
z *= 0x1.0p+52;
}
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index f273b678edf527..21ae9d081d3f12 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -97,7 +97,7 @@ LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
StorageType x_mant = bits.get_mantissa();
// Step 1a: Normalize denormal input and append hidden bit to the mantissa
- if (bits.get_biased_exponent() == 0) {
+ if (bits.is_subnormal()) {
++x_exp; // let x_exp be the correct exponent of ONE bit.
internal::normalize<T>(x_exp, x_mant);
} else {
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 4fe9b49ff41cf0..4f8d136938f56e 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
@@ -65,7 +65,7 @@ LIBC_INLINE long double sqrt(long double x) {
// Step 1a: Normalize denormal input
if (bits.get_implicit_bit()) {
x_mant |= ONE;
- } else if (bits.get_biased_exponent() == 0) {
+ } else if (bits.is_subnormal()) {
normalize(x_exp, x_mant);
}
diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
index 5f15bac5df77f8..6e3cc1d1834d79 100644
--- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
@@ -39,7 +39,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
// Convert pseudo subnormal number to normal number.
if (from_bits.get_implicit_bit() == 1 &&
- from_bits.get_biased_exponent() == 0) {
+ from_bits.is_subnormal()) {
from_bits.set_biased_exponent(1);
}
diff --git a/libc/utils/MPFRWrapper/MPFRUtils.cpp b/libc/utils/MPFRWrapper/MPFRUtils.cpp
index fca83c4cdc52f1..b6ca525db6cf74 100644
--- a/libc/utils/MPFRWrapper/MPFRUtils.cpp
+++ b/libc/utils/MPFRWrapper/MPFRUtils.cpp
@@ -457,9 +457,9 @@ class MPFRNumber {
int thisExponent = FPBits<T>(thisAsT).get_exponent();
int inputExponent = FPBits<T>(input).get_exponent();
// Adjust the exponents for denormal numbers.
- if (FPBits<T>(thisAsT).get_biased_exponent() == 0)
+ if (FPBits<T>(thisAsT).is_subnormal())
++thisExponent;
- if (FPBits<T>(input).get_biased_exponent() == 0)
+ if (FPBits<T>(input).is_subnormal())
++inputExponent;
if (thisAsT * input < 0 || thisExponent == inputExponent) {
@@ -481,9 +481,9 @@ class MPFRNumber {
int minExponent = FPBits<T>(min).get_exponent();
int maxExponent = FPBits<T>(max).get_exponent();
// Adjust the exponents for denormal numbers.
- if (FPBits<T>(min).get_biased_exponent() == 0)
+ if (FPBits<T>(min).is_subnormal())
++minExponent;
- if (FPBits<T>(max).get_biased_exponent() == 0)
+ if (FPBits<T>(max).is_subnormal())
++maxExponent;
MPFRNumber minMPFR(min);
>From c0996f7f2ec53017feade1a40d910850d6f59544 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 18 Jan 2024 19:18:16 +0000
Subject: [PATCH 2/2] Fix formatting, move `is_subnormal` and `is_zero` in
`FPRepBase`
---
libc/src/__support/FPUtil/FPBits.h | 27 +++++--------------
.../FPUtil/x86_64/NextAfterLongDouble.h | 3 +--
2 files changed, 8 insertions(+), 22 deletions(-)
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index e6c0f91c878f75..be700285de8285 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -386,8 +386,11 @@ struct FPRepBase : public internal::FPLayout<fp_type> {
bits = (value & FP_MASK);
}
- LIBC_INLINE constexpr bool is_zero() const {
- return (bits & EXP_SIG_MASK) == 0;
+ LIBC_INLINE constexpr bool is_zero() const { return exp_sig_bits() == 0; }
+
+ LIBC_INLINE
+ constexpr bool is_subnormal() const {
+ return exp_bits() == encode(BiasedExponent::BITS_ALL_ZEROES());
}
LIBC_INLINE constexpr bool is_neg() const { return sign().is_neg(); }
@@ -435,19 +438,11 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
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();
+ return is_finite() && !UP::is_subnormal();
}
LIBC_INLINE static constexpr StorageType zero(Sign sign = Sign::POS) {
@@ -488,7 +483,7 @@ template <FPType fp_type> struct FPRep : public FPRepBase<fp_type> {
// 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())
+ if (UP::is_subnormal())
return sig_bits();
return (StorageType(1) << UP::SIG_LEN) | sig_bits();
}
@@ -550,17 +545,9 @@ struct FPRep<FPType::X86_Binary80> : public FPRepBase<FPType::X86_Binary80> {
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_bits() == encode(BiasedExponent::BITS_ALL_ZEROES());
- }
LIBC_INLINE constexpr bool is_normal() const {
const auto exp = exp_bits();
if (exp == encode(BiasedExponent::BITS_ALL_ZEROES()) ||
diff --git a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
index 6e3cc1d1834d79..512f5de4e7931a 100644
--- a/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
+++ b/libc/src/__support/FPUtil/x86_64/NextAfterLongDouble.h
@@ -38,8 +38,7 @@ LIBC_INLINE long double nextafter(long double from, long double to) {
return to;
// Convert pseudo subnormal number to normal number.
- if (from_bits.get_implicit_bit() == 1 &&
- from_bits.is_subnormal()) {
+ if (from_bits.get_implicit_bit() == 1 && from_bits.is_subnormal()) {
from_bits.set_biased_exponent(1);
}
More information about the libc-commits
mailing list