diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 73 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/float128-math.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 | 20 |
5 files changed, 128 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1547b6f..f7faf89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2018-10-24 Michael Meissner <meissner@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. + 2018-10-24 Martin Sebor <msebor@redhat.com> * doc/extend.texi (nonnull): List no-argument form. Reference diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 75e30ce..726038e 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1981,6 +1981,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #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,76 @@ rs6000_globalize_decl_name (FILE * stream, tree decl) #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. + In the future, glibc will export names like __ieee128_sinf128 and we can + switch to using those instead of using sinf128, which pollutes the user's + namespace. + + This will switch the names for Fortran math functions as well (which doesn't + use math.h). However, Fortran needs other changes to the compiler and + 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. */ + +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 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 + { + 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) + { + 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); + } + } + } + + return id; +} + + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-rs6000.h" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 96ef4b9..54334c9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-10-24 Michael Meissner <meissner@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. + 2018-10-24 Jakub Jelinek <jakub@redhat.com> PR c++/86288 diff --git a/gcc/testsuite/gcc.target/powerpc/float128-math.c b/gcc/testsuite/gcc.target/powerpc/float128-math.c new file mode 100644 index 0000000..4ad3b5b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/float128-math.c @@ -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} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 b/gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 new file mode 100644 index 0000000..d74c8d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 @@ -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} } } |