From 262112840ca3807d2e5c7227a476be88be5740a7 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 26 May 2016 16:38:04 +0000 Subject: Support sNaN testing in libm-test.inc. This patch adds support in libm-test.inc for tests with signaling NaN arguments. gen-libm-test.pl is made to set a flag TEST_SNAN for such tests, so that they can be disabled automatically when sNaN testing isn't supported for a given type (at present, for float and double on 32-bit x86 because it's unpredictable when a value might be loaded into a floating-point register and so automatically converted to long double with sNaNs converted to quiet NaNs). -fsignaling-nans is used where needed. Tests are added for classification macros, as a starting point; this is deliberately more conservative than Thomas's patch , to allow more tests to be added, and issues exposed fixed, bit by bit. Tested for x86_64 and x86. * math/libm-test.inc: Update comment about NaN testing. (TEST_SNAN): New macro. (snan_value): Likewise. (enable_test): Disable tests of sNaNs when SNAN_TESTS fails. (fpclassify_test_data): Add sNaN tests. (isfinite_test_data): Likewise. (isinf_test_data): Likewise. (isnan_test_data): Likewise. (isnormal_test_data): Likewise. (issignaling_test_data): Likewise. (signbit_test_data): Likewise. * math/gen-libm-test.pl (%beautify): Add snan_value. (show_exceptions): Add argument $test_snan. (parse_args): Handle snan_value as non-finite. Update call to show_exceptions. * math/Makefile (libm-test-no-inline-cflags): Add -fsignaling-nans. --- ChangeLog | 20 ++++++++++++++++++++ math/Makefile | 9 ++++++++- math/gen-libm-test.pl | 14 +++++++++----- math/libm-test.inc | 21 +++++++++++++++++++-- 4 files changed, 56 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index ecedf6f6e6..1c8023b278 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2016-05-26 Joseph Myers + + * math/libm-test.inc: Update comment about NaN testing. + (TEST_SNAN): New macro. + (snan_value): Likewise. + (enable_test): Disable tests of sNaNs when SNAN_TESTS fails. + (fpclassify_test_data): Add sNaN tests. + (isfinite_test_data): Likewise. + (isinf_test_data): Likewise. + (isnan_test_data): Likewise. + (isnormal_test_data): Likewise. + (issignaling_test_data): Likewise. + (signbit_test_data): Likewise. + * math/gen-libm-test.pl (%beautify): Add snan_value. + (show_exceptions): Add argument $test_snan. + (parse_args): Handle snan_value as non-finite. Update call to + show_exceptions. + * math/Makefile (libm-test-no-inline-cflags): Add + -fsignaling-nans. + 2016-05-26 Adhemerval Zanella * nptl/Makefile (CFLAGS-oldrecvfrom.c): Remove rule. diff --git a/math/Makefile b/math/Makefile index 57c3ec15aa..f0265bb640 100644 --- a/math/Makefile +++ b/math/Makefile @@ -187,7 +187,14 @@ CFLAGS-test-float-vlen8-wrappers.c = $(float-vlen8-arch-ext-cflags) CFLAGS-test-float-vlen16.c = $(libm-test-vec-cflags) CFLAGS-test-float-vlen16-wrappers.c = $(float-vlen16-arch-ext-cflags) -libm-test-no-inline-cflags = -fno-inline -ffloat-store -fno-builtin +# The no-inline tests use -fsignaling-nans, and thereby use the +# versions of classification macros that support sNaNs. The inline +# function tests use the versions of classification macros that may +# raise spurious exceptions for sNaNs, but also do not test for +# exceptions. Thus both versions of the classification macros are +# validated. +libm-test-no-inline-cflags = -fno-inline -ffloat-store -fno-builtin \ + -fsignaling-nans libm-test-finite-cflags = $(libm-test-no-inline-cflags) \ -U__FINITE_MATH_ONLY__ -D__FINITE_MATH_ONLY__=1 CFLAGS-test-float.c = $(libm-test-no-inline-cflags) diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl index 17f17f7493..c42a53b1e5 100755 --- a/math/gen-libm-test.pl +++ b/math/gen-libm-test.pl @@ -59,6 +59,7 @@ use vars qw (%auto_tests); "minus_infty" => "-inf", "plus_infty" => "inf", "qnan_value" => "qNaN", + "snan_value" => "sNaN", ); @@ -141,13 +142,14 @@ sub build_complex_beautify { # Return the text to put in an initializer for a test's exception # information. sub show_exceptions { - my ($ignore_result, $non_finite, $exception) = @_; + my ($ignore_result, $non_finite, $test_snan, $exception) = @_; $ignore_result = ($ignore_result ? "IGNORE_RESULT|" : ""); $non_finite = ($non_finite ? "NON_FINITE|" : ""); + $test_snan = ($test_snan ? "TEST_SNAN|" : ""); if (defined $exception) { - return ", ${ignore_result}${non_finite}$exception"; + return ", ${ignore_result}${non_finite}${test_snan}$exception"; } else { - return ", ${ignore_result}${non_finite}0"; + return ", ${ignore_result}${non_finite}${test_snan}0"; } } @@ -163,7 +165,7 @@ sub parse_args { my (@plus_oflow, @minus_oflow, @plus_uflow, @minus_uflow); my (@errno_plus_oflow, @errno_minus_oflow); my (@errno_plus_uflow, @errno_minus_uflow); - my ($non_finite); + my ($non_finite, $test_snan); ($descr_args, $descr_res) = split /_/,$descr, 2; @@ -310,10 +312,12 @@ sub parse_args { } # Determine whether any arguments or results, for any rounding # mode, are non-finite. - $non_finite = ($args =~ /qnan_value|plus_infty|minus_infty/); + $non_finite = ($args =~ /qnan_value|snan_value|plus_infty|minus_infty/); + $test_snan = ($args =~ /snan_value/); # Add exceptions. $cline_res .= show_exceptions ($ignore_result_any, $non_finite, + $test_snan, ($current_arg <= $#args_res) ? $args_res[$current_arg] : undef); diff --git a/math/libm-test.inc b/math/libm-test.inc index 169be7e85f..7d29700775 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -79,8 +79,7 @@ against. These implemented tests should check all cases that are specified in ISO C99. - NaN values: There exist signalling and quiet NaNs. This implementation - only uses quiet NaN as parameter. The payload of NaNs is not examined. + NaN values: The payload of NaNs is not examined. Inline functions: Inlining functions should give an improvement in speed - but not in precission. The inlined functions return @@ -182,6 +181,7 @@ struct ulp_data /* Flags generated by gen-libm-test.pl, not entered here manually. */ #define IGNORE_RESULT 0x20000 #define NON_FINITE 0x40000 +#define TEST_SNAN 0x80000 /* Values underflowing only for float. */ #ifdef TEST_FLOAT @@ -311,6 +311,7 @@ static int ignore_max_ulp; /* Should we ignore max_ulp? */ #define minus_infty CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF, \ -HUGE_VALL, -HUGE_VAL, -HUGE_VALF) #define qnan_value FUNC (__builtin_nan) ("") +#define snan_value FUNC (__builtin_nans) ("") #define max_value CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX, \ LDBL_MAX, DBL_MAX, FLT_MAX) #define min_value CHOOSE (LDBL_MIN, DBL_MIN, FLT_MIN, \ @@ -1050,6 +1051,8 @@ enable_test (int exceptions) return 0; if (TEST_FINITE && (exceptions & NON_FINITE) != 0) return 0; + if (!SNAN_TESTS (FLOAT) && (exceptions & TEST_SNAN) != 0) + return 0; return 1; } @@ -7691,6 +7694,8 @@ static const struct test_f_i_data fpclassify_test_data[] = { TEST_f_i (fpclassify, qnan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_i (fpclassify, -qnan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_i (fpclassify, snan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_i (fpclassify, -snan_value, FP_NAN, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_i (fpclassify, plus_infty, FP_INFINITE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_i (fpclassify, minus_infty, FP_INFINITE, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_i (fpclassify, plus_zero, FP_ZERO, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), @@ -7932,6 +7937,8 @@ static const struct test_f_i_data isfinite_test_data[] = TEST_f_b (isfinite, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isfinite, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isfinite, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isfinite, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isfinite, -snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), }; static void @@ -8032,6 +8039,8 @@ static const struct test_f_i_data isinf_test_data[] = TEST_f_b (isinf, minus_infty, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isinf, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isinf, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isinf, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isinf, -snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), }; static void @@ -8160,6 +8169,8 @@ static const struct test_f_i_data isnan_test_data[] = TEST_f_b (isnan, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isnan, qnan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isnan, -qnan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isnan, snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isnan, -snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), }; static void @@ -8183,6 +8194,8 @@ static const struct test_f_i_data isnormal_test_data[] = TEST_f_b (isnormal, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isnormal, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (isnormal, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isnormal, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (isnormal, -snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), }; static void @@ -8206,6 +8219,8 @@ static const struct test_f_i_data issignaling_test_data[] = TEST_f_b (issignaling, minus_infty, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (issignaling, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (issignaling, -qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (issignaling, snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (issignaling, -snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), }; static void @@ -11245,6 +11260,8 @@ static const struct test_f_i_data signbit_test_data[] = TEST_f_b (signbit, minus_infty, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (signbit, qnan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), TEST_f_b (signbit, -qnan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (signbit, snan_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_f_b (signbit, -snan_value, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), /* signbit (x) != 0 for x < 0. */ TEST_f_b (signbit, -1, 1, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), -- cgit 1.4.1