This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] powerpc: Fix inline feraiseexcept, feclearexcept macros
- From: Adhemerval Zanella <azanella at linux dot vnet dot ibm dot com>
- To: libc-alpha at sourceware dot org
- Cc: "Joseph S. Myers" <joseph at codesourcery dot com>
- Date: Mon, 09 Feb 2015 11:24:09 -0200
- Subject: Re: [PATCH] powerpc: Fix inline feraiseexcept, feclearexcept macros
- Authentication-results: sourceware.org; auth=none
- References: <54C2C558 dot 2050304 at linux dot vnet dot ibm dot com> <alpine dot DEB dot 2 dot 10 dot 1501240219420 dot 15542 at digraph dot polyomino dot org dot uk> <54C6449B dot 60609 at linux dot vnet dot ibm dot com> <alpine dot DEB dot 2 dot 10 dot 1501261804490 dot 28603 at digraph dot polyomino dot org dot uk> <54C7DC43 dot 7040500 at linux dot vnet dot ibm dot com>
Ping (with NEWS adjusted to 2.22).
> Indeed, I have dropped the conditionals (I used test-fenv.c as base, but I think
> in this context they are not really required).
>
> Tested on powerpc64 with fix for BZ#17885 applied.
>
> --
>
> [BZ #17776]
> * sysdeps/powerpc/bits/fenvinline.h (feraiseexcept): Convert input to
> integer before bitwise and assembly operations.
> (feclearexcept): Likewise.
> * math/test-fenvinline.c: New file.
> * math/Makefile: Add test-fenvinline test.
>
> --
>
> diff --git a/NEWS b/NEWS
> index 1dcfc7d..97c4d66 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -17,8 +17,8 @@ Version 2.21
> 17601, 17608, 17616, 17625, 17630, 17633, 17634, 17635, 17647, 17653,
> 17657, 17658, 17664, 17665, 17668, 17682, 17702, 17717, 17719, 17722,
> 17723, 17724, 17725, 17732, 17733, 17744, 17745, 17746, 17747, 17748,
> - 17775, 17777, 17780, 17781, 17782, 17791, 17793, 17796, 17797, 17803,
> - 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885
> + 17775, 17776, 17777, 17780, 17781, 17782, 17791, 17793, 17796, 17797,
> + 17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885
>
> * A new semaphore algorithm has been implemented in generic C code for all
> machines. Previous custom assembly implementations of semaphore were
> diff --git a/math/Makefile b/math/Makefile
> index fec7627..3904e41 100644
> --- a/math/Makefile
> +++ b/math/Makefile
> @@ -90,7 +90,8 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
> test-misc test-fpucw test-fpucw-ieee tst-definitions test-tgmath \
> test-tgmath-ret bug-nextafter bug-nexttoward bug-tgmath1 \
> test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \
> - test-fenv-tls test-fenv-preserve test-fenv-return $(tests-static)
> + test-fenv-tls test-fenv-preserve test-fenv-return test-fenvinline \
> + $(tests-static)
> tests-static = test-fpucw-static test-fpucw-ieee-static
> # We do the `long double' tests only if this data type is available and
> # distinct from `double'.
> diff --git a/math/test-fenvinline.c b/math/test-fenvinline.c
> new file mode 100644
> index 0000000..53e5f16
> --- /dev/null
> +++ b/math/test-fenvinline.c
> @@ -0,0 +1,173 @@
> +/* Test for fenv inline implementations.
> + Copyright (C) 2015 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
> + <http://www.gnu.org/licenses/>. */
> +
> +#ifndef _GNU_SOURCE
> +# define _GNU_SOURCE
> +#endif
> +
> +/* To make sure the fenv inline function are used. */
> +#undef __NO_MATH_INLINES
> +
> +#include <fenv.h>
> +#include <stdio.h>
> +
> +/*
> + Since not all architectures might define all exceptions, we define
> + a private set and map accordingly.
> +*/
> +#define NO_EXC 0
> +#define INEXACT_EXC 0x1
> +#define DIVBYZERO_EXC 0x2
> +#define UNDERFLOW_EXC 0x04
> +#define OVERFLOW_EXC 0x08
> +#define INVALID_EXC 0x10
> +#define ALL_EXC \
> + (INEXACT_EXC | DIVBYZERO_EXC | UNDERFLOW_EXC | OVERFLOW_EXC | \
> + INVALID_EXC)
> +static int count_errors;
> +
> +#if FE_ALL_EXCEPT
> +/* Test whether a given exception was raised. */
> +static void
> +test_single_exception_fp (int exception,
> + int exc_flag,
> + double fe_flag,
> + const char *flag_name)
> +{
> + if (exception & exc_flag)
> + {
> + if (fetestexcept (fe_flag))
> + printf (" Pass: Exception \"%s\" is set\n", flag_name);
> + else
> + {
> + printf (" Fail: Exception \"%s\" is not set\n", flag_name);
> + ++count_errors;
> + }
> + }
> + else
> + {
> + if (fetestexcept (fe_flag))
> + {
> + printf (" Fail: Exception \"%s\" is set\n", flag_name);
> + ++count_errors;
> + }
> + else
> + printf (" Pass: Exception \"%s\" is not set\n", flag_name);
> + }
> +}
> +#endif
> +
> +static void
> +test_exceptions (const char *test_name, int exception)
> +{
> + printf ("Test: %s\n", test_name);
> +#ifdef FE_DIVBYZERO
> + test_single_exception_fp (exception, DIVBYZERO_EXC, FE_DIVBYZERO,
> + "DIVBYZERO");
> +#endif
> +#ifdef FE_INVALID
> + test_single_exception_fp (exception, INVALID_EXC, FE_INVALID,
> + "INVALID");
> +#endif
> +#ifdef FE_INEXACT
> + test_single_exception_fp (exception, INEXACT_EXC, FE_INEXACT,
> + "INEXACT");
> +#endif
> +#ifdef FE_UNDERFLOW
> + test_single_exception_fp (exception, UNDERFLOW_EXC, FE_UNDERFLOW,
> + "UNDERFLOW");
> +#endif
> +#ifdef FE_OVERFLOW
> + test_single_exception_fp (exception, OVERFLOW_EXC, FE_OVERFLOW,
> + "OVERFLOW");
> +#endif
> +}
> +
> +static void
> +test_exceptionflag (void)
> +{
> + printf ("Test: fegetexceptionflag (FE_ALL_EXCEPT)\n");
> +#if FE_ALL_EXCEPT
> + fexcept_t excepts;
> +
> + feclearexcept (FE_ALL_EXCEPT);
> +
> + feraiseexcept (FE_INVALID);
> + fegetexceptflag (&excepts, FE_ALL_EXCEPT);
> +
> + feclearexcept (FE_ALL_EXCEPT);
> + feraiseexcept (FE_OVERFLOW | FE_INEXACT);
> +
> + fesetexceptflag (&excepts, FE_ALL_EXCEPT);
> +
> + test_single_exception_fp (INVALID_EXC, INVALID_EXC, FE_INVALID,
> + "INVALID");
> + test_single_exception_fp (INVALID_EXC, OVERFLOW_EXC, FE_OVERFLOW,
> + "OVERFLOW");
> + test_single_exception_fp (INVALID_EXC, INEXACT_EXC, FE_INEXACT,
> + "OVERFLOW");
> +
> + /* Same test, but using double as argument */
> + feclearexcept (FE_ALL_EXCEPT);
> +
> + feraiseexcept (FE_INVALID);
> + fegetexceptflag (&excepts, (double)FE_ALL_EXCEPT);
> +
> + feclearexcept (FE_ALL_EXCEPT);
> + feraiseexcept (FE_OVERFLOW | FE_INEXACT);
> +
> + fesetexceptflag (&excepts, (double)FE_ALL_EXCEPT);
> +
> + test_single_exception_fp (INVALID_EXC, INVALID_EXC, FE_INVALID,
> + "INVALID (double)");
> + test_single_exception_fp (INVALID_EXC, OVERFLOW_EXC, FE_OVERFLOW,
> + "OVERFLOW (double)");
> + test_single_exception_fp (INVALID_EXC, INEXACT_EXC, FE_INEXACT,
> + "OVERFLOW (double)");
> +#endif
> +}
> +
> +static int
> +do_test (void)
> +{
> + /* clear all exceptions and test if all are cleared */
> + feclearexcept (FE_ALL_EXCEPT);
> + test_exceptions ("feclearexcept (FE_ALL_EXCEPT) clears all exceptions",
> + NO_EXC);
> +
> + /* raise all exceptions and test if all are raised */
> + feraiseexcept (FE_ALL_EXCEPT);
> + test_exceptions ("feraiseexcept (FE_ALL_EXCEPT) raises all exceptions",
> + ALL_EXC);
> +
> + /* Same test, but using double as argument */
> + feclearexcept ((double)FE_ALL_EXCEPT);
> + test_exceptions ("feclearexcept ((double)FE_ALL_EXCEPT) clears all exceptions",
> + NO_EXC);
> +
> + feraiseexcept ((double)FE_ALL_EXCEPT);
> + test_exceptions ("feraiseexcept ((double)FE_ALL_EXCEPT) raises all exceptions",
> + ALL_EXC);
> +
> + test_exceptionflag ();
> +
> + return count_errors;
> +}
> +
> +#define TEST_FUNCTION do_test ()
> +#include "../test-skeleton.c"
> diff --git a/sysdeps/powerpc/bits/fenvinline.h b/sysdeps/powerpc/bits/fenvinline.h
> index 35c2114..894789e 100644
> --- a/sysdeps/powerpc/bits/fenvinline.h
> +++ b/sysdeps/powerpc/bits/fenvinline.h
> @@ -34,29 +34,41 @@
>
> /* Inline definition for feraiseexcept. */
> # define feraiseexcept(__excepts) \
> - ((__builtin_constant_p (__excepts) \
> - && ((__excepts) & ((__excepts)-1)) == 0 \
> - && (__excepts) != FE_INVALID) \
> - ? ((__excepts) != 0 \
> - ? (__extension__ ({ __asm__ __volatile__ \
> - ("mtfsb1 %s0" \
> - : : "i#*X"(__builtin_ffs (__excepts))); \
> - 0; })) \
> - : 0) \
> - : (feraiseexcept) (__excepts))
> + (__extension__ ({ \
> + int __e = __excepts; \
> + int __ret; \
> + if (__builtin_constant_p (__e) \
> + && (__e & (__e - 1)) == 0 \
> + && __e != FE_INVALID) \
> + { \
> + if (__e != 0) \
> + __asm__ __volatile__ ("mtfsb1 %s0" \
> + : : "i#*X" (__builtin_ffs (__e))); \
> + __ret = 0; \
> + } \
> + else \
> + __ret = feraiseexcept (__e); \
> + __ret; \
> + }))
>
> /* Inline definition for feclearexcept. */
> # define feclearexcept(__excepts) \
> - ((__builtin_constant_p (__excepts) \
> - && ((__excepts) & ((__excepts)-1)) == 0 \
> - && (__excepts) != FE_INVALID) \
> - ? ((__excepts) != 0 \
> - ? (__extension__ ({ __asm__ __volatile__ \
> - ("mtfsb0 %s0" \
> - : : "i#*X"(__builtin_ffs (__excepts))); \
> - 0; })) \
> - : 0) \
> - : (feclearexcept) (__excepts))
> + (__extension__ ({ \
> + int __e = __excepts; \
> + int __ret; \
> + if (__builtin_constant_p (__e) \
> + && (__e & (__e - 1)) == 0 \
> + && __e != FE_INVALID) \
> + { \
> + if (__e != 0) \
> + __asm__ __volatile__ ("mtfsb0 %s0" \
> + : : "i#*X" (__builtin_ffs (__e))); \
> + __ret = 0; \
> + } \
> + else \
> + __ret = feclearexcept (__e); \
> + __ret; \
> + }))
>
> # endif /* !__NO_MATH_INLINES. */
>
>