This patch changes the name used by the <math>l built-in functions that return or are passed long double if the long double type is changed from the current IBM long double format to the IEEE 128-bit format.
I have done a bootstrap and make check with no regressions on a little endian power8 system. Is it ok to check into the trunk? This will need to be back ported to the GCC 8.x branch. [gcc] 2018-10-23 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/rs6000.c (TARGET_MANGLE_DECL_ASSEMBLER_NAME): Define as rs6000_mangle_decl_assembler_name. (rs6000_mangle_decl_assembler_name): If the user switched from IBM long double to IEEE long double, switch the names of the long double built-in functions to be <func>f128 instead of <func>l. [gcc/testsuite] 2018-10-23 Michael Meissner <meiss...@linux.ibm.com> * gcc.target/powerpc/float128-math.c: New test to make sure the long double built-in function names use the f128 form if the user switched from IBM long double to IEEE long double. * gcc.target/powerpc/ppc-fortran/ieee128-math.f90: Likewise. -- 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
Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 265400) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1981,6 +1981,9 @@ static const struct attribute_spec rs600 #undef TARGET_SETJMP_PRESERVES_NONVOLATILE_REGS_P #define TARGET_SETJMP_PRESERVES_NONVOLATILE_REGS_P hook_bool_void_true + +#undef TARGET_MANGLE_DECL_ASSEMBLER_NAME +#define TARGET_MANGLE_DECL_ASSEMBLER_NAME rs6000_mangle_decl_assembler_name /* Processor table. */ @@ -38965,6 +38968,67 @@ rs6000_globalize_decl_name (FILE * strea #endif +/* On 64-bit Linux and Freebsd systems, possibly switch the long double library + function names from <foo>l to <foo>f128 if the default long double type is + IEEE 128-bit. Typically, with the C and C++ languages, the standard math.h + include file switches the names on systems that support long double as IEEE + 128-bit, but that doesn't work if the user uses __builtin_<foo>l directly or + if they use Fortran. Use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to + change this name. We only do this if the default is long double is not IEEE + 128-bit, and the user asked for IEEE 128-bit. */ + +static tree +rs6000_mangle_decl_assembler_name (tree decl, tree id) +{ + if (!TARGET_IEEEQUAD_DEFAULT && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 + && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl) ) + { + size_t len = IDENTIFIER_LENGTH (id); + const char *name = IDENTIFIER_POINTER (id); + + if (name[len-1] == 'l') + { + bool has_long_double_p = false; + tree type = TREE_TYPE (decl); + machine_mode ret_mode = TYPE_MODE (type); + + /* See if the function returns long double or long double + complex. */ + if (ret_mode == TFmode || ret_mode == TCmode) + has_long_double_p = true; + else + { + function_args_iterator args_iter; + tree arg; + + /* See if we have a long double or long double complex + argument. */ + FOREACH_FUNCTION_ARGS (type, arg, args_iter) + { + machine_mode arg_mode = TYPE_MODE (arg); + if (arg_mode == TFmode || arg_mode == TCmode) + { + has_long_double_p = true; + break; + } + } + } + + /* If we have long double, change the name. */ + if (has_long_double_p) + { + char *name2 = (char *) alloca (len + 4); + memcpy (name2, name, len-1); + strcpy (name2 + len - 1, "f128"); + id = get_identifier (name2); + } + } + } + + return id; +} + + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rs6000.h" Index: gcc/testsuite/gcc.target/powerpc/float128-math.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-math.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-math.c (working copy) @@ -0,0 +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" } */ + +/* 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. */ + +extern __float128 sinf128 (__float128); + +void foo (__float128 *p, long double *q, long double *r) +{ + *p = sinf128 (*p); + *q = __builtin_sinl (*q); +} + +/* { dg-final { scan-assembler-times {\mbl sinf128\M} 2 } } */ +/* { dg-final { scan-assembler-not {\mbl sinl\M} } } */ Index: gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 (working copy) @@ -0,0 +1,20 @@ +! { dg-do compile { target { powerpc*-*-linux* } } } +! { dg-require-effective-target ppc_float128_sw } +! { dg-require-effective-target vsx_hw } +! { dg-options "-mvsx -mabi=ieeelongdouble -mfloat128" } +! { dg-excess-errors "expect error due to switching long double type" } +! Since the error message is not associated with a particular line +! number, we cannot use the dg-error directive and cannot specify a +! regexp to describe the expected error message. The expected warning +! message is: +! "Warning: Using IEEE extended precision long double [-Wpsabi]" + +program test_qp + implicit none + real(16), volatile :: fp1, fp2; + fp1 = 2.0 + fp2 = log (fp1) +end + +! { dg-final { scan-assembler-not {\mbl logl\M} } } +! { dg-final { scan-assembler {\mbl logf128\M} } }