[newlib] Generally make all 'long double complex' methods available in <complex.h>

Message ID 20221108183108.1233500-1-thomas@codesourcery.com
State Unresolved
Headers
Series [newlib] Generally make all 'long double complex' methods available in <complex.h> |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Thomas Schwinge Nov. 8, 2022, 6:31 p.m. UTC
  ..., not just '#if defined(__CYGWIN__)'.  (Exception: 'clog10l' which currently
indeed is for Cygwin only.)

This completes 2017-07-05 commit be3ca3947402827aa52709e677369bc7ad30aa1d
"Fixed warnings for some long double complex methods" after Aditya Upadhyay's
work on importing "Long double complex methods" from NetBSD.

For example, this changes GCC/nvptx libgfortran 'configure' output as follows:

    [...]
    checking for ccosf... yes
    checking for ccos... yes
    checking for ccosl... [-no-]{+yes+}
    [...]

..., and correspondingly GCC/nvptx 'nvptx-none/libgfortran/config.h' as
follows:

    [...]
     /* Define to 1 if you have the `ccosl' function. */
    -/* #undef HAVE_CCOSL */
    +#define HAVE_CCOSL 1
    [...]

Similarly for 'ccoshl', 'cexpl', 'cpowl', 'csinl', 'csinhl', 'ctanl', 'ctanhl',
'cacoshl', 'cacosl', 'casinhl', 'catanhl'.  ('conjl', 'cprojl' are not
currently being used in libgfortran.)

This in turn simplifies GCC/nvptx 'libgfortran/intrinsics/c99_functions.c'
compilation such that this files doesn't have to provide its own
"Implementation of various C99 functions" for those, when in fact they're
available in newlib libm.
---

A few more words on why this is relevant for GCC.

For example, 'cexpl' usually is provided by libm, but if it isn't, the
open-coded replacement function in
'libgfortran/intrinsics/c99_functions.c' is effective if it holds that
'defined(HAVE_COSL) && defined(HAVE_SINL) && defined(HAVE_EXPL)':

    long double complex
    cexpl (long double complex z)
    {
      long double a, b;
      long double complex v;

      a = REALPART (z);
      b = IMAGPART (z);
      COMPLEX_ASSIGN (v, cosl (b), sinl (b));
      return expl (a) * v;
    }

This replacement code is active for current GCC/nvptx (... if no longer
compiling GCC/nvptx libgfortran in "minimal" mode, 'LIBGFOR_MINIMAL',
which I'm currently working on).

Comparing the preceeding to the 'c99_functions.c.188t.sincos' dump, we see for
that function:

     __attribute__((nothrow, leaf, const))
     complex long double cexpl (complex long double z)
     {
       long double b;
       long double a;
       long double _1;
       long double _2;
       long double _4;
       long double _5;
       long double _11;
    +  complex long double sincostmp_13;

       <bb 2> [local count: 1073741824]:
       a_7 = REALPART_EXPR <z_6(D)>;
       b_8 = IMAGPART_EXPR <z_6(D)>;
    -  _1 = cosl (b_8);
    -  _2 = sinl (b_8);
    +  sincostmp_13 = __builtin_cexpil (b_8);
    +  _1 = REALPART_EXPR <sincostmp_13>;
    +  _2 = IMAGPART_EXPR <sincostmp_13>;
       _11 = expl (a_7);
       _4 = _1 * _11;
       _5 = _2 * _11;
       REALPART_EXPR <<retval>> = _4;
       IMAGPART_EXPR <<retval>> = _5;
       return <retval>;

     }

That is, the 'cosl (b)', 'sinl (b)' sequence is replaced by
'__builtin_cexpil'.  That '__builtin_cexpil' is then later mapped back
into: 'cexpl'.  We've now got an infinitely-recursive 'cexpl' replacement
function, "implemented via itself"; GCC/nvptx libgfortran assumes there
is no 'cexpl' in libm, whereas this 'sincos' transformation does assume
that there is.  (..., which looks like an additional bug on its own.)

At the PTX-level, this leads to the following:

    [...]
    // BEGIN GLOBAL FUNCTION DECL: cexpl
    .visible .func cexpl (.param.u64 %in_ar0, .param.f64 %in_ar1, .param.f64 %in_ar2);

    // BEGIN GLOBAL FUNCTION DEF: cexpl
    .visible .func cexpl (.param.u64 %in_ar0, .param.f64 %in_ar1, .param.f64 %in_ar2)
    {
            [...]
                    call cexpl, (%out_arg1, %out_arg2, %out_arg3);
            [...]
            ret;
    }

    [...]
    // BEGIN GLOBAL FUNCTION DECL: cexpl
    .extern .func cexpl (.param.u64 %in_ar0, .param.f64 %in_ar1, .param.f64 %in_ar2);
    [...]

We see the '.visible .func cexpl' declaration and definition for the
libgfortran replacement function and in the same compilation unit also
the '.extern .func cexpl' declaration that implicitly gets introduced via
the 'sincos' transformation (via the GCC/nvptx back end emitting an
explicit declaration of any function referenced), and 'ptxas' then
(rightfully so) complains about that mismatch:

    ptxas c99_functions.o, line 35; error   : Inconsistent redefinition of variable 'cexpl'
    ptxas fatal   : Ptx assembly aborted due to errors
    nvptx-as: ptxas returned 255 exit status
    make[2]: *** [c99_functions.lo] Error 1

---
 newlib/libc/include/complex.h | 35 ++++++++++++++++-------------------
 1 file changed, 16 insertions(+), 19 deletions(-)

--
2.25.1

-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
  

Comments

Jeff Johnston Nov. 8, 2022, 8:24 p.m. UTC | #1
LGTM.

-- Jeff J.

On Tue, Nov 8, 2022 at 1:31 PM Thomas Schwinge <thomas@codesourcery.com>
wrote:

> ..., not just '#if defined(__CYGWIN__)'.  (Exception: 'clog10l' which
> currently
> indeed is for Cygwin only.)
>
> This completes 2017-07-05 commit be3ca3947402827aa52709e677369bc7ad30aa1d
> "Fixed warnings for some long double complex methods" after Aditya
> Upadhyay's
> work on importing "Long double complex methods" from NetBSD.
>
> For example, this changes GCC/nvptx libgfortran 'configure' output as
> follows:
>
>     [...]
>     checking for ccosf... yes
>     checking for ccos... yes
>     checking for ccosl... [-no-]{+yes+}
>     [...]
>
> ..., and correspondingly GCC/nvptx 'nvptx-none/libgfortran/config.h' as
> follows:
>
>     [...]
>      /* Define to 1 if you have the `ccosl' function. */
>     -/* #undef HAVE_CCOSL */
>     +#define HAVE_CCOSL 1
>     [...]
>
> Similarly for 'ccoshl', 'cexpl', 'cpowl', 'csinl', 'csinhl', 'ctanl',
> 'ctanhl',
> 'cacoshl', 'cacosl', 'casinhl', 'catanhl'.  ('conjl', 'cprojl' are not
> currently being used in libgfortran.)
>
> This in turn simplifies GCC/nvptx 'libgfortran/intrinsics/c99_functions.c'
> compilation such that this files doesn't have to provide its own
> "Implementation of various C99 functions" for those, when in fact they're
> available in newlib libm.
> ---
>
> A few more words on why this is relevant for GCC.
>
> For example, 'cexpl' usually is provided by libm, but if it isn't, the
> open-coded replacement function in
> 'libgfortran/intrinsics/c99_functions.c' is effective if it holds that
> 'defined(HAVE_COSL) && defined(HAVE_SINL) && defined(HAVE_EXPL)':
>
>     long double complex
>     cexpl (long double complex z)
>     {
>       long double a, b;
>       long double complex v;
>
>       a = REALPART (z);
>       b = IMAGPART (z);
>       COMPLEX_ASSIGN (v, cosl (b), sinl (b));
>       return expl (a) * v;
>     }
>
> This replacement code is active for current GCC/nvptx (... if no longer
> compiling GCC/nvptx libgfortran in "minimal" mode, 'LIBGFOR_MINIMAL',
> which I'm currently working on).
>
> Comparing the preceeding to the 'c99_functions.c.188t.sincos' dump, we see
> for
> that function:
>
>      __attribute__((nothrow, leaf, const))
>      complex long double cexpl (complex long double z)
>      {
>        long double b;
>        long double a;
>        long double _1;
>        long double _2;
>        long double _4;
>        long double _5;
>        long double _11;
>     +  complex long double sincostmp_13;
>
>        <bb 2> [local count: 1073741824]:
>        a_7 = REALPART_EXPR <z_6(D)>;
>        b_8 = IMAGPART_EXPR <z_6(D)>;
>     -  _1 = cosl (b_8);
>     -  _2 = sinl (b_8);
>     +  sincostmp_13 = __builtin_cexpil (b_8);
>     +  _1 = REALPART_EXPR <sincostmp_13>;
>     +  _2 = IMAGPART_EXPR <sincostmp_13>;
>        _11 = expl (a_7);
>        _4 = _1 * _11;
>        _5 = _2 * _11;
>        REALPART_EXPR <<retval>> = _4;
>        IMAGPART_EXPR <<retval>> = _5;
>        return <retval>;
>
>      }
>
> That is, the 'cosl (b)', 'sinl (b)' sequence is replaced by
> '__builtin_cexpil'.  That '__builtin_cexpil' is then later mapped back
> into: 'cexpl'.  We've now got an infinitely-recursive 'cexpl' replacement
> function, "implemented via itself"; GCC/nvptx libgfortran assumes there
> is no 'cexpl' in libm, whereas this 'sincos' transformation does assume
> that there is.  (..., which looks like an additional bug on its own.)
>
> At the PTX-level, this leads to the following:
>
>     [...]
>     // BEGIN GLOBAL FUNCTION DECL: cexpl
>     .visible .func cexpl (.param.u64 %in_ar0, .param.f64 %in_ar1,
> .param.f64 %in_ar2);
>
>     // BEGIN GLOBAL FUNCTION DEF: cexpl
>     .visible .func cexpl (.param.u64 %in_ar0, .param.f64 %in_ar1,
> .param.f64 %in_ar2)
>     {
>             [...]
>                     call cexpl, (%out_arg1, %out_arg2, %out_arg3);
>             [...]
>             ret;
>     }
>
>     [...]
>     // BEGIN GLOBAL FUNCTION DECL: cexpl
>     .extern .func cexpl (.param.u64 %in_ar0, .param.f64 %in_ar1,
> .param.f64 %in_ar2);
>     [...]
>
> We see the '.visible .func cexpl' declaration and definition for the
> libgfortran replacement function and in the same compilation unit also
> the '.extern .func cexpl' declaration that implicitly gets introduced via
> the 'sincos' transformation (via the GCC/nvptx back end emitting an
> explicit declaration of any function referenced), and 'ptxas' then
> (rightfully so) complains about that mismatch:
>
>     ptxas c99_functions.o, line 35; error   : Inconsistent redefinition of
> variable 'cexpl'
>     ptxas fatal   : Ptx assembly aborted due to errors
>     nvptx-as: ptxas returned 255 exit status
>     make[2]: *** [c99_functions.lo] Error 1
>
> ---
>  newlib/libc/include/complex.h | 35 ++++++++++++++++-------------------
>  1 file changed, 16 insertions(+), 19 deletions(-)
>
> diff --git a/newlib/libc/include/complex.h b/newlib/libc/include/complex.h
> index 0a3ea97ed..ad3028e4c 100644
> --- a/newlib/libc/include/complex.h
> +++ b/newlib/libc/include/complex.h
> @@ -20,6 +20,7 @@ __BEGIN_DECLS
>  /* 7.3.5.1 The cacos functions */
>  double complex cacos(double complex);
>  float complex cacosf(float complex);
> +long double complex cacosl(long double complex);
>
>  /* 7.3.5.2 The casin functions */
>  double complex casin(double complex);
> @@ -34,44 +35,54 @@ long double complex catanl(long double complex);
>  /* 7.3.5.1 The ccos functions */
>  double complex ccos(double complex);
>  float complex ccosf(float complex);
> +long double complex ccosl(long double complex);
>
>  /* 7.3.5.1 The csin functions */
>  double complex csin(double complex);
>  float complex csinf(float complex);
> +long double complex csinl(long double complex);
>
>  /* 7.3.5.1 The ctan functions */
>  double complex ctan(double complex);
>  float complex ctanf(float complex);
> +long double complex ctanl(long double complex);
>
>  /* 7.3.6 Hyperbolic functions */
>  /* 7.3.6.1 The cacosh functions */
>  double complex cacosh(double complex);
>  float complex cacoshf(float complex);
> +long double complex cacoshl(long double complex);
>
>  /* 7.3.6.2 The casinh functions */
>  double complex casinh(double complex);
>  float complex casinhf(float complex);
> +long double complex casinhl(long double complex);
>
>  /* 7.3.6.3 The catanh functions */
>  double complex catanh(double complex);
>  float complex catanhf(float complex);
> +long double complex catanhl(long double complex);
>
>  /* 7.3.6.4 The ccosh functions */
>  double complex ccosh(double complex);
>  float complex ccoshf(float complex);
> +long double complex ccoshl(long double complex);
>
>  /* 7.3.6.5 The csinh functions */
>  double complex csinh(double complex);
>  float complex csinhf(float complex);
> +long double complex csinhl(long double complex);
>
>  /* 7.3.6.6 The ctanh functions */
>  double complex ctanh(double complex);
>  float complex ctanhf(float complex);
> +long double complex ctanhl(long double complex);
>
>  /* 7.3.7 Exponential and logarithmic functions */
>  /* 7.3.7.1 The cexp functions */
>  double complex cexp(double complex);
>  float complex cexpf(float complex);
> +long double complex cexpl(long double complex);
>
>  /* 7.3.7.2 The clog functions */
>  double complex clog(double complex);
> @@ -93,6 +104,7 @@ float cabsf(float complex) ;
>  /* 7.3.8.2 The cpow functions */
>  double complex cpow(double complex, double complex);
>  float complex cpowf(float complex, float complex);
> +long double complex cpowl(long double complex, long double complex);
>
>  /* 7.3.8.3 The csqrt functions */
>  double complex csqrt(double complex);
> @@ -113,10 +125,12 @@ long double cimagl(long double complex);
>  /* 7.3.9.3 The conj functions */
>  double complex conj(double complex);
>  float complex conjf(float complex);
> +long double complex conjl(long double complex);
>
>  /* 7.3.9.4 The cproj functions */
>  double complex cproj(double complex);
>  float complex cprojf(float complex);
> +long double complex cprojl(long double complex);
>
>  /* 7.3.9.5 The creal functions */
>  double creal(double complex);
> @@ -126,27 +140,10 @@ long double creall(long double complex);
>  #if __GNU_VISIBLE
>  double complex clog10(double complex);
>  float complex clog10f(float complex);
> -#endif
> -
> -#if defined(__CYGWIN__)
> -long double complex cacosl(long double complex);
> -long double complex ccosl(long double complex);
> -long double complex csinl(long double complex);
> -long double complex ctanl(long double complex);
> -long double complex cacoshl(long double complex);
> -long double complex casinhl(long double complex);
> -long double complex catanhl(long double complex);
> -long double complex ccoshl(long double complex);
> -long double complex csinhl(long double complex);
> -long double complex ctanhl(long double complex);
> -long double complex cexpl(long double complex);
> -long double complex cpowl(long double complex, long double complex);
> -long double complex conjl(long double complex);
> -long double complex cprojl(long double complex);
> -#if __GNU_VISIBLE
> +# if defined(__CYGWIN__)
>  long double complex clog10l(long double complex);
> +# endif
>  #endif
> -#endif /* __CYGWIN__ */
>
>  __END_DECLS
>
> --
> 2.25.1
>
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201,
> 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer:
> Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München;
> Registergericht München, HRB 106955
>
>
  

Patch

diff --git a/newlib/libc/include/complex.h b/newlib/libc/include/complex.h
index 0a3ea97ed..ad3028e4c 100644
--- a/newlib/libc/include/complex.h
+++ b/newlib/libc/include/complex.h
@@ -20,6 +20,7 @@  __BEGIN_DECLS
 /* 7.3.5.1 The cacos functions */
 double complex cacos(double complex);
 float complex cacosf(float complex);
+long double complex cacosl(long double complex);

 /* 7.3.5.2 The casin functions */
 double complex casin(double complex);
@@ -34,44 +35,54 @@  long double complex catanl(long double complex);
 /* 7.3.5.1 The ccos functions */
 double complex ccos(double complex);
 float complex ccosf(float complex);
+long double complex ccosl(long double complex);

 /* 7.3.5.1 The csin functions */
 double complex csin(double complex);
 float complex csinf(float complex);
+long double complex csinl(long double complex);

 /* 7.3.5.1 The ctan functions */
 double complex ctan(double complex);
 float complex ctanf(float complex);
+long double complex ctanl(long double complex);

 /* 7.3.6 Hyperbolic functions */
 /* 7.3.6.1 The cacosh functions */
 double complex cacosh(double complex);
 float complex cacoshf(float complex);
+long double complex cacoshl(long double complex);

 /* 7.3.6.2 The casinh functions */
 double complex casinh(double complex);
 float complex casinhf(float complex);
+long double complex casinhl(long double complex);

 /* 7.3.6.3 The catanh functions */
 double complex catanh(double complex);
 float complex catanhf(float complex);
+long double complex catanhl(long double complex);

 /* 7.3.6.4 The ccosh functions */
 double complex ccosh(double complex);
 float complex ccoshf(float complex);
+long double complex ccoshl(long double complex);

 /* 7.3.6.5 The csinh functions */
 double complex csinh(double complex);
 float complex csinhf(float complex);
+long double complex csinhl(long double complex);

 /* 7.3.6.6 The ctanh functions */
 double complex ctanh(double complex);
 float complex ctanhf(float complex);
+long double complex ctanhl(long double complex);

 /* 7.3.7 Exponential and logarithmic functions */
 /* 7.3.7.1 The cexp functions */
 double complex cexp(double complex);
 float complex cexpf(float complex);
+long double complex cexpl(long double complex);

 /* 7.3.7.2 The clog functions */
 double complex clog(double complex);
@@ -93,6 +104,7 @@  float cabsf(float complex) ;
 /* 7.3.8.2 The cpow functions */
 double complex cpow(double complex, double complex);
 float complex cpowf(float complex, float complex);
+long double complex cpowl(long double complex, long double complex);

 /* 7.3.8.3 The csqrt functions */
 double complex csqrt(double complex);
@@ -113,10 +125,12 @@  long double cimagl(long double complex);
 /* 7.3.9.3 The conj functions */
 double complex conj(double complex);
 float complex conjf(float complex);
+long double complex conjl(long double complex);

 /* 7.3.9.4 The cproj functions */
 double complex cproj(double complex);
 float complex cprojf(float complex);
+long double complex cprojl(long double complex);

 /* 7.3.9.5 The creal functions */
 double creal(double complex);
@@ -126,27 +140,10 @@  long double creall(long double complex);
 #if __GNU_VISIBLE
 double complex clog10(double complex);
 float complex clog10f(float complex);
-#endif
-
-#if defined(__CYGWIN__)
-long double complex cacosl(long double complex);
-long double complex ccosl(long double complex);
-long double complex csinl(long double complex);
-long double complex ctanl(long double complex);
-long double complex cacoshl(long double complex);
-long double complex casinhl(long double complex);
-long double complex catanhl(long double complex);
-long double complex ccoshl(long double complex);
-long double complex csinhl(long double complex);
-long double complex ctanhl(long double complex);
-long double complex cexpl(long double complex);
-long double complex cpowl(long double complex, long double complex);
-long double complex conjl(long double complex);
-long double complex cprojl(long double complex);
-#if __GNU_VISIBLE
+# if defined(__CYGWIN__)
 long double complex clog10l(long double complex);
+# endif
 #endif
-#endif /* __CYGWIN__ */

 __END_DECLS