[libc-commits] [libc] 74ec467 - [libc] Resolve NaN/implementation-defined behavior of floating-point tests
Dominic Chen via libc-commits
libc-commits at lists.llvm.org
Thu Oct 6 21:13:15 PDT 2022
Author: Dominic Chen
Date: 2022-10-06T21:11:47-07:00
New Revision: 74ec46796493738af8dd61c28d492a350a376063
URL: https://github.com/llvm/llvm-project/commit/74ec46796493738af8dd61c28d492a350a376063
DIFF: https://github.com/llvm/llvm-project/commit/74ec46796493738af8dd61c28d492a350a376063.diff
LOG: [libc] Resolve NaN/implementation-defined behavior of floating-point tests
Differential Revision: https://reviews.llvm.org/D134917
Added:
Modified:
libc/CMakeLists.txt
libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
libc/src/__support/FPUtil/FPBits.h
libc/src/__support/FPUtil/generic/FMod.h
libc/src/__support/FPUtil/generic/sqrt.h
libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
libc/src/__support/str_to_float.h
libc/src/math/generic/atanf.cpp
libc/src/math/generic/atanhf.cpp
libc/test/src/math/FDimTest.h
libc/test/src/math/FmaTest.h
libc/test/src/math/HypotTest.h
libc/test/src/math/ILogbTest.h
libc/test/src/math/LdExpTest.h
libc/test/src/math/NextAfterTest.h
libc/test/src/math/RIntTest.h
libc/test/src/math/RemQuoTest.h
libc/test/src/math/RoundToIntegerTest.h
libc/test/src/math/atanf_test.cpp
libc/test/src/math/atanhf_test.cpp
libc/utils/UnitTest/FPMatcher.h
Removed:
################################################################################
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 2c403b98cf41..eff5e00453f5 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -49,7 +49,7 @@ else()
endif()
option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc" OFF)
-
+option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON)
option(LLVM_LIBC_ENABLE_LINTING "Enables linting of libc source files" OFF)
if(LLVM_LIBC_CLANG_TIDY)
diff --git a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
index 6af682cc4cac..6a55525108d6 100644
--- a/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
+++ b/libc/src/__support/FPUtil/DivisionAndRemainderOperations.h
@@ -30,7 +30,7 @@ static 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_nan(1);
+ 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 af6891decfb8..fd62a790585c 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -170,6 +170,10 @@ template <typename T> struct FPBits {
return T(bits);
}
+ static constexpr T build_quiet_nan(UIntType v) {
+ return build_nan(FloatProp::QUIET_NAN_MASK | v);
+ }
+
// The function convert integer number and unbiased exponent to proper float
// T type:
// Result = number * 2^(ep+1 - exponent_bias)
diff --git a/libc/src/__support/FPUtil/generic/FMod.h b/libc/src/__support/FPUtil/generic/FMod.h
index 836238210e6b..c20bd8950b9d 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 {
static bool PreCheck(T x, T y, T &out) {
using FPB = fputil::FPBits<T>;
- const T quiet_NaN = FPB::build_nan(FPB::FloatProp::QUIET_NAN_MASK);
+ const T quiet_NaN = FPB::build_quiet_nan(0);
FPB sx(x), sy(y);
if (likely(!sy.is_zero() && !sy.is_inf_or_nan() && !sx.is_inf_or_nan())) {
return false;
diff --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index a6c1e649672f..125d864672bb 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -79,7 +79,7 @@ static inline cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
if (bits.is_inf_or_nan()) {
if (bits.get_sign() && (bits.get_mantissa() == 0)) {
// sqrt(-Inf) = NaN
- return FPBits<T>::build_nan(ONE >> 1);
+ return FPBits<T>::build_quiet_nan(ONE >> 1);
} else {
// sqrt(NaN) = NaN
// sqrt(+Inf) = +Inf
@@ -91,7 +91,7 @@ static inline cpp::enable_if_t<cpp::is_floating_point_v<T>, T> sqrt(T x) {
return x;
} else if (bits.get_sign()) {
// sqrt( negative numbers ) = NaN
- return FPBits<T>::build_nan(ONE >> 1);
+ return FPBits<T>::build_quiet_nan(ONE >> 1);
} else {
int x_exp = bits.get_exponent();
UIntType x_mant = bits.get_mantissa();
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 2943c7d54a13..cf3b2e4aa8d4 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
@@ -44,7 +44,7 @@ static inline long double sqrt(long double x) {
if (bits.is_inf_or_nan()) {
if (bits.get_sign() && (bits.get_mantissa() == 0)) {
// sqrt(-Inf) = NaN
- return FPBits<long double>::build_nan(ONE >> 1);
+ return FPBits<long double>::build_quiet_nan(ONE >> 1);
} else {
// sqrt(NaN) = NaN
// sqrt(+Inf) = +Inf
@@ -56,7 +56,7 @@ static inline long double sqrt(long double x) {
return x;
} else if (bits.get_sign()) {
// sqrt( negative numbers ) = NaN
- return FPBits<long double>::build_nan(ONE >> 1);
+ return FPBits<long double>::build_quiet_nan(ONE >> 1);
} else {
int x_exp = bits.get_exponent();
UIntType x_mant = bits.get_mantissa();
diff --git a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
index 6992000d0615..57e1923795bf 100644
--- a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
+++ b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
@@ -185,6 +185,10 @@ template <> struct FPBits<long double> {
return bits;
}
+ static long double build_quiet_nan(UIntType v) {
+ return build_nan(FloatProp::QUIET_NAN_MASK | v);
+ }
+
inline static FPBits<long double>
create_value(bool sign, UIntType unbiased_exp, UIntType mantissa) {
FPBits<long double> result;
diff --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 4f952bcb54e1..bc0d574f650c 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -971,11 +971,11 @@ static inline T strtofloatingpoint(const char *__restrict src,
}
nan_mantissa |= fputil::FloatProperties<T>::QUIET_NAN_MASK;
if (result.get_sign()) {
- result = fputil::FPBits<T>(result.build_nan(nan_mantissa));
+ result = fputil::FPBits<T>(result.build_quiet_nan(nan_mantissa));
result.set_sign(true);
} else {
result.set_sign(false);
- result = fputil::FPBits<T>(result.build_nan(nan_mantissa));
+ result = fputil::FPBits<T>(result.build_quiet_nan(nan_mantissa));
}
}
} else if ((*src | 32) == 'i') { // INF
diff --git a/libc/src/math/generic/atanf.cpp b/libc/src/math/generic/atanf.cpp
index 490a77c61b91..d27db5931347 100644
--- a/libc/src/math/generic/atanf.cpp
+++ b/libc/src/math/generic/atanf.cpp
@@ -23,7 +23,7 @@ LLVM_LIBC_FUNCTION(float, atanf, (float x)) {
if (xbits.is_inf())
return opt_barrier(sign ? -M_MATH_PI_2 : M_MATH_PI_2);
else
- return x + 1.0f;
+ return x;
}
// |x| == 0.06905200332403183
if (unlikely(xbits.uintval() == 0x3d8d6b23U)) {
diff --git a/libc/src/math/generic/atanhf.cpp b/libc/src/math/generic/atanhf.cpp
index 0d015101090a..7f39e9914588 100644
--- a/libc/src/math/generic/atanhf.cpp
+++ b/libc/src/math/generic/atanhf.cpp
@@ -21,7 +21,7 @@ LLVM_LIBC_FUNCTION(float, atanhf, (float x)) {
// |x| >= 1.0
if (unlikely(x_abs >= 0x3F80'0000U)) {
if (xbits.is_nan()) {
- return x + 1.0f;
+ return x;
}
// |x| == 0
if (x_abs == 0x3F80'0000U) {
diff --git a/libc/test/src/math/FDimTest.h b/libc/test/src/math/FDimTest.h
index 587913acb1f1..5763e04f95f3 100644
--- a/libc/test/src/math/FDimTest.h
+++ b/libc/test/src/math/FDimTest.h
@@ -74,7 +74,7 @@ class FDimTestTemplate : public __llvm_libc::testing::Test {
private:
// constexpr does not work on FPBits yet, so we cannot have these constants as
// static.
- const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(1));
+ const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
diff --git a/libc/test/src/math/FmaTest.h b/libc/test/src/math/FmaTest.h
index 959c4e837a77..4726267cea40 100644
--- a/libc/test/src/math/FmaTest.h
+++ b/libc/test/src/math/FmaTest.h
@@ -23,7 +23,7 @@ class FmaTestTemplate : public __llvm_libc::testing::Test {
using Func = T (*)(T, T, T);
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
- const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(1));
+ const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
const T zero = T(__llvm_libc::fputil::FPBits<T>::zero());
diff --git a/libc/test/src/math/HypotTest.h b/libc/test/src/math/HypotTest.h
index 57abef8b6234..b110bcee3311 100644
--- a/libc/test/src/math/HypotTest.h
+++ b/libc/test/src/math/HypotTest.h
@@ -24,7 +24,7 @@ class HypotTestTemplate : public __llvm_libc::testing::Test {
using Func = T (*)(T, T);
using FPBits = __llvm_libc::fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
- const T nan = T(FPBits::build_nan(1));
+ const T nan = T(FPBits::build_quiet_nan(1));
const T inf = T(FPBits::inf());
const T neg_inf = T(FPBits::neg_inf());
const T zero = T(FPBits::zero());
diff --git a/libc/test/src/math/ILogbTest.h b/libc/test/src/math/ILogbTest.h
index e2de14de446d..b026b0557f9c 100644
--- a/libc/test/src/math/ILogbTest.h
+++ b/libc/test/src/math/ILogbTest.h
@@ -26,7 +26,7 @@ class LlvmLibcILogbTest : public __llvm_libc::testing::Test {
EXPECT_EQ(FP_ILOGB0, func(T(__llvm_libc::fputil::FPBits<T>::neg_zero())));
EXPECT_EQ(FP_ILOGBNAN,
- func(T(__llvm_libc::fputil::FPBits<T>::build_nan(1))));
+ func(T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1))));
EXPECT_EQ(INT_MAX, func(T(__llvm_libc::fputil::FPBits<T>::inf())));
EXPECT_EQ(INT_MAX, func(T(__llvm_libc::fputil::FPBits<T>::neg_inf())));
diff --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h
index ca9f33f2f816..5830fc37a6f5 100644
--- a/libc/test/src/math/LdExpTest.h
+++ b/libc/test/src/math/LdExpTest.h
@@ -32,7 +32,7 @@ class LdExpTestTemplate : public __llvm_libc::testing::Test {
const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
- const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(1));
+ const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));
public:
typedef T (*LdExpFunc)(T, int);
diff --git a/libc/test/src/math/NextAfterTest.h b/libc/test/src/math/NextAfterTest.h
index fcc2c43a5aac..12c9bb988ab7 100644
--- a/libc/test/src/math/NextAfterTest.h
+++ b/libc/test/src/math/NextAfterTest.h
@@ -30,7 +30,7 @@ class NextAfterTestTemplate : public __llvm_libc::testing::Test {
const T neg_zero = T(FPBits::neg_zero());
const T inf = T(FPBits::inf());
const T neg_inf = T(FPBits::neg_inf());
- const T nan = T(FPBits::build_nan(1));
+ const T nan = T(FPBits::build_quiet_nan(1));
const UIntType min_subnormal = FPBits::MIN_SUBNORMAL;
const UIntType max_subnormal = FPBits::MAX_SUBNORMAL;
const UIntType min_normal = FPBits::MIN_NORMAL;
diff --git a/libc/test/src/math/RIntTest.h b/libc/test/src/math/RIntTest.h
index 90945feb6789..de5652b03272 100644
--- a/libc/test/src/math/RIntTest.h
+++ b/libc/test/src/math/RIntTest.h
@@ -37,7 +37,7 @@ class RIntTestTemplate : public __llvm_libc::testing::Test {
const T neg_zero = T(FPBits::neg_zero());
const T inf = T(FPBits::inf());
const T neg_inf = T(FPBits::neg_inf());
- const T nan = T(FPBits::build_nan(1));
+ const T nan = T(FPBits::build_quiet_nan(1));
static inline mpfr::RoundingMode to_mpfr_rounding_mode(int mode) {
switch (mode) {
diff --git a/libc/test/src/math/RemQuoTest.h b/libc/test/src/math/RemQuoTest.h
index 5903760c1969..3428f8d6758e 100644
--- a/libc/test/src/math/RemQuoTest.h
+++ b/libc/test/src/math/RemQuoTest.h
@@ -27,7 +27,7 @@ class RemQuoTestTemplate : public __llvm_libc::testing::Test {
const T neg_zero = T(__llvm_libc::fputil::FPBits<T>::neg_zero());
const T inf = T(__llvm_libc::fputil::FPBits<T>::inf());
const T neg_inf = T(__llvm_libc::fputil::FPBits<T>::neg_inf());
- const T nan = T(__llvm_libc::fputil::FPBits<T>::build_nan(1));
+ const T nan = T(__llvm_libc::fputil::FPBits<T>::build_quiet_nan(1));
public:
typedef T (*RemQuoFunc)(T, T, int *);
diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h
index 27a19e11c27a..a7627b2f50cd 100644
--- a/libc/test/src/math/RoundToIntegerTest.h
+++ b/libc/test/src/math/RoundToIntegerTest.h
@@ -36,7 +36,7 @@ class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test {
const F neg_zero = F(__llvm_libc::fputil::FPBits<F>::neg_zero());
const F inf = F(__llvm_libc::fputil::FPBits<F>::inf());
const F neg_inf = F(__llvm_libc::fputil::FPBits<F>::neg_inf());
- const F nan = F(__llvm_libc::fputil::FPBits<F>::build_nan(1));
+ const F nan = F(__llvm_libc::fputil::FPBits<F>::build_quiet_nan(1));
static constexpr I INTEGER_MIN = I(1) << (sizeof(I) * 8 - 1);
static constexpr I INTEGER_MAX = -(INTEGER_MIN + 1);
@@ -84,7 +84,10 @@ class RoundToIntegerTestTemplate : public __llvm_libc::testing::Test {
void do_infinity_and_na_n_test(RoundToIntegerFunc func) {
test_one_input(func, inf, INTEGER_MAX, true);
test_one_input(func, neg_inf, INTEGER_MIN, true);
+#if LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR
+ // Result is not well-defined, we always returns INTEGER_MAX
test_one_input(func, nan, INTEGER_MAX, true);
+#endif
}
void testInfinityAndNaN(RoundToIntegerFunc func) {
diff --git a/libc/test/src/math/atanf_test.cpp b/libc/test/src/math/atanf_test.cpp
index 8dc61bb55a4c..28c5fcd30057 100644
--- a/libc/test/src/math/atanf_test.cpp
+++ b/libc/test/src/math/atanf_test.cpp
@@ -28,7 +28,7 @@ TEST(LlvmLibcAtanfTest, SpecialNumbers) {
errno = 0;
__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ(aNaN, __llvm_libc::atanf(aNaN));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
diff --git a/libc/test/src/math/atanhf_test.cpp b/libc/test/src/math/atanhf_test.cpp
index 306fc1962df5..ad6d56d10ead 100644
--- a/libc/test/src/math/atanhf_test.cpp
+++ b/libc/test/src/math/atanhf_test.cpp
@@ -26,7 +26,7 @@ TEST(LlvmLibcAtanhfTest, SpecialNumbers) {
errno = 0;
__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
EXPECT_FP_EQ(aNaN, __llvm_libc::atanhf(aNaN));
- EXPECT_FP_EXCEPTION(FE_INVALID);
+ EXPECT_FP_EXCEPTION(0);
EXPECT_MATH_ERRNO(0);
__llvm_libc::fputil::clear_except(FE_ALL_EXCEPT);
diff --git a/libc/utils/UnitTest/FPMatcher.h b/libc/utils/UnitTest/FPMatcher.h
index 0dd9754035e3..1c2b54067563 100644
--- a/libc/utils/UnitTest/FPMatcher.h
+++ b/libc/utils/UnitTest/FPMatcher.h
@@ -72,7 +72,7 @@ FPMatcher<T, C> getMatcher(T expectedValue) {
using UIntType = typename FPBits::UIntType; \
const T zero = T(FPBits::zero()); \
const T neg_zero = T(FPBits::neg_zero()); \
- const T aNaN = T(FPBits::build_nan(1)); \
+ const T aNaN = T(FPBits::build_quiet_nan(1)); \
const T inf = T(FPBits::inf()); \
const T neg_inf = T(FPBits::neg_inf());
More information about the libc-commits
mailing list