This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] powerpc: Fix inline feraiseexcept, feclearexcept macros


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.  */
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]