[PATCH] PowerPC: Map IEEE 128-bit long double built-in functions. I posted this patch by accident to an internal IBM mailing list instead of gcc-patches.
This patch replaces patches previously submitted: September 24th, 2020: Message-ID: <20200924203159.ga31...@ibm-toto.the-meissners.org> October 9th, 2020: Message-ID: <20201009043543.ga11...@ibm-toto.the-meissners.org> October 24th, 2020: Message-ID: <20201022220346.ga8...@ibm-toto.the-meissners.org> This patch maps the built-in functions that take or return long double arguments on systems where long double is IEEE 128-bit. This patch goes through the built-in functions and changes the name of the math, scanf, and printf built-in functions to use the functions that GLIBC provides when long double uses the IEEE 128-bit representation. In addition, changing the name in GCC allows the Fortran compiler to automatically use the correct name. To map the math functions, typically this patch changes <name>l to __<name>ieee128. However there are some exceptions that are handled with this patch. To map the printf functions, <name> is mapped to __<name>ieee128. To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128. With the other IEEE long double patches, I have tested this patch by building 3 bootstrap compilers on a little endian power9 system, using the Advance Toolchain AT14.0 library, which uses GLIBC 2.32: 1) One compiler defaulted long double to IBM extended double; 2) One compiler defaulted long double to IEEE 128-bit; (and) 3) One compiler defaulted long double to 64 bit. I was able to bootstrap each compiler and run make check. In addition for the compilers using the two 128-bit long double types (IBM, IEEE), I have built the spec 2017 benchmark for both power9 and power10. At the moment, there are some differences between between the three runs for make check. I have some patches to fix these issue that I've done in the past, and I will be working on resubmitting them in the future. In addition, there are 3 fortran benchmarks (ieee/large_2.f90, default_format_2.f90, and default_format_denormal_2.f90) that now pass when the long double default is IEEE 128-bit. Can I check this into the master branch? gcc/ 2020-11-17 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add support for mapping built-in function names for long double built-in functions if long double is IEEE 128-bit. gcc/testsuite/ 2020-11-17 Michael Meissner <meiss...@linux.ibm.com> * gcc.target/powerpc/float128-longdouble-math.c: New test. * gcc.target/powerpc/float128-longdouble-stdio.c: New test. * gcc.target/powerpc/float128-math.c: Adjust test for new name being generated. Add support for running test on power10. Add support for running if long double defaults to 64-bits. --- gcc/config/rs6000/rs6000.c | 135 ++++-- .../powerpc/float128-longdouble-math.c | 442 ++++++++++++++++++ .../powerpc/float128-longdouble-stdio.c | 36 ++ .../gcc.target/powerpc/float128-math.c | 16 +- 4 files changed, 589 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c create mode 100644 gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a5188553593..35e9c844e17 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -27065,57 +27065,128 @@ rs6000_globalize_decl_name (FILE * stream, tree decl) library before you can switch the real*16 type at compile time. We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name. We - only do this if the default is that long double is IBM extended double, and - the user asked for IEEE 128-bit. */ + only do this transformation if the __float128 type is enabled. This + prevents us from doing the transformation on older 32-bit ports that might + have enabled using IEEE 128-bit floating point as the default long double + type. */ static tree rs6000_mangle_decl_assembler_name (tree decl, tree id) { - if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 + if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 && TREE_CODE (decl) == FUNCTION_DECL - && DECL_IS_UNDECLARED_BUILTIN (decl)) + && DECL_IS_UNDECLARED_BUILTIN (decl) + && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) { size_t len = IDENTIFIER_LENGTH (id); const char *name = IDENTIFIER_POINTER (id); + char *newname = NULL; - if (name[len - 1] == 'l') + /* See if it is one of the built-in functions with an unusual name. */ + switch (DECL_FUNCTION_CODE (decl)) { - bool uses_ieee128_p = false; - tree type = TREE_TYPE (decl); - machine_mode ret_mode = TYPE_MODE (type); + case BUILT_IN_DREML: + newname = xstrdup ("__remainderieee128"); + break; - /* See if the function returns a IEEE 128-bit floating point type or - complex type. */ - if (ret_mode == TFmode || ret_mode == TCmode) - uses_ieee128_p = true; - else - { - function_args_iterator args_iter; - tree arg; + case BUILT_IN_GAMMAL: + newname = xstrdup ("__lgammaieee128"); + break; + + case BUILT_IN_GAMMAL_R: + case BUILT_IN_LGAMMAL_R: + newname = xstrdup ("__lgammaieee128_r"); + break; + + case BUILT_IN_NEXTTOWARD: + newname = xstrdup ("__nexttoward_to_ieee128"); + break; + + case BUILT_IN_NEXTTOWARDF: + newname = xstrdup ("__nexttowardf_to_ieee128"); + break; + + case BUILT_IN_NEXTTOWARDL: + newname = xstrdup ("__nexttowardieee128"); + break; + + case BUILT_IN_POW10L: + newname = xstrdup ("__exp10ieee128"); + break; + + case BUILT_IN_SCALBL: + newname = xstrdup ("__scalbieee128"); + break; + + case BUILT_IN_SIGNIFICANDL: + newname = xstrdup ("__significandieee128"); + break; + + case BUILT_IN_SINCOSL: + newname = xstrdup ("__sincosieee128"); + break; - /* See if the function passes a IEEE 128-bit floating point type - or complex type. */ - FOREACH_FUNCTION_ARGS (type, arg, args_iter) + default: + break; + } + + /* Update the __builtin_*printf and __builtin_*scanf functions. */ + if (!newname) + { + size_t printf_len = strlen ("printf"); + size_t scanf_len = strlen ("scanf"); + + if (len >= printf_len + && strcmp (name + len - printf_len, "printf") == 0) + newname = xasprintf ("__%sieee128", name); + + else if (len >= scanf_len + && strcmp (name + len - scanf_len, "scanf") == 0) + newname = xasprintf ("__isoc99_%sieee128", name); + + else if (name[len - 1] == 'l') + { + bool uses_ieee128_p = false; + tree type = TREE_TYPE (decl); + machine_mode ret_mode = TYPE_MODE (type); + + /* See if the function returns a IEEE 128-bit floating point type or + complex type. */ + if (ret_mode == TFmode || ret_mode == TCmode) + uses_ieee128_p = true; + else { - machine_mode arg_mode = TYPE_MODE (arg); - if (arg_mode == TFmode || arg_mode == TCmode) + function_args_iterator args_iter; + tree arg; + + /* See if the function passes a IEEE 128-bit floating point type + or complex type. */ + FOREACH_FUNCTION_ARGS (type, arg, args_iter) { - uses_ieee128_p = true; - break; + machine_mode arg_mode = TYPE_MODE (arg); + if (arg_mode == TFmode || arg_mode == TCmode) + { + uses_ieee128_p = true; + break; + } } } - } - /* If we passed or returned an IEEE 128-bit floating point type, - change the name. */ - if (uses_ieee128_p) - { - char *name2 = (char *) alloca (len + 4); - memcpy (name2, name, len - 1); - strcpy (name2 + len - 1, "f128"); - id = get_identifier (name2); + /* If we passed or returned an IEEE 128-bit floating point type, + change the name. Use __<name>ieee128, instead of <name>l. */ + if (uses_ieee128_p) + newname = xasprintf ("__%.*sieee128", (int)(len - 1), name); } } + + if (newname) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "Map %s => %s\n", name, newname); + + id = get_identifier (newname); + free (newname); + } } return id; diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c new file mode 100644 index 00000000000..07934bb7357 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c @@ -0,0 +1,442 @@ +/* { dg-require-effective-target ppc_float128_hw } */ +/* { dg-options "-mdejagnu-cpu=power9 -O2 -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" } */ + +/* Test if switching long double to IEEE 128-bit maps all of the math built-in + function names correctly. We leave off the \M in matching the calls, so + power10 will match using bl foo@notoc. */ + +#ifdef DO_FUNC +#define BUILTIN1(FUNC, ARG1) FUNC (ARG1) +#define BUILTIN2(FUNC, ARG1, ARG2) FUNC (ARG1, ARG2) +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) FUNC (ARG1, ARG2, ARG3) + +#else +#define BUILTIN1(FUNC, ARG1) __builtin_ ## FUNC (ARG1) +#define BUILTIN2(FUNC, ARG1, ARG2) __builtin_ ## FUNC (ARG1, ARG2) +#define BUILTIN3(FUNC, ARG1, ARG2, ARG3) __builtin_ ## FUNC (ARG1, ARG2, ARG3) +#endif + +/* Built-in functions that returns a long double and take one long double + argument. */ + +void +return_ld_arg_ld (long double *p, + long double *q) +{ + /* { dg-final { scan-assembler {\mbl __acoshieee128} } } */ + *p++ = BUILTIN1 (acoshl, *q++); + + /* { dg-final { scan-assembler {\mbl __acosieee128} } } */ + *p++ = BUILTIN1 (acosl, *q++); + + /* { dg-final { scan-assembler {\mbl __asinhieee128} } } */ + *p++ = BUILTIN1 (asinhl, *q++); + + /* { dg-final { scan-assembler {\mbl __asinieee128} } } */ + *p++ = BUILTIN1 (asinl, *q++); + + /* { dg-final { scan-assembler {\mbl __atanhieee128} } } */ + *p++ = BUILTIN1 (atanhl, *q++); + + /* { dg-final { scan-assembler {\mbl __atanieee128} } } */ + *p++ = BUILTIN1 (atanl, *q++); + + /* { dg-final { scan-assembler {\mbl __cbrtieee128} } } */ + *p++ = BUILTIN1 (cbrtl, *q++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2} } } */ + *p++ = BUILTIN1 (ceill, *q++); + + /* { dg-final { scan-assembler {\mbl __coshieee128} } } */ + *p++ = BUILTIN1 (coshl, *q++); + + /* { dg-final { scan-assembler {\mbl __cosieee128} } } */ + *p++ = BUILTIN1 (cosl, *q++); + + /* { dg-final { scan-assembler {\mbl __erfcieee128} } } */ + *p++ = BUILTIN1 (erfcl, *q++); + + /* { dg-final { scan-assembler {\mbl __erfieee128} } } */ + *p++ = BUILTIN1 (erfl, *q++); + + /* { dg-final { scan-assembler {\mbl __exp10ieee128} } } */ + *p++ = BUILTIN1 (exp10l, *q++); + + /* { dg-final { scan-assembler {\mbl __exp2ieee128} } } */ + *p++ = BUILTIN1 (exp2l, *q++); + + /* { dg-final { scan-assembler {\mbl __expieee128} } } */ + *p++ = BUILTIN1 (expl, *q++); + + /* { dg-final { scan-assembler {\mbl __expm1ieee128} } } */ + *p++ = BUILTIN1 (expm1l, *q++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxsabsqp} } } */ + *p++ = BUILTIN1 (fabsl, *q++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3} } } */ + *p++ = BUILTIN1 (floorl, *q++); + + /* { dg-final { scan-assembler {\mbl __lgammaieee128} } } */ + *p++ = BUILTIN1 (gammal, *q++); + + /* { dg-final { scan-assembler {\mbl __j0ieee128} } } */ + *p++ = BUILTIN1 (j0l, *q++); + + /* { dg-final { scan-assembler {\mbl __j1ieee128} } } */ + *p++ = BUILTIN1 (j1l, *q++); + + /* { dg-final { scan-assembler {\mbl __log10ieee128} } } */ + *p++ = BUILTIN1 (log10l, *q++); + + /* { dg-final { scan-assembler {\mbl __log1pieee128} } } */ + *p++ = BUILTIN1 (log1pl, *q++); + + /* { dg-final { scan-assembler {\mbl __log2ieee128} } } */ + *p++ = BUILTIN1 (log2l, *q++); + + /* { dg-final { scan-assembler {\mbl __logbieee128} } } */ + *p++ = BUILTIN1 (logbl, *q++); + + /* { dg-final { scan-assembler {\mbl __logieee128} } } */ + *p++ = BUILTIN1 (logl, *q++); + + /* { dg-final { scan-assembler {\mbl __nearbyintieee128} } } */ + *p++ = BUILTIN1 (nearbyintl, *q++); + + /* { dg-final { scan-assembler {\mbl __exp10ieee128} } } */ + *p++ = BUILTIN1 (pow10l, *q++); + + /* { dg-final { scan-assembler {\mbl __rintieee128} } } */ + *p++ = BUILTIN1 (rintl, *q++); + + /* { dg-final { scan-assembler {\mbl __roundevenieee128} } } */ + *p++ = BUILTIN1 (roundevenl, *q++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,0} } } */ + *p++ = BUILTIN1 (roundl, *q++); + + /* { dg-final { scan-assembler {\mbl __significandieee128} } } */ + *p++ = BUILTIN1 (significandl, *q++); + + /* { dg-final { scan-assembler {\mbl __sinhieee128} } } */ + *p++ = BUILTIN1 (sinhl, *q++); + + /* { dg-final { scan-assembler {\mbl __sinieee128} } } */ + *p++ = BUILTIN1 (sinl, *q++); + + /* { dg-final { scan-assembler {\mbl __sqrtieee128} } } */ + *p++ = BUILTIN1 (sqrtl, *q++); + + /* { dg-final { scan-assembler {\mbl __tanhieee128} } } */ + *p++ = BUILTIN1 (tanhl, *q++); + + /* { dg-final { scan-assembler {\mbl __tanieee128} } } */ + *p++ = BUILTIN1 (tanl, *q++); + + /* { dg-final { scan-assembler {\mbl __tgammaieee128} } } */ + *p++ = BUILTIN1 (tgammal, *q++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1} } } */ + *p++ = BUILTIN1 (truncl, *q++); + + /* { dg-final { scan-assembler {\mbl __y0ieee128} } } */ + *p++ = BUILTIN1 (y0l, *q++); + + /* { dg-final { scan-assembler {\mbl __y1ieee128} } } */ + *p = BUILTIN1 (y1l, *q); + +} + +/* Built-in functions that returns a long double and take two long double + arguments. */ + +void +return_ld_arg_ld_ld (long double *p, + long double *q, + long double *r) +{ + /* { dg-final { scan-assembler {\mbl __atan2ieee128} } } */ + *p++ = BUILTIN2 (atan2l, *q++, *r++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxscpsgnqp} } } */ + *p++ = BUILTIN2 (copysignl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __remainderieee128} } } */ + *p++ = BUILTIN2 (dreml, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __fdimieee128} } } */ + *p++ = BUILTIN2 (fdiml, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __fmaxieee128} } } */ + *p++ = BUILTIN2 (fmaxl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __fminieee128} } } */ + *p++ = BUILTIN2 (fminl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __fmodieee128} } } */ + *p++ = BUILTIN2 (fmodl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __hypotieee128} } } */ + *p++ = BUILTIN2 (hypotl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __nextafterieee128} } } */ + *p++ = BUILTIN2 (nextafterl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __nexttowardieee128} } } */ + *p++ = BUILTIN2 (nexttowardl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __powieee128} } } */ + *p++ = BUILTIN2 (powl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __scalbnieee128} } } */ + *p = BUILTIN2 (scalbl, *q, *r); +} + +/* Built-in function that returns a long double and take three long double + arguments. */ + +void +return_ld_arg_ld_ld_ld (long double *p, + long double *q, + long double *r, + long double *s) +{ + /* inline code. */ + /* { dg-final { scan-assembler {\mxsmaddqp} } } */ + *p = BUILTIN3 (fmal, *q, *r, *s); +} + +/* Built-in functions that returns a long double and take one + _Complex long double argument. */ + +void +return_ld_arg_cld (long double *p, + _Complex long double *q) +{ + /* { dg-final { scan-assembler {\mbl __cabsieee128} } } */ + *p++ = BUILTIN1 (cabsl, *q++); +} + +/* Built-in functions that returns a _Complex long double and takes one + _Complex long double argument. */ + +void +return_cld_arg_cld (_Complex long double *p, + _Complex long double *q) +{ + /* { dg-final { scan-assembler {\mbl __cacoshieee128} } } */ + *p++ = BUILTIN1 (cacoshl, *q++); + + /* { dg-final { scan-assembler {\mbl __cacosieee128} } } */ + *p++ = BUILTIN1 (cacosl, *q++); + + /* { dg-final { scan-assembler {\mbl __casinhieee128} } } */ + *p++ = BUILTIN1 (casinhl, *q++); + + /* { dg-final { scan-assembler {\mbl __casinieee128} } } */ + *p++ = BUILTIN1 (casinl, *q++); + + /* { dg-final { scan-assembler {\mbl __catanhieee128} } } */ + *p++ = BUILTIN1 (catanhl, *q++); + + /* { dg-final { scan-assembler {\mbl __catanieee128} } } */ + *p++ = BUILTIN1 (catanl, *q++); + + /* { dg-final { scan-assembler {\mbl __ccoshieee128} } } */ + *p++ = BUILTIN1 (ccoshl, *q++); + + /* { dg-final { scan-assembler {\mbl __ccosieee128} } } */ + *p++ = BUILTIN1 (ccosl, *q++); + + /* { dg-final { scan-assembler {\mbl __cexpieee128} } } */ + *p++ = BUILTIN1 (cexpl, *q++); + + /* { dg-final { scan-assembler {\mbl __clogieee128} } } */ + *p++ = BUILTIN1 (clogl, *q++); + + /* { dg-final { scan-assembler {\mbl __clog10ieee128} } } */ + *p++ = BUILTIN1 (clog10l, *q++); + + /* { dg-final { scan-assembler {\mbl __cprojieee128} } } */ + *p++ = BUILTIN1 (cprojl, *q++); + + /* { dg-final { scan-assembler {\mbl __csinhieee128} } } */ + *p++ = BUILTIN1 (csinhl, *q++); + + /* { dg-final { scan-assembler {\mbl __csinieee128} } } */ + *p++ = BUILTIN1 (csinl, *q++); + + /* { dg-final { scan-assembler {\mbl __csqrtieee128} } } */ + *p++ = BUILTIN1 (csqrtl, *q++); + + /* { dg-final { scan-assembler {\mbl __ctanhieee128} } } */ + *p++ = BUILTIN1 (ctanhl, *q++); + + /* { dg-final { scan-assembler {\mbl __ctanieee128} } } */ + *p = BUILTIN1 (ctanl, *q); +} + +/* Built-in functions that returns a _Complex long double and takes one + long double argument. */ + +void +return_cld_arg_ld (_Complex long double *p, + long double *q) +{ + /* { dg-final { scan-assembler {\mbl __sincosieee128} } } */ + *p = BUILTIN1 (cexpil, *q); +} + +/* Built-in function that returns a _Complex long double and takes two + _Complex long double arguments. */ + +void +return_cld_arg_cld_cld (_Complex long double *p, + _Complex long double *q, + _Complex long double *r) +{ + /* { dg-final { scan-assembler {\mbl __cpowieee128} } } */ + *p = BUILTIN2 (cpowl, *q, *r); +} + +/* Built-in functions that returns a long double and takes a long double and a + pointer to an int arguments. */ + +void +return_ld_arg_ld_pi (long double *p, + long double *q, + int **r) +{ + /* { dg-final { scan-assembler {\mbl __frexpieee128} } } */ + *p++ = BUILTIN2 (frexpl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __lgammaieee128_r} } } */ + *p++ = BUILTIN2 (gammal_r, *q++, *r++); +} + +/* Built-in functions that returns a long double and takes a long double and an + int arguments. */ + +void +return_ld_arg_ld_i (long double *p, + long double *q, + int *r) +{ + /* { dg-final { scan-assembler {\mbl __ldexpieee128} } } */ + *p++ = BUILTIN2 (ldexpl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __powikf2} } } */ + *p++ = BUILTIN2 (powil, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __scalbnieee128} } } */ + *p = BUILTIN2 (scalbnl, *q, *r); +} + +/* Built-in function that returns a long double and takes a long double and a + long arguments. */ + +void +return_ld_arg_ld_l (long double *p, + long double *q, + long *r) +{ + /* { dg-final { scan-assembler {\mbl __scalblnieee128} } } */ + *p = BUILTIN2 (scalblnl, *q, *r); +} + +/* Built-in functions that returns a long double and takes a long double and a + long long arguments. */ + +void +return_ld_arg_i_ld (long double *p, + int *q, + long double *r) +{ + /* { dg-final { scan-assembler {\mbl __jnieee128} } } */ + *p++ = BUILTIN2 (jnl, *q++, *r++); + + /* { dg-final { scan-assembler {\mbl __ynieee128} } } */ + *p = BUILTIN2 (ynl, *q, *r); +} + +/* Built-in functions that returns a long double and takes a long double and a + pointer to a long double arguments. */ + +void +return_ld_arg_ld_pld (long double *p, + long double *q, + long double **r) +{ + /* { dg-final { scan-assembler {\mbl __modfieee128} } } */ + *p = BUILTIN2 (modfl, *q, *r); +} + +/* Built-in function that returns a long double and takes two long double and a + pointer to an int arguments. */ + +void +return_ld_arg_ld_ld_pi (long double *p, + long double *q, + long double *r, + int **s) +{ + /* { dg-final { scan-assembler {\mbl __remquoieee128} } } */ + *p = BUILTIN3 (remquol, *q, *r, *s); +} + +/* Built-in functions that return san int and takes one long double argument. */ + +void +return_i_arg_ld (int *p, + long double *q) +{ + /* { dg-final { scan-assembler {\mbl __ceilieee128} } } */ + *p++ = BUILTIN1 (iceill, *q++); + + /* { dg-final { scan-assembler {\mbl __floorieee128} } } */ + *p++ = BUILTIN1 (ifloorl, *q++); + + /* { dg-final { scan-assembler {\mbl __ilogbieee128} } } */ + *p++ = BUILTIN1 (ilogbl, *q++); + + /* { dg-final { scan-assembler {\mbl __lrintieee128} } } */ + *p++ = BUILTIN1 (irintl, *q++); + + /* { dg-final { scan-assembler {\mbl __lroundieee128} } } */ + *p++ = BUILTIN1 (iroundl, *q++); + + /* inline code. */ + /* { dg-final { scan-assembler {\mxscvqpswz} } } */ + *p++ = BUILTIN1 (signbitl, *q++); +} + +/* Built-in function that returns a double and takes one double and one long + double arguments. */ + +void +return_d_arg_d_ld (double *p, + double *q, + long double *r) +{ + /* { dg-final { scan-assembler {\mbl __nexttoward_to_ieee128} } } */ + *p = BUILTIN2 (nexttoward, *q, *r); +} + +/* Built-in function that returns a float and takes one float and one long + double arguments. */ + +void +return_f_arg_f_ld (float *p, + float *q, + long double *r) +{ + /* { dg-final { scan-assembler {\mbl __nexttowardf_to_ieee128} } } */ + *p = BUILTIN2 (nexttowardf, *q, *r); +} diff --git a/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c new file mode 100644 index 00000000000..39e59d949f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c @@ -0,0 +1,36 @@ +/* { dg-require-effective-target ppc_float128_hw } */ +/* { dg-options "-mdejagnu-cpu=power9 -O2 -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble" } */ + +/* Test if switching long double to IEEE 128-bit maps the printf and scanf + function names correctly. We leave off the \M in matching the calls, so + power10 will match using bl foo@notoc. */ + +#include <stdlib.h> + +volatile long double x = 1.0L; +volatile long double y, z; + +int +main (void) +{ + char buffer[100]; + + /* { dg-final { scan-assembler {\mbl __sprintfieee128} } } */ + __builtin_sprintf (buffer, "%Lg", x); + + /* { dg-final { scan-assembler {\mbl __printfieee128} } } */ + __builtin_printf ("x is %Lg [%s]\n", x, buffer); + + /* { dg-final { scan-assembler {\mbl __isoc99_sscanfieee128} } } */ + __builtin_sscanf (buffer, "%Lg", &y); + + __builtin_printf ("Type 1.0: "); + + /* { dg-final { scan-assembler {\mbl __isoc99_scanfieee128} } } */ + __builtin_scanf ("%Lg", &z); + + if (x != y || x != z) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.target/powerpc/float128-math.c b/gcc/testsuite/gcc.target/powerpc/float128-math.c index 4ad3b5b8363..d1e22239718 100644 --- a/gcc/testsuite/gcc.target/powerpc/float128-math.c +++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c @@ -1,20 +1,20 @@ -/* { dg-do compile { target { powerpc*-*-linux* } } } */ /* { dg-require-effective-target ppc_float128_sw } */ /* { dg-require-effective-target vsx_hw } */ -/* { dg-options "-mvsx -O2 -mfloat128 -mabi=ieeelongdouble -Wno-psabi" } */ +/* { dg-options "-mvsx -O2 -mfloat128 -mlong-double-128 -mabi=ieeelongdouble -Wno-psabi" } */ /* Test whether we convert __builtin_<math>l to __builtin_<math>f128 if the - default long double type is IEEE 128-bit. Also test that using the explicit - __builtin_<math>f128 function does not interfere with the __builtin_<math>l - function. */ + default long double type is IEEE 128-bit. We leave off the \M in matching + the calls, so power10 will match using bl foo@notoc. Also test that using + the explicit __builtin_<math>f128 function does not interfere with the + __builtin_<math>l function. */ extern __float128 sinf128 (__float128); -void foo (__float128 *p, long double *q, long double *r) +void foo (__float128 *p, long double *q) { *p = sinf128 (*p); *q = __builtin_sinl (*q); } -/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */ -/* { dg-final { scan-assembler-not {\mbl sinl\M} } } */ +/* { dg-final { scan-assembler {\mbl __sinieee128} } } */ +/* { dg-final { scan-assembler-not {\mbl sinl} } } */ -- 2.22.0 -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797