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

Jeff Johnston jjohnstn@redhat.com
Tue Nov 8 20:24:51 GMT 2022


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
>
>


More information about the Newlib mailing list