diff options
author | Dominic Chen <ddchen@apple.com> | 2022-09-30 00:57:56 +0300 |
---|---|---|
committer | Dominic Chen <ddchen@apple.com> | 2022-10-07 07:11:47 +0300 |
commit | 74ec46796493738af8dd61c28d492a350a376063 (patch) | |
tree | 13bb05ee8367f631062afa37acb3d69f04a5b5f2 /libc | |
parent | e88e149fe4edb51e6409766bcdf96a54da84afe6 (diff) |
[libc] Resolve NaN/implementation-defined behavior of floating-point tests
Differential Revision: https://reviews.llvm.org/D134917
Diffstat (limited to 'libc')
22 files changed, 34 insertions, 23 deletions
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 @@ public: 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 @@ private: 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 @@ private: 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 @@ public: 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 @@ private: 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 @@ private: 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 @@ public: 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()); |