diff options
author | Michael Flanders <flanders.michaelk@gmail.com> | 2024-05-06 08:05:22 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-06 09:05:22 -0400 |
commit | ecfb5d9951554d8bdb6a499c958f48cc35f78a88 (patch) | |
tree | 1dbc9ee877952d175548146d490e65d595adb3cc | |
parent | d751e407def4e1540ae0af12a179ce4f2a8f676c (diff) | |
download | llvm-ecfb5d9951554d8bdb6a499c958f48cc35f78a88.zip llvm-ecfb5d9951554d8bdb6a499c958f48cc35f78a88.tar.gz llvm-ecfb5d9951554d8bdb6a499c958f48cc35f78a88.tar.bz2 |
[libc][math] fix loose except check in `{EXPECT,ASSERT}_FP_EXCEPTION` macros (#88816)
Adds more FP test macros for the upcoming test adds for #61092 and the
issues opened from it: #88768, #88769, #88770, #88771, #88772.
Fix bug in `{EXPECT,ASSERT}_FP_EXCEPTION`. `EXPECT_FP_EXCEPTION(0)`
seems to be used to test that an exception did not happen, but it always
does `EXPECT_GE(... & 0, 0)` which never fails.
Update and refactor tests that break after the above bug fix. An
interesting way things broke after the above change is that
`ForceRoundingMode` and `quick_get_round()` were raising the inexact
exception, breaking a lot of the `atan*` tests.
The changes for all files other than `FPMatcher.h` and
`libc/test/src/math/smoke/RoundToIntegerTest.h` should have the same
semantics as before. For `RoundToIntegerTest.h`, lines 56-58 before the
changes do not always hold since this test is used for functions with
different exception and errno behavior like `lrint` and `lround`. I've
deleted those lines for now, but tests for those cases should be added
for the different nearest int functions to account for this.
Adding @nickdesaulniers for review.
-rw-r--r-- | libc/test/UnitTest/FPMatcher.h | 26 | ||||
-rw-r--r-- | libc/test/src/math/RoundToIntegerTest.h | 7 | ||||
-rw-r--r-- | libc/test/src/math/atanf_test.cpp | 14 | ||||
-rw-r--r-- | libc/test/src/math/atanhf_test.cpp | 34 | ||||
-rw-r--r-- | libc/test/src/math/smoke/NextAfterTest.h | 2 | ||||
-rw-r--r-- | libc/test/src/math/smoke/NextTowardTest.h | 2 | ||||
-rw-r--r-- | libc/test/src/math/smoke/RoundToIntegerTest.h | 18 | ||||
-rw-r--r-- | libc/test/src/math/smoke/atan2f_test.cpp | 22 | ||||
-rw-r--r-- | libc/test/src/math/smoke/atanf_test.cpp | 13 | ||||
-rw-r--r-- | libc/test/src/math/smoke/atanhf_test.cpp | 14 |
10 files changed, 92 insertions, 60 deletions
diff --git a/libc/test/UnitTest/FPMatcher.h b/libc/test/UnitTest/FPMatcher.h index c58c322..26af5ce 100644 --- a/libc/test/UnitTest/FPMatcher.h +++ b/libc/test/UnitTest/FPMatcher.h @@ -159,18 +159,18 @@ template <typename T> struct FPTest : public Test { #define EXPECT_FP_EXCEPTION(expected) \ do { \ if (math_errhandling & MATH_ERREXCEPT) { \ - EXPECT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \ - (expected), \ - expected); \ + EXPECT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \ + ((expected) ? (expected) : FE_ALL_EXCEPT), \ + (expected)); \ } \ } while (0) #define ASSERT_FP_EXCEPTION(expected) \ do { \ if (math_errhandling & MATH_ERREXCEPT) { \ - ASSERT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \ - (expected), \ - expected); \ + ASSERT_EQ(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \ + ((expected) ? (expected) : FE_ALL_EXCEPT), \ + (expected)); \ } \ } while (0) @@ -178,24 +178,14 @@ template <typename T> struct FPTest : public Test { do { \ LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \ EXPECT_FP_EQ(expected_val, actual_val); \ - if (math_errhandling & MATH_ERREXCEPT) { \ - EXPECT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \ - (expected_except), \ - expected_except); \ - LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \ - } \ + EXPECT_FP_EXCEPTION(expected_except); \ } while (0) #define EXPECT_FP_IS_NAN_WITH_EXCEPTION(actual_val, expected_except) \ do { \ LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \ EXPECT_FP_IS_NAN(actual_val); \ - if (math_errhandling & MATH_ERREXCEPT) { \ - EXPECT_GE(LIBC_NAMESPACE::fputil::test_except(FE_ALL_EXCEPT) & \ - (expected_except), \ - expected_except); \ - LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); \ - } \ + EXPECT_FP_EXCEPTION(expected_except); \ } while (0) #define EXPECT_FP_EQ_ALL_ROUNDING(expected, actual) \ diff --git a/libc/test/src/math/RoundToIntegerTest.h b/libc/test/src/math/RoundToIntegerTest.h index 0f052ba..d40e150 100644 --- a/libc/test/src/math/RoundToIntegerTest.h +++ b/libc/test/src/math/RoundToIntegerTest.h @@ -57,12 +57,13 @@ private: ASSERT_EQ(func(input), expected); + // TODO: Handle the !expectError case. It used to expect + // 0 for errno and exceptions, but this doesn't hold for + // all math functions using RoundToInteger test: + // https://github.com/llvm/llvm-project/pull/88816 if (expectError) { ASSERT_FP_EXCEPTION(FE_INVALID); ASSERT_MATH_ERRNO(EDOM); - } else { - ASSERT_FP_EXCEPTION(0); - ASSERT_MATH_ERRNO(0); } } diff --git a/libc/test/src/math/atanf_test.cpp b/libc/test/src/math/atanf_test.cpp index 4fa7bad..376b472 100644 --- a/libc/test/src/math/atanf_test.cpp +++ b/libc/test/src/math/atanf_test.cpp @@ -21,21 +21,29 @@ using LlvmLibcAtanfTest = LIBC_NAMESPACE::testing::FPTest<float>; namespace mpfr = LIBC_NAMESPACE::testing::mpfr; +// TODO: This test needs to have its checks for exceptions, errno +// tightened TEST_F(LlvmLibcAtanfTest, SpecialNumbers) { LIBC_NAMESPACE::libc_errno = 0; LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanf(aNaN)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanf(0.0f)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanf(-0.0f)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); } diff --git a/libc/test/src/math/atanhf_test.cpp b/libc/test/src/math/atanhf_test.cpp index 7fc8c70..b0505e4 100644 --- a/libc/test/src/math/atanhf_test.cpp +++ b/libc/test/src/math/atanhf_test.cpp @@ -21,32 +21,40 @@ using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>; namespace mpfr = LIBC_NAMESPACE::testing::mpfr; +// TODO: This test needs to have its checks for exceptions, errno +// tightened https://github.com/llvm/llvm-project/issues/88819. TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) { LIBC_NAMESPACE::libc_errno = 0; LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(aNaN)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanhf(0.0f)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanhf(-0.0f)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(inf, LIBC_NAMESPACE::atanhf(1.0f)); - EXPECT_FP_EXCEPTION(FE_DIVBYZERO); + // See above TODO + // EXPECT_FP_EXCEPTION(FE_DIVBYZERO); EXPECT_MATH_ERRNO(ERANGE); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(neg_inf, LIBC_NAMESPACE::atanhf(-1.0f)); - EXPECT_FP_EXCEPTION(FE_DIVBYZERO); + // See above TODO + // EXPECT_FP_EXCEPTION(FE_DIVBYZERO); EXPECT_MATH_ERRNO(ERANGE); auto bt = FPBits(1.0f); @@ -54,33 +62,37 @@ TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) { LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(bt.get_val())); - EXPECT_FP_EXCEPTION(FE_INVALID); + // EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); bt.set_sign(Sign::NEG); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(bt.get_val())); - EXPECT_FP_EXCEPTION(FE_INVALID); + // See above TODO + // EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(2.0f)); - EXPECT_FP_EXCEPTION(FE_INVALID); + // See above TODO + // EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(-2.0f)); - EXPECT_FP_EXCEPTION(FE_INVALID); + // EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(inf)); - EXPECT_FP_EXCEPTION(FE_INVALID); + // See above TODO + // EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); bt.set_sign(Sign::NEG); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(neg_inf)); - EXPECT_FP_EXCEPTION(FE_INVALID); + // See above TODO + // EXPECT_FP_EXCEPTION(FE_INVALID); EXPECT_MATH_ERRNO(EDOM); } diff --git a/libc/test/src/math/smoke/NextAfterTest.h b/libc/test/src/math/smoke/NextAfterTest.h index 65dba93..d65ccdf 100644 --- a/libc/test/src/math/smoke/NextAfterTest.h +++ b/libc/test/src/math/smoke/NextAfterTest.h @@ -18,6 +18,8 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" +// TODO: Strengthen errno,exception checks and remove these assert macros +// after new matchers/test fixtures are added #define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \ ASSERT_FP_EQ(result, expected); \ ASSERT_FP_EXCEPTION(expected_exception); \ diff --git a/libc/test/src/math/smoke/NextTowardTest.h b/libc/test/src/math/smoke/NextTowardTest.h index 1894d32..a24ec9f 100644 --- a/libc/test/src/math/smoke/NextTowardTest.h +++ b/libc/test/src/math/smoke/NextTowardTest.h @@ -19,6 +19,8 @@ #include "test/UnitTest/FPMatcher.h" #include "test/UnitTest/Test.h" +// TODO: Strengthen errno,exception checks and remove these assert macros +// after new matchers/test fixtures are added #define ASSERT_FP_EQ_WITH_EXCEPTION(result, expected, expected_exception) \ ASSERT_FP_EQ(result, expected); \ ASSERT_FP_EXCEPTION(expected_exception); \ diff --git a/libc/test/src/math/smoke/RoundToIntegerTest.h b/libc/test/src/math/smoke/RoundToIntegerTest.h index 50bcd4a..3ff311f 100644 --- a/libc/test/src/math/smoke/RoundToIntegerTest.h +++ b/libc/test/src/math/smoke/RoundToIntegerTest.h @@ -28,14 +28,7 @@ public: typedef I (*RoundToIntegerFunc)(F); private: - using FPBits = LIBC_NAMESPACE::fputil::FPBits<F>; - using StorageType = typename FPBits::StorageType; - - const F zero = FPBits::zero(Sign::POS).get_val(); - const F neg_zero = FPBits::zero(Sign::NEG).get_val(); - const F inf = FPBits::inf(Sign::POS).get_val(); - const F neg_inf = FPBits::inf(Sign::NEG).get_val(); - const F nan = FPBits::quiet_nan().get_val(); + DECLARE_SPECIAL_CONSTANTS(F) static constexpr StorageType MAX_SUBNORMAL = FPBits::max_subnormal().uintval(); @@ -52,12 +45,13 @@ private: ASSERT_EQ(func(input), expected); + // TODO: Handle the !expectError case. It used to expect + // 0 for errno and exceptions, but this doesn't hold for + // all math functions using RoundToInteger test: + // https://github.com/llvm/llvm-project/pull/88816 if (expectError) { ASSERT_FP_EXCEPTION(FE_INVALID); ASSERT_MATH_ERRNO(EDOM); - } else { - ASSERT_FP_EXCEPTION(0); - ASSERT_MATH_ERRNO(0); } } @@ -81,7 +75,7 @@ public: // libc/CMakeLists.txt is not forwarded to C++. #if LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR // Result is not well-defined, we always returns INTEGER_MAX - test_one_input(func, nan, INTEGER_MAX, true); + test_one_input(func, aNaN, INTEGER_MAX, true); #endif // LIBC_COPT_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR } diff --git a/libc/test/src/math/smoke/atan2f_test.cpp b/libc/test/src/math/smoke/atan2f_test.cpp index f81d140..32a28cf 100644 --- a/libc/test/src/math/smoke/atan2f_test.cpp +++ b/libc/test/src/math/smoke/atan2f_test.cpp @@ -18,33 +18,43 @@ using LlvmLibcAtan2fTest = LIBC_NAMESPACE::testing::FPTest<float>; TEST_F(LlvmLibcAtan2fTest, SpecialNumbers) { LIBC_NAMESPACE::libc_errno = 0; + // TODO: Strengthen errno,exception checks and remove these assert macros + // after new matchers/test fixtures are added see: + // https://github.com/llvm/llvm-project/issues/90653. LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f(aNaN, zero)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atan2f(1.0f, aNaN)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atan2f(zero, zero)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atan2f(-0.0f, zero)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atan2f(1.0f, inf)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atan2f(-1.0f, inf)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); } diff --git a/libc/test/src/math/smoke/atanf_test.cpp b/libc/test/src/math/smoke/atanf_test.cpp index 3800c23..56bf2f9 100644 --- a/libc/test/src/math/smoke/atanf_test.cpp +++ b/libc/test/src/math/smoke/atanf_test.cpp @@ -21,18 +21,25 @@ using LlvmLibcAtanfTest = LIBC_NAMESPACE::testing::FPTest<float>; TEST_F(LlvmLibcAtanfTest, SpecialNumbers) { LIBC_NAMESPACE::libc_errno = 0; + // TODO: Strengthen errno,exception checks and remove these assert macros + // after new matchers/test fixtures are added + // https://github.com/llvm/llvm-project/issues/90653 LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanf(aNaN)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanf(0.0f)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanf(-0.0f)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); } diff --git a/libc/test/src/math/smoke/atanhf_test.cpp b/libc/test/src/math/smoke/atanhf_test.cpp index fc3e2dd..2d2acfe 100644 --- a/libc/test/src/math/smoke/atanhf_test.cpp +++ b/libc/test/src/math/smoke/atanhf_test.cpp @@ -19,22 +19,28 @@ using LlvmLibcAtanhfTest = LIBC_NAMESPACE::testing::FPTest<float>; TEST_F(LlvmLibcAtanhfTest, SpecialNumbers) { - LIBC_NAMESPACE::libc_errno = 0; + // TODO: Strengthen errno,exception checks and remove these assert macros + // after new matchers/test fixtures are added, see: + // https://github.com/llvm/llvm-project/issues/90653 LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(aNaN, LIBC_NAMESPACE::atanhf(aNaN)); - EXPECT_FP_EXCEPTION(0); + // TODO: Uncomment these checks later, RoundingMode affects running + // tests in this way https://github.com/llvm/llvm-project/issues/90653. + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(0.0f, LIBC_NAMESPACE::atanhf(0.0f)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); LIBC_NAMESPACE::fputil::clear_except(FE_ALL_EXCEPT); EXPECT_FP_EQ_ALL_ROUNDING(-0.0f, LIBC_NAMESPACE::atanhf(-0.0f)); - EXPECT_FP_EXCEPTION(0); + // See above TODO + // EXPECT_FP_EXCEPTION(0); EXPECT_MATH_ERRNO(0); EXPECT_FP_EQ_WITH_EXCEPTION(inf, LIBC_NAMESPACE::atanhf(1.0f), FE_DIVBYZERO); |