As we have discussed on the patch submission, I'm going to be back porting the
IEEE 128-bit changes that we've made recently in the trunk to the GCC 8.x
branch.  The motivation is to allow distributions to switch to IEEE 128-bit
long double without having to wait for the GCC 9.1 compiler.

I'm sending out these patches in terms of the submission to the FSF trunk.  I
will probably wait a few days before committing the patches just in case
something major was broken.

Patch #1 is the May 21st submission.  Note, in this patch, we had 3 separate
types activelly used (__ibm128, __float128, and long double).  However we
eventually decided we only wanted to use 2 types, and this changed in Patch #2.

Patch #2 is the June 1-8th changes by me (Michael Meissner), Segher Boessenkool
and David Edelsohn.  In the second set of changed we changed this to the
current two active types, one of which is the long double type, and other is
the alternate type.  We also changed the C++ mangling of the float128 type (and
long double if it uses the IEEE 128-bit encoding) from "U10__float128" to
"u9__ieee128".  We put out weak aliases so that old code could still call
functions compiled with the new compiler.

Patch #3 is the change committed on June 18th that reworks the internal
ordering of the 128-bit binary floating point types.  This prevents the machine
independent portions of the compiler trying to convert __ibm128 data to
__float128 if you are running on a Power9 (ISA 3.0) system that has 128-bit
hardware floating point support.

Patch #4 will be a collection of small patches to fix some problems that were
noticed in running the test suite with the long double default changed to IEEE
128-bit floating point.

This is patch #3.

[gcc]
2018-06-18  Michael Meissner  <meiss...@linux.ibm.com>

        Back port from trunk
        2018-06-18  Michael Meissner  <meiss...@linux.ibm.com>

        PR target/85358
        * config/rs6000/rs6000-modes.def (toplevel): Rework the 128-bit
        floating point modes, so that IFmode is numerically greater than
        TFmode, which is greater than KFmode using FRACTIONAL_FLOAT_MODE
        to declare the ordering.  This prevents IFmode from being
        converted to TFmode when long double is IEEE 128-bit on an ISA 3.0
        machine.  Include rs6000-modes.h to share the fractional values
        between genmodes* and the rest of the compiler.
        (IFmode): Likewise.
        (KFmode): Likewise.
        (TFmode): Likewise.
        * config/rs6000/rs6000-modes.h: New file.
        * config/rs6000/rs6000.c (rs6000_debug_reg_global): Change the
        meaning of rs6000_long_double_size so that 126..128 selects an
        appropriate 128-bit floating point type.
        (rs6000_option_override_internal): Likewise.
        * config/rs6000/rs6000.h (toplevel): Include rs6000-modes.h.
        (TARGET_LONG_DOUBLE_128): Change the meaning of
        rs6000_long_double_size so that 126..128 selects an appropriate
        128-bit floating point type.
        (LONG_DOUBLE_TYPE_SIZE): Update comment.
        * config/rs6000/rs6000.md (trunciftf2): Correct the modes of the
        source and destination to match the standard usage.
        (truncifkf2): Likewise.
        (copysign<mode>3, IEEE iterator): Rework copysign of float128 on
        ISA 2.07 to use an explicit clobber, instead of passing in a
        temporary.
        (copysign<mode>3_soft): Likewise.

[libgcc]
2018-06-18  Michael Meissner  <meiss...@linux.ibm.com>

        Back port from trunk
        2018-06-18  Michael Meissner  <meiss...@linux.ibm.com>

        * config/rs6000/t-float128 (FP128_CFLAGS_SW): Compile float128
        support modules with -mno-gnu-attribute.
        * config/rs6000/t-float128-hw (FP128_CFLAGS_HW): 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-modes.def
===================================================================
--- gcc/config/rs6000/rs6000-modes.def  (revision 261712)
+++ gcc/config/rs6000/rs6000-modes.def  (working copy)
@@ -18,16 +18,39 @@
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
-/* IBM 128-bit floating point.  IFmode and KFmode use the fractional float
-   support in order to declare 3 128-bit floating point types.  */
-FRACTIONAL_FLOAT_MODE (IF, 106, 16, ibm_extended_format);
+/* We order the 3 128-bit floating point types so that IFmode (IBM 128-bit
+   floating point) is the 128-bit floating point type with the highest
+   precision (128 bits).  This so that machine independent parts of the
+   compiler do not try to widen IFmode to TFmode on ISA 3.0 (power9) that has
+   hardware support for IEEE 128-bit.  We set TFmode (long double mode) in
+   between, and KFmode (explicit __float128) below it.
+
+   Previously, IFmode and KFmode were defined to be fractional modes and TFmode
+   was the standard mode.  Since IFmode does not define the normal arithmetic
+   insns (other than neg/abs), on a ISA 3.0 system, the machine independent
+   parts of the compiler would see that TFmode has the necessary hardware
+   support, and widen the operation from IFmode to TFmode.  However, IEEE
+   128-bit is not strictly a super-set of IBM extended double and the
+   conversion to/from IEEE 128-bit was a function call.
+
+   We now make IFmode the highest fractional mode, which means its values are
+   not considered for widening.  Since we don't define insns for IFmode, the
+   IEEE 128-bit modes would not widen to IFmode.  */
+
+#ifndef RS6000_MODES_H
+#include "config/rs6000/rs6000-modes.h"
+#endif
+
+/* IBM 128-bit floating point.  */
+FRACTIONAL_FLOAT_MODE (IF, FLOAT_PRECISION_IFmode, 16, ibm_extended_format);
 
 /* Explicit IEEE 128-bit floating point.  */
-FRACTIONAL_FLOAT_MODE (KF, 113, 16, ieee_quad_format);
+FRACTIONAL_FLOAT_MODE (KF, FLOAT_PRECISION_KFmode, 16, ieee_quad_format);
 
-/* 128-bit floating point.  ABI_V4 uses IEEE quad, AIX/Darwin
-   adjust this in rs6000_option_override_internal.  */
-FLOAT_MODE (TF, 16, ieee_quad_format);
+/* 128-bit floating point, either IBM 128-bit or IEEE 128-bit.  This is
+   adjusted in rs6000_option_override_internal to be the appropriate floating
+   point type.  */
+FRACTIONAL_FLOAT_MODE (TF, FLOAT_PRECISION_TFmode, 16, ieee_quad_format);
 
 /* Add any extra modes needed to represent the condition code.
 
Index: gcc/config/rs6000/rs6000-modes.h
===================================================================
--- gcc/config/rs6000/rs6000-modes.h    (revision 0)
+++ gcc/config/rs6000/rs6000-modes.h    (working copy)
@@ -0,0 +1,36 @@
+/* Definitions 128-bit floating point precisions used by PowerPC.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   Contributed by Michael Meissner (meiss...@linux.ibm.com)
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* We order the 3 128-bit floating point types so that IFmode (IBM 128-bit
+   floating point) is the 128-bit floating point type with the highest
+   precision (128 bits).  This so that machine independent parts of the
+   compiler do not try to widen IFmode to TFmode on ISA 3.0 (power9) that has
+   hardware support for IEEE 128-bit.  We set TFmode (long double mode) in
+   between, and KFmode (explicit __float128) below it.
+
+   We won't encounter conversion from IEEE 128-bit to IBM 128-bit because we
+   don't have insns to support the IBM 128-bit aritmetic operations.  */
+
+#ifndef RS6000_MODES_H
+#define RS6000_MODES_H         1
+#define FLOAT_PRECISION_IFmode 128
+#define FLOAT_PRECISION_TFmode 127
+#define FLOAT_PRECISION_KFmode 126
+#endif /* RS6000_MODES_H */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 261712)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -2915,7 +2915,7 @@ rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_D, "tls_size", rs6000_tls_size);
   fprintf (stderr, DEBUG_FMT_D, "long_double_size",
           rs6000_long_double_type_size);
-  if (rs6000_long_double_type_size == 128)
+  if (rs6000_long_double_type_size > 64)
     {
       fprintf (stderr, DEBUG_FMT_S, "long double type",
               TARGET_IEEEQUAD ? "IEEE" : "IBM");
@@ -4612,16 +4612,25 @@ rs6000_option_override_internal (bool gl
        }
     }
 
+  /* Use long double size to select the appropriate long double.  We use
+     TYPE_PRECISION to differentiate the 3 different long double types.  We map
+     128 into the precision used for TFmode.  */
+  int default_long_double_size = (RS6000_DEFAULT_LONG_DOUBLE_SIZE == 64
+                                 ? 64
+                                 : FLOAT_PRECISION_TFmode);
+
   /* Set long double size before the IEEE 128-bit tests.  */
   if (!global_options_set.x_rs6000_long_double_type_size)
     {
       if (main_target_opt != NULL
          && (main_target_opt->x_rs6000_long_double_type_size
-             != RS6000_DEFAULT_LONG_DOUBLE_SIZE))
+             != default_long_double_size))
        error ("target attribute or pragma changes long double size");
       else
-       rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+       rs6000_long_double_type_size = default_long_double_size;
     }
+  else if (rs6000_long_double_type_size == 128)
+    rs6000_long_double_type_size = FLOAT_PRECISION_TFmode;
 
   /* Set -mabi=ieeelongdouble on some old targets.  In the future, power server
      systems will also set long double to be IEEE 128-bit.  AIX and Darwin
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h  (revision 261712)
+++ gcc/config/rs6000/rs6000.h  (working copy)
@@ -30,6 +30,11 @@
 #include "config/rs6000/rs6000-opts.h"
 #endif
 
+/* 128-bit floating point precision values.  */
+#ifndef RS6000_MODES_H
+#include "config/rs6000/rs6000-modes.h"
+#endif
+
 /* Definitions for the object file format.  These are set at
    compile-time.  */
 
@@ -561,7 +566,9 @@ extern int rs6000_vector_align[];
 #define TARGET_ALIGN_NATURAL 0
 #endif
 
-#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
+/* We use values 126..128 to pick the appropriate long double type (IFmode,
+   KFmode, TFmode).  */
+#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size > 64)
 #define TARGET_IEEEQUAD rs6000_ieeequad
 #define TARGET_ALTIVEC_ABI rs6000_altivec_abi
 #define TARGET_LDBRX (TARGET_POPCNTD || rs6000_cpu == PROCESSOR_CELL)
@@ -910,9 +917,8 @@ extern unsigned char rs6000_recip_bits[]
    words.  */
 #define DOUBLE_TYPE_SIZE 64
 
-/* A C expression for the size in bits of the type `long double' on
-   the target machine.  If you don't define this, the default is two
-   words.  */
+/* A C expression for the size in bits of the type `long double' on the target
+   machine.  If you don't define this, the default is two words.  */
 #define LONG_DOUBLE_TYPE_SIZE rs6000_long_double_type_size
 
 /* Work around rs6000_long_double_type_size dependency in ada/targtyps.c.  */
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 261712)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -8139,8 +8139,8 @@ (define_expand "extendtfkf2"
 })
 
 (define_expand "trunciftf2"
-  [(set (match_operand:IF 0 "gpc_reg_operand")
-       (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand")))]
+  [(set (match_operand:TF 0 "gpc_reg_operand")
+       (float_truncate:TF (match_operand:IF 1 "gpc_reg_operand")))]
   "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
@@ -8148,8 +8148,8 @@ (define_expand "trunciftf2"
 })
 
 (define_expand "truncifkf2"
-  [(set (match_operand:IF 0 "gpc_reg_operand")
-       (float_truncate:IF (match_operand:KF 1 "gpc_reg_operand")))]
+  [(set (match_operand:KF 0 "gpc_reg_operand")
+       (float_truncate:KF (match_operand:IF 1 "gpc_reg_operand")))]
   "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
@@ -14077,11 +14077,8 @@ (define_expand "copysign<mode>3"
     emit_insn (gen_copysign<mode>3_hard (operands[0], operands[1],
                                         operands[2]));
   else
-    {
-      rtx tmp = gen_reg_rtx (<MODE>mode);
-      emit_insn (gen_copysign<mode>3_soft (operands[0], operands[1],
-                                          operands[2], tmp));
-    }
+    emit_insn (gen_copysign<mode>3_soft (operands[0], operands[1],
+                                        operands[2]));
   DONE;
 })
 
@@ -14100,9 +14097,9 @@ (define_insn "copysign<mode>3_soft"
   [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
        (unspec:IEEE128
         [(match_operand:IEEE128 1 "altivec_register_operand" "v")
-         (match_operand:IEEE128 2 "altivec_register_operand" "v")
-         (match_operand:IEEE128 3 "altivec_register_operand" "+v")]
-        UNSPEC_COPYSIGN))]
+         (match_operand:IEEE128 2 "altivec_register_operand" "v")]
+        UNSPEC_COPYSIGN))
+   (clobber (match_scratch:IEEE128 3 "=&v"))]
   "!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
    "xscpsgndp %x3,%x2,%x1\;xxpermdi %x0,%x3,%x1,1"
   [(set_attr "type" "veccomplex")
Index: libgcc/config/rs6000/t-float128
===================================================================
--- libgcc/config/rs6000/t-float128     (revision 261712)
+++ libgcc/config/rs6000/t-float128     (working copy)
@@ -59,7 +59,7 @@ fp128_includes                = $(srcdir)/soft-fp/doub
 
 # Build the emulator without ISA 3.0 hardware support.
 FP128_CFLAGS_SW                 = -Wno-type-limits -mvsx -mfloat128 \
-                          -mno-float128-hardware \
+                          -mno-float128-hardware -mno-gnu-attribute \
                           -I$(srcdir)/soft-fp \
                           -I$(srcdir)/config/rs6000 \
                           $(FLOAT128_HW_INSNS)
Index: libgcc/config/rs6000/t-float128-hw
===================================================================
--- libgcc/config/rs6000/t-float128-hw  (revision 261712)
+++ libgcc/config/rs6000/t-float128-hw  (working copy)
@@ -25,7 +25,7 @@ fp128_sed_hw          = -hw
 # Build the hardware support functions with appropriate hardware support
 FP128_CFLAGS_HW                 = -Wno-type-limits -mvsx -mfloat128 \
                           -mpower8-vector -mpower9-vector \
-                          -mfloat128-hardware \
+                          -mfloat128-hardware -mno-gnu-attribute \
                           -I$(srcdir)/soft-fp \
                           -I$(srcdir)/config/rs6000 \
                           $(FLOAT128_HW_INSNS)

Reply via email to