In working on the transition of PowerPC long double from using the IBM extended
double format to IEEE 128-bit floating point, I noticed that the long double
.gnu_attribute (#4) was not set if the compiler can handle long double directly
without doing the call to an emulator, such as using IEEE 128-bit floating
point on an ISA 3.0 (power9) 64-bit system.  This patch sets the attribute if
there is a move of the appropriate type.  I only check TF/TCmode for the normal
case, and DF/DCmode for -mlong-double-64, since IFmode is used for __ibm128
when long double is IEEE and KFmode is used for __float128 when long double is
IEEE.

I have checked this on a little endian power8 system with bootstrap and make
check.  There were no regressions, and I verified that the three new tests are
run and pass.  Can I check this into the trunk?

[gcc]
2018-01-11  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        (rs6000_emit_move): If we load or store a long double type, set
        the flags for noting the default long double type, even if we
        don't pass or return a long double type.

[gcc/testsuite]
2018-01-11  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        * gcc.target/powerpc/gnuattr1.c: New test to make sure we set the
        appropriate .gnu_attribute for the long double type, if we use the
        long double type, but do not generate any calls.
        * gcc.target/powerpc/gnuattr2.c: Likewise.
        * gcc.target/powerpc/gnuattr3.c: Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 256534)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -10505,6 +10505,22 @@ rs6000_emit_move (rtx dest, rtx source,
       gcc_unreachable ();
     }
 
+#ifdef HAVE_AS_GNU_ATTRIBUTE
+  /* If we use a long double type, set the flags in .gnu_attribute that say
+     what the long double type is.  This is to allow the linker's warning
+     message for the wrong long double to be useful, even if the function does
+     not do a call (for example, doing a 128-bit add on power9 if the long
+     double type is IEEE 128-bit.  Do not set this if __ibm128 or __floa128 are
+     used if they aren't the default long dobule type.  */
+  if (rs6000_gnu_attr
+      && ((HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE || TARGET_64BIT))
+      && ((TARGET_LONG_DOUBLE_128
+          && (mode == TFmode || mode == TCmode))
+         || (!TARGET_LONG_DOUBLE_128
+             && (mode == DFmode || mode == DCmode))))
+    rs6000_passes_float = rs6000_passes_long_double = true;
+#endif
+
   /* See if we need to special case SImode/SFmode SUBREG moves.  */
   if ((mode == SImode || mode == SFmode) && SUBREG_P (source)
       && rs6000_emit_move_si_sf_subreg (dest, source, mode))
Index: gcc/testsuite/gcc.target/powerpc/gnuattr1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/gnuattr1.c (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/gnuattr1.c (working copy)
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { powerpc*-linux-* } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx -mlong-double-64" } */
+/* { dg-final { scan-assembler "gnu_attribute 4, 9" } } */
+
+/* Check that if we can do the long double operation without doing an emulator
+   call, such as with 64-bit long double support, that we still set the
+   appropriate .gnu_attribute.  */
+
+long double a;
+
+void add1 (void)
+{
+  a++;
+}
Index: gcc/testsuite/gcc.target/powerpc/gnuattr2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/gnuattr2.c (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/gnuattr2.c (working copy)
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { powerpc*-linux-* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-O2 -mpower9-vector -mabi=ieeelongdouble -Wno-psabi" } */
+/* { dg-final { scan-assembler "gnu_attribute 4, 13" } } */
+
+/* Check that if we can do the long double operation without doing an emulator
+   call, such as with IEEE 128-bit hardware support on power9, that we still
+   set the appropriate .gnu_attribute.  The && lp64 is needed, because we can't
+   enable the IEEE 128-bit hardware instructions on ISA 3.0 (power9) in 32-bit,
+   because we don't have a TImode available.  */
+
+long double a;
+
+void add1 (void)
+{
+  a++;
+}
Index: gcc/testsuite/gcc.target/powerpc/gnuattr3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/gnuattr3.c (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/gnuattr3.c (working copy)
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { powerpc*-linux-* } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx -mabi=ibmlongdouble -Wno-psabi" } */
+/* { dg-final { scan-assembler "gnu_attribute 4, 5" } } */
+
+/* Check that if we can do the long double operation without doing an emulator
+   call, such as with copysign, that we still set the appropriate
+   .gnu_attribute.  */
+
+long double a, b, c;
+
+void cs (void)
+{
+  a = __builtin_copysignl (b, c);
+}

Reply via email to