Re: [PATCH] libgfortran: Provide some further math library fallbacks [PR94694]

2020-04-22 Thread Jeff Law via Gcc-patches
On Wed, 2020-04-22 at 16:42 +0200, Jakub Jelinek via Gcc-patches wrote:
> Hi!
> 
> The following patch provides some further math library fallbacks.
> fmaf can be implemented using fma if available, fma and fmal can use
> x * y + z as fallback, it is not perfect, but e.g. glibc on various arches
> has been using that as fallback for many years,
> and copysign/copysignl/fabs/fabsl can be implemented using corresponding
> __builtin_* if we make sure that gcc expands it inline instead of using
> a library call (these days it is expanded inline on most targets).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux and Andrea Corallo
> has tested it on aarch64-elf.  Ok for trunk?
> 
> Fritz has a further patch for the PR to deal with cases where some functions
> aren't available and there is no easy fallback for them.
> 
> 2020-04-22  Jakub Jelinek  
> 
>   PR libfortran/94694
>   PR libfortran/94586
>   * configure.ac: Add math func checks for fmaf, fma and fmal.  Add
>   HAVE_INLINE_BUILTIN_COPYSIGN check.
>   * c99_protos.h (copysign, fmaf, fma, fmal): Provide fallback
>   prototypes.
>   (HAVE_COPYSIGN, HAVE_FMAF, HAVE_FMA, HAVE_FMAL): Define if not
>   defined and fallback version is provided.
>   * intrinsics/c99_functions.c (copysign, fmaf, fma, fmal): Provide
>   fallback implementations if possible
>   * configure: Regenerated.
>   * config.h.in: Regenerated.
Normally I try to stay out of libgfortran.  But I'll go ahead and ACK this.

The *-elf targets in my tester don't build fortran/libgfortran.  But I'm open to
possibly turning that on if they're stable enough.

jeff
> 



[PATCH] libgfortran: Provide some further math library fallbacks [PR94694]

2020-04-22 Thread Jakub Jelinek via Gcc-patches
Hi!

The following patch provides some further math library fallbacks.
fmaf can be implemented using fma if available, fma and fmal can use
x * y + z as fallback, it is not perfect, but e.g. glibc on various arches
has been using that as fallback for many years,
and copysign/copysignl/fabs/fabsl can be implemented using corresponding
__builtin_* if we make sure that gcc expands it inline instead of using
a library call (these days it is expanded inline on most targets).

Bootstrapped/regtested on x86_64-linux and i686-linux and Andrea Corallo
has tested it on aarch64-elf.  Ok for trunk?

Fritz has a further patch for the PR to deal with cases where some functions
aren't available and there is no easy fallback for them.

2020-04-22  Jakub Jelinek  

PR libfortran/94694
PR libfortran/94586
* configure.ac: Add math func checks for fmaf, fma and fmal.  Add
HAVE_INLINE_BUILTIN_COPYSIGN check.
* c99_protos.h (copysign, fmaf, fma, fmal): Provide fallback
prototypes.
(HAVE_COPYSIGN, HAVE_FMAF, HAVE_FMA, HAVE_FMAL): Define if not
defined and fallback version is provided.
* intrinsics/c99_functions.c (copysign, fmaf, fma, fmal): Provide
fallback implementations if possible
* configure: Regenerated.
* config.h.in: Regenerated.

--- config/math.m4.jj   2020-01-12 11:54:35.753423366 +0100
+++ config/math.m4  2020-04-21 21:30:13.870397648 +0200
@@ -48,3 +48,67 @@ main ()
[Define to 1 if you have the `$1' function.])
   fi
 ])
+
+dnl GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK1([name], [type])
+dnl
+dnl Check if math function NAME fallback for function with single
+dnl TYPE argument and TYPE result can be implemented using
+dnl __builtin_NAME expanded inline without needing unavailable math
+dnl library function.
+AC_DEFUN([GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK1],
+[
+  AC_REQUIRE([GCC_CHECK_LIBM])
+if test $gcc_cv_math_func_$1 = no; then
+  AC_CACHE_CHECK([for inline __builtin_$1], [gcc_cv_math_inline_builtin_$1],
+[AC_LINK_IFELSE([AC_LANG_SOURCE([
+$2
+$1_fallback ($2 x)
+{
+  return __builtin_$1 (x);
+}
+
+int
+main ()
+{
+  return 0;
+}
+])],
+[gcc_cv_math_inline_builtin_$1=yes],
+[gcc_cv_math_inline_builtin_$1=no])])
+  if test $gcc_cv_math_inline_builtin_$1 = yes; then
+AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_INLINE_BUILTIN_$1),[1],
+ [Define to 1 if `__builtin_$1' is expanded inline.])
+  fi
+fi])
+
+dnl GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK2([name], [type])
+dnl
+dnl Check if math function NAME fallback for function with two
+dnl TYPE arguments and TYPE result can be implemented using
+dnl __builtin_NAME expanded inline without needing unavailable math
+dnl library function.
+AC_DEFUN([GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK2],
+[
+  AC_REQUIRE([GCC_CHECK_LIBM])
+if test $gcc_cv_math_func_$1 = no; then
+  AC_CACHE_CHECK([for inline __builtin_$1], [gcc_cv_math_inline_builtin_$1],
+[AC_LINK_IFELSE([AC_LANG_SOURCE([
+$2
+$1_fallback ($2 x, $2 y)
+{
+  return __builtin_$1 (x, y);
+}
+
+int
+main ()
+{
+  return 0;
+}
+])],
+[gcc_cv_math_inline_builtin_$1=yes],
+[gcc_cv_math_inline_builtin_$1=no])])
+  if test $gcc_cv_math_inline_builtin_$1 = yes; then
+AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_INLINE_BUILTIN_$1),[1],
+ [Define to 1 if `__builtin_$1' is expanded inline.])
+  fi
+fi])
--- libgfortran/configure.ac.jj 2020-01-24 22:34:36.340641225 +0100
+++ libgfortran/configure.ac2020-04-21 21:31:25.435319945 +0200
@@ -392,6 +392,9 @@ GCC_CHECK_MATH_FUNC([cabsl])
 GCC_CHECK_MATH_FUNC([floorf])
 GCC_CHECK_MATH_FUNC([floor])
 GCC_CHECK_MATH_FUNC([floorl])
+GCC_CHECK_MATH_FUNC([fmaf])
+GCC_CHECK_MATH_FUNC([fma])
+GCC_CHECK_MATH_FUNC([fmal])
 GCC_CHECK_MATH_FUNC([fmodf])
 GCC_CHECK_MATH_FUNC([fmod])
 GCC_CHECK_MATH_FUNC([fmodl])
@@ -516,6 +519,11 @@ GCC_CHECK_MATH_FUNC([catanl])
 # On AIX, clog is present in libm as __clog
 AC_CHECK_LIB([m],[__clog],[AC_DEFINE([HAVE_CLOG],[1],[libm includes clog])])
 
+GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK2([copysign], [double])
+GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK2([copysignl], [long double])
+GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK1([fabs], [double])
+GCC_CHECK_MATH_INLINE_BUILTIN_FALLBACK1([fabsl], [long double])
+
 # Check whether the system has a working stat()
 LIBGFOR_CHECK_WORKING_STAT
 
--- libgfortran/c99_protos.h.jj 2020-01-12 11:54:38.707378799 +0100
+++ libgfortran/c99_protos.h2020-04-21 21:33:57.949023242 +0200
@@ -71,6 +71,16 @@ extern float ceilf(float);
 extern float copysignf(float, float);
 #endif
 
+#if !defined(HAVE_COPYSIGN) && defined(HAVE_INLINE_BUILTIN_COPYSIGN)
+#define HAVE_COPYSIGN 1
+extern double copysign(double, double);
+#endif
+
+#if !defined(HAVE_COPYSIGNL) && defined(HAVE_INLINE_BUILTIN_COPYSIGNL)
+#define HAVE_COPYSIGNL 1
+extern long double copysignl(long double, long double);
+#endif
+
 #ifndef HAVE_COSF
 #define HAVE_COSF 1
 extern float cosf(float);
@@ -91,6 +101,16 @@