From patchwork Thu Oct 16 16:37:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Senkevich X-Patchwork-Id: 3249 Received: (qmail 24160 invoked by alias); 16 Oct 2014 16:37:42 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 24118 invoked by uid 89); 16 Oct 2014 16:37:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qg0-f49.google.com X-Received: by 10.229.212.202 with SMTP id gt10mr3972909qcb.0.1413477455427; Thu, 16 Oct 2014 09:37:35 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: <54246CB5.7020908@redhat.com> <5424733D.6010305@redhat.com> <54247FAB.6050002@redhat.com> <54257507.9070508@redhat.com> <542AF92E.8090708@lip6.fr> From: Andrew Senkevich Date: Thu, 16 Oct 2014 20:37:05 +0400 Message-ID: Subject: Re: [RFC] How to add vector math functions to Glibc To: "Joseph S. Myers" Cc: libc-alpha Hi, Joseph, here is the patch with test suite changes with fixes based on your previous comments. >> @@ -6258,7 +6274,11 @@ static const struct test_f_f_data cos_test_data[] = >> static void >> cos_test (void) >> { >> +#ifndef TEST_MATHVEC >> ALL_RM_TEST (cos, 0, cos_test_data, RUN_TEST_LOOP_f_f, END); >> +#else >> + TN_RM_TEST (vector_cos, 0, cos_test_data, RUN_TEST_LOOP_f_f, END); >> +#endif >> } > > And I don't think we want conditionals like this for every function - > indeed, the tests shouldn't need to know which functions have vector > versions at all. Do you mean to use the same *_test function for testing vector (through wrapper)? I have such scheme now but it requires to add macros named as standard function and it also caused changes in START macros. >> +CFLAGS-test-vec-double.c = -fno-inline -ffloat-store -fno-builtin >> -frounding-math -mavx2 -Wno-unused-function > > And since you can't determine at configure > time what host the tests might run on, instruction set features such as > AVX need testing for at runtime (this means building separate source files > for the test with separate options so that you know the compiler won't > generate AVX code before you've tested for AVX availability). Because of vector tests grouped by ISA we have different test driver names containing vector length (test-double-vlen4.c for AVX2). Scalar wrappers (called from test driver) will be in separate files (test-double-vlen4-wrapper.c) and will be built with architecture-specific options specified in sysdeps Makefile. For runtime check we need to insert condition before wrapper start so with help of new macros added in *_test function that condition could be defined in test driver. Now I have built test-double-vlen4 manually and if this way is ok I will prepare that sysdeps Makefile. +#include "libm-test.c" --- WBR, Andrew diff --git a/math/libm-test.inc b/math/libm-test.inc index f86a4fa..9ddb77e 100644 --- a/math/libm-test.inc +++ b/math/libm-test.inc @@ -684,7 +684,7 @@ static void test_single_errno (const char *test_name, int errno_value, int expected_value, const char *expected_name) { -#ifndef TEST_INLINE +#if !defined TEST_INLINE && !defined TEST_MATHVEC if (errno_value == expected_value) { if (print_screen (1)) @@ -1691,8 +1691,9 @@ struct test_fFF_11_data ROUND_RESTORE_ ## ROUNDING_MODE /* Start and end the tests for a given function. */ -#define START(FUNC, EXACT) \ - const char *this_func = #FUNC; \ +#define STR_CON(x,y) __STRING(x##y) +#define START(FUNC, SUFF, EXACT) \ + const char *this_func = STR_CON (FUNC, SUFF); \ init_max_error (this_func, EXACT) #define END \ print_max_error (this_func) @@ -1705,28 +1706,28 @@ struct test_fFF_11_data { \ do \ { \ - START (FUNC, EXACT); \ + START (FUNC, , EXACT); \ LOOP_MACRO (FUNC, ARRAY, , ## __VA_ARGS__); \ END_MACRO; \ } \ while (0); \ do \ { \ - START (FUNC ## _downward, EXACT); \ + START (FUNC, _downward, EXACT); \ LOOP_MACRO (FUNC, ARRAY, FE_DOWNWARD, ## __VA_ARGS__); \ END_MACRO; \ } \ while (0); \ do \ { \ - START (FUNC ## _towardzero, EXACT); \ + START (FUNC, _towardzero, EXACT); \ LOOP_MACRO (FUNC, ARRAY, FE_TOWARDZERO, ## __VA_ARGS__); \ END_MACRO; \ } \ while (0); \ do \ { \ - START (FUNC ## _upward, EXACT); \ + START (FUNC, _upward, EXACT); \ LOOP_MACRO (FUNC, ARRAY, FE_UPWARD, ## __VA_ARGS__); \ END_MACRO; \ } \ @@ -6034,7 +6035,7 @@ static const struct test_c_c_data cexp_test_data[] = static void cexp_test (void) { - START (cexp, 0); + START (cexp, , 0); RUN_TEST_LOOP_c_c (cexp, cexp_test_data, ); END_COMPLEX; } @@ -6247,7 +6248,7 @@ copysign_test (void) static const struct test_f_f_data cos_test_data[] = - { + { TEST_f_f (cos, plus_infty, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM), TEST_f_f (cos, minus_infty, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM), TEST_f_f (cos, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), @@ -6255,9 +6256,14 @@ static const struct test_f_f_data cos_test_data[] = AUTO_TESTS_f_f (cos), }; +#ifndef CHECKARCH +# define CHECKARCH +#endif + static void cos_test (void) { + CHECKARCH ALL_RM_TEST (cos, 0, cos_test_data, RUN_TEST_LOOP_f_f, END); } @@ -7548,7 +7554,7 @@ static const struct test_if_f_data jn_test_data[] = static void jn_test (void) { - START (jn, 0); + START (jn, , 0); RUN_TEST_LOOP_if_f (jn, jn_test_data, ); END; } @@ -9374,7 +9380,7 @@ static const struct test_f_f_data tgamma_test_data[] = static void tgamma_test (void) { - START (tgamma, 0); + START (tgamma, , 0); RUN_TEST_LOOP_f_f (tgamma, tgamma_test_data, ); END; } @@ -9824,6 +9830,12 @@ main (int argc, char **argv) initialize (); printf (TEST_MSG); + /* Vector trigonometric functions: */ +#ifdef TEST_MATHVEC + + cos_test (); + +#else check_ulp (); /* Keep the tests a wee bit ordered (according to ISO C99). */ @@ -9960,6 +9972,7 @@ main (int argc, char **argv) y0_test (); y1_test (); yn_test (); +#endif if (output_ulps) fclose (ulps_file); diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps index 36e1b76..0e11cd5 100644 --- a/sysdeps/x86_64/fpu/libm-test-ulps +++ b/sysdeps/x86_64/fpu/libm-test-ulps @@ -905,6 +905,12 @@ idouble: 1 ildouble: 2 ldouble: 2 + +Function: "vlen4_cos": +double: 1 + Function: "cosh": double: 1 float: 1 diff --git a/sysdeps/x86_64/fpu/test-double-vlen4-wrapper.c b/sysdeps/x86_64/fpu/test-double-vlen4-wrapper.c new file mode 100644 index 0000000..35e130e --- /dev/null +++ b/sysdeps/x86_64/fpu/test-double-vlen4-wrapper.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define FLOAT double + +// Wrapper from scalar to vector function implemented in AVX2. +#define VECTOR_WRAPPER(scalar_func,vector_func) \ +extern __m256d vector_func(__m256d); \ +FLOAT scalar_func(FLOAT x)\ +{\ + int i;\ + __m256d mx = _mm256_set1_pd(x);\ + __m256d mr = vector_func(mx);\ + for(i=1;i<4;i++)\ + {\ + if (((FLOAT*)&mr)[0]!=((FLOAT*)&mr)[i])\ + {\ + return ((FLOAT*)&mr)[0]+0.1;\ + }\ + }\ + return ((FLOAT*)&mr)[0];\ +} + +#include + +VECTOR_WRAPPER(vlen4_cos,_ZGVdN4v_cos) diff --git a/sysdeps/x86_64/fpu/test-double-vlen4.c b/sysdeps/x86_64/fpu/test-double-vlen4.c new file mode 100644 index 0000000..ce40c04 --- /dev/null +++ b/sysdeps/x86_64/fpu/test-double-vlen4.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define FUNC(function) function +#define FLOAT double +#define TEST_MSG "testing double vector math (without inline functions)\n" +#define MATHCONST(x) x +#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cdouble +#define PRINTF_EXPR "e" +#define PRINTF_XEXPR "a" +#define PRINTF_NEXPR "f" +#define TEST_DOUBLE 1 + +#ifndef __NO_MATH_INLINES +# define __NO_MATH_INLINES +#endif + +#define TEST_MATHVEC +#define EXCEPTION_TESTS_double 0 +#define ROUNDING_TESTS_double(MODE) ((MODE) == FE_TONEAREST) + +#define cos vlen4_cos + +#include + +#define CHECKARCH \ +__init_cpu_features();\ +if (__cpu_features.feature[index_AVX2_Usable] & bit_AVX2_Usable) +