This is just the combined patch of the last three patches that have been
approved for trunk.  I expanded the description in rs6000-modes.def of what the
3 128-bit floating point types are and why IFmode needs to be ordered above
KFmode and TFmode.

These patches were individually proposed in:
https://gcc.gnu.org/ml/gcc-patches/2018-06/msg00634.html
https://gcc.gnu.org/ml/gcc-patches/2018-06/msg00796.html
https://gcc.gnu.org/ml/gcc-patches/2018-06/msg00799.html

In terms of the tests, the following tests fail if you switch the default long
double format.  At the moment, I don't have the GLIBC that provides native
support for IEEE 128-bit long double:

C tests:
c-c++-common/dfp/cast.c                         (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-11.c               (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-2.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-3.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-4.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-5.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-6.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp.c                  (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/pr39034.c                      (_Decimal128 <-> IEEE 128-bit)
gcc.dg/nextafter-2.c                            (needs updated GLIBC)
gcc.dg/torture/float128-nan.c                   (I need to investigate this)
gcc.dg/tree-ssa/builtin-sprintf.c               (needs updated GLIBC)
gcc.dg/tree-ssa/vrp104.c                        (I need to investigate this)
gcc.target/powerpc/clone1.c                     (I have patches for this)
gcc.target/powerpc/clone2.c                     (I have patches for this)
gcc.target/powerpc/divkc3-1.c                   (I have patches for this)
gcc.target/powerpc/float128-3.c                 (I have patches for this)
gcc.target/powerpc/float128-5.c                 (I have patches for this)
gcc.target/powerpc/float128-complex-1.c         (I have patches for this)
gcc.target/powerpc/float128-mix.c               (I have patches for this)
gcc.target/powerpc/mulkc3-1.c                   (I have patches for this)
gcc.target/powerpc/nan128-1.c                   (I need to investigate this)
gcc.target/powerpc/pack02.c                     (I have patches for this)
gcc.target/powerpc/pr57150.c                    (I have patches for this)
gcc.target/powerpc/pr60203.c                    (I have patches for this)
gcc.target/powerpc/pr67808.c                    (I have patches for this)
gcc.target/powerpc/pr70117.c                    (bug in isnormal on IEEE 128)
gcc.target/powerpc/pr78056-1.c                  (I have patches for this)
gcc.target/powerpc/pr78056-3.c                  (I have patches for this)
gcc.target/powerpc/pr80210-2.c                  (I have patches for this)
gcc.target/powerpc/pr80210.c                    (I have patches for this)
gcc.target/powerpc/pr85657-3.c                  (I have patches for this)
gcc.target/powerpc/tfmode_off.c                 (I have patches for this)

C++ tests:
c-c++-common/dfp/cast.c                         (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-11.c               (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-2.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-3.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-4.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-5.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp-6.c                (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/convert-bfp.c                  (_Decimal128 <-> IEEE 128-bit)
c-c++-common/dfp/pr39034.c                      (_Decimal128 <-> IEEE 128-bit)
g++.dg/cdce3.C                                  (needs updated GLIBC) 

The following Fortran tests fail.  I assume most of these are library issues:
gfortran.dg/erf_3.F90
gfortran.dg/fmt_en.f90
gfortran.dg/fmt_g0_7.f08
gfortran.dg/fmt_pf.f90
gfortran.dg/ieee/large_1.f90
gfortran.dg/ieee/large_3.F90
gfortran.dg/large_real_kind_1.f90
gfortran.dg/large_real_kind_2.F90
gfortran.dg/large_real_kind_3.F90
gfortran.dg/large_real_kind_form_io_1.f90
gfortran.dg/large_real_kind_form_io_2.f90
gfortran.dg/norm2_3.f90
gfortran.dg/quad_2.f90
gfortran.dg/round_2.f03

[gcc]
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>

        * 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 261708)
+++ 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    (nonexistent)
+++ 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 261708)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -2887,7 +2887,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");
@@ -4558,16 +4558,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 261708)
+++ 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.  */
 
@@ -539,7 +544,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)
@@ -865,9 +872,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 261708)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -8159,8 +8159,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);
@@ -8168,8 +8168,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);
@@ -14102,11 +14102,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;
 })
 
@@ -14125,9 +14122,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 261708)
+++ 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 261708)
+++ 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