rs6000.c (TARGET_MANGLE_DECL_ASSEMBLER_NAME): Define as rs6000_mangle_decl_assembler_...
authorMichael Meissner <meissner@linux.ibm.com>
Wed, 24 Oct 2018 20:16:31 +0000 (20:16 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Wed, 24 Oct 2018 20:16:31 +0000 (20:16 +0000)
[gcc]
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.

[gcc/testsuite]
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.

From-SVN: r265471

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/float128-math.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/ppc-fortran/ieee128-math.f90 [new file with mode: 0644]

index 1547b6f2754a5aead85888787dc746728a401302..f7faf892a9dc9f14080550b6ba502a2d6a562a99 100644 (file)
@@ -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
index 75e30ce978448e2f5339ffca78f47c2c860fee1c..726038ef2b74410d70d16dedd2a929cf4052630a 100644 (file)
@@ -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
 \f
 
 /* Processor table.  */
@@ -38964,6 +38967,76 @@ rs6000_globalize_decl_name (FILE * stream, tree decl)
 }
 #endif
 
+\f
+/* 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;
+}
+
 \f
 struct gcc_target targetm = TARGET_INITIALIZER;
 
index 96ef4b999bc554425d8b311aa7fabbd3cca41655..54334c9717deeee3db7d3251d0bab9919db62033 100644 (file)
@@ -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 (file)
index 0000000..4ad3b5b
--- /dev/null
@@ -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 (file)
index 0000000..d74c8d7
--- /dev/null
@@ -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} } }