public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH], PowerPC IEEE 128-bit patch #4
@ 2015-07-29 20:14 Michael Meissner
  2015-07-29 22:38 ` Segher Boessenkool
                   ` (6 more replies)
  0 siblings, 7 replies; 78+ messages in thread
From: Michael Meissner @ 2015-07-29 20:14 UTC (permalink / raw)
  To: gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 3644 bytes --]

This is another intermediate patch to get IEEE 128-bit support on the PowerPC
into the GCC compiler. This patch adds a lot of the support to allow IEEE
128-bit support in VSX registers. Note, it will need future patches that
updates rs6000.c and rs6000.md to enable the basic IEEE 128-bit support.

This patch bootstraps and has no test suite regressions on a big endian Power7
system and a little endian system. Is it ok to install?

The expected future patches are:

  #5	Finish the enablement of the basic support (rs6000.c & rs6000.md
	changes);

  #6	Add support for using different names for the 64/128-bit integer
	conversion to IBM extended double, to allow a future version to
	switch the default for what long double is. It is not expected that GCC
	6.x will make this switch, but we would like to eventually use the
	standard TF names for the library when the default change is made. If
	this isn't clear, the following names use 'tf' in them, when they use
	IBM extended double:

		__dpd_extendddtf
		__dpd_extendsdtf
		__dpd_extendtftd
		__dpd_trunctdtf
		__dpd_trunctfdd
		__dpd_trunctfsd
		__fixtfdi
		__fixtfti
		__fixunstfti
		__floattitf
		__floatuntitf
		__powitf2
		__floatditf
		__floatunditf
		__fixunstfdi

  #7	Basic patches to enable libgcc support. It is anticipated that these
	patches may be temporary changes, to allow for the glibc team to do the
	soft-float emulator changes that are shared with libgcc (but they can't
	really start until there is basic support in there).

  #8	Enable IEEE 128-bit floating point in VSX registers by default for VSX
	systems, add tests for IEEE 128-bit support and correct calling
	sequence.

  #9...	Various fixes of things I haven't yet covered (complex, libquadmath,
	etc.).

2015-07-28  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/vector.md (VEC_L): Add KFmode and TFmode.
	(VEC_M): Likewise.
	(VEC_N): Likewise.
	(mov<mode>, VEC_M iterator): Add support for IEEE 128-bit floating
	point in VSX registers.

	* config/rs6000/constraints.md (wb constraint): Document unused
	w<x> constraint.
	(we constraint): Likewise.
	(wo constraint): Likewise.
	(wp constraint): New constraint for IEEE 128-bit floating point in
	VSX registers.
	(wq constraint): Likewise.

	* config/rs6000/predicates.md (easy_fp_constant): Add support for
	IEEE 128-bit floating point in VSX registers.
	(easy_scalar_constant): Likewise.

	* config/rs6000/rs6000.c (rs6000_debug_reg_global): Add new
	constraints (wp, wq) for IEEE 128-bit floating point in VSX
	registers.
	(rs6000_init_hard_regno_mode_ok): Likewise.

	* config/rs6000/vsx.md (VSX_LE_128): Add support for IEEE 128-bit
	floating point in VSX registers.
	(VSX_L): Likewise.
	(VSX_M): Likewise.
	(VSX_M2): Likewise.
	(VSm): Likewise.
	(VSs): Likewise.
	(VSr): Likewise.
	(VSa): Likewise.
	(VSv): Likewise.
	(vsx_le_permute_<mode>): Add support to properly swap bytes for
	IEEE 128-bit floating point in VSX registers on little endian.
	(vsx_le_undo_permute_<mode>): Likewise.
	(vsx_le_perm_load_<mode>): Likewise.
	(vsx_le_perm_store_<mode>): Likewise.
	(splitters for IEEE 128-bit fp moves): Likewise.

	* config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wp and
	wq constraints.

	* config/rs6000/altivec.md (VM): Add support for IEEE 128-bit
	floating point in VSX registers.
	(VM2): Likewise.
	(altivec_high_bit): New insn to set just the high bit in an
	altivec register.

	* doc/md.text (Machine Constraints): Document wp and wq
	constraints on PowerPC.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch04b --]
[-- Type: text/plain, Size: 16756 bytes --]

Index: gcc/config/rs6000/vector.md
===================================================================
--- gcc/config/rs6000/vector.md	(revision 226275)
+++ gcc/config/rs6000/vector.md	(working copy)
@@ -36,13 +36,14 @@ (define_mode_iterator VEC_A [V16QI V8HI 
 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
 
 ;; Vector logical modes
-(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI])
+(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF])
 
-;; Vector modes for moves.  Don't do TImode here.
-(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI])
+;; Vector modes for moves.  Don't do TImode or TFmode here, since their
+;; moves are handled elsewhere.
+(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF])
 
 ;; Vector modes for types that don't need a realignment under VSX
-(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI])
+(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF])
 
 ;; Vector comparison modes
 (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF])
@@ -95,12 +96,19 @@ (define_expand "mov<mode>"
 {
   if (can_create_pseudo_p ())
     {
-      if (CONSTANT_P (operands[1])
-	  && !easy_vector_constant (operands[1], <MODE>mode))
-	operands[1] = force_const_mem (<MODE>mode, operands[1]);
+      if (CONSTANT_P (operands[1]))
+	{
+	  if (FLOAT128_VECTOR_P (<MODE>mode))
+	    {
+	      if (!easy_fp_constant (operands[1], <MODE>mode))
+		operands[1] = force_const_mem (<MODE>mode, operands[1]);
+	    }
+	  else if (!easy_vector_constant (operands[1], <MODE>mode))
+	    operands[1] = force_const_mem (<MODE>mode, operands[1]);
+	}
 
-      else if (!vlogical_operand (operands[0], <MODE>mode)
-	       && !vlogical_operand (operands[1], <MODE>mode))
+      if (!vlogical_operand (operands[0], <MODE>mode)
+	  && !vlogical_operand (operands[1], <MODE>mode))
 	operands[1] = force_reg (<MODE>mode, operands[1]);
     }
   if (!BYTES_BIG_ENDIAN
Index: gcc/config/rs6000/constraints.md
===================================================================
--- gcc/config/rs6000/constraints.md	(revision 226275)
+++ gcc/config/rs6000/constraints.md	(working copy)
@@ -56,12 +56,16 @@ (define_register_constraint "z" "CA_REGS
 (define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
   "Any VSX register if the -mvsx option was used or NO_REGS.")
 
+;; wb is not currently used
+
 ;; NOTE: For compatibility, "wc" is reserved to represent individual CR bits.
 ;; It is currently used for that purpose in LLVM.
 
 (define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]"
   "VSX vector register to hold vector double data or NO_REGS.")
 
+;; we is not currently used
+
 (define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]"
   "VSX vector register to hold vector float data or NO_REGS.")
 
@@ -93,6 +97,14 @@ (define_register_constraint "wm" "rs6000
 ;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
 (define_register_constraint "wn" "NO_REGS" "No register (NO_REGS).")
 
+;; wo is not currently used
+
+(define_register_constraint "wp" "rs6000_constraints[RS6000_CONSTRAINT_wp]"
+  "VSX register to use for IEEE 128-bit fp TFmode, or NO_REGS.")
+
+(define_register_constraint "wq" "rs6000_constraints[RS6000_CONSTRAINT_wq]"
+  "VSX register to use for IEEE 128-bit fp KFmode, or NO_REGS.")
+
 (define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]"
   "General purpose register if 64-bit instructions are enabled or NO_REGS.")
 
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 226275)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -460,6 +460,8 @@ (define_predicate "easy_fp_constant"
 
   switch (mode)
     {
+    case KFmode:
+    case IFmode:
     case TFmode:
     case DFmode:
     case SFmode:
@@ -486,6 +488,12 @@ (define_predicate "easy_vector_constant"
   if (TARGET_PAIRED_FLOAT)
     return false;
 
+  /* Because IEEE 128-bit floating point is considered a vector type
+     in order to pass it in VSX registers, it might use this function
+     instead of easy_fp_constant.  */
+  if (FLOAT128_VECTOR_P (mode))
+    return easy_fp_constant (op, mode);
+
   if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
     {
       if (zero_constant (op, mode))
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 226275)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -2167,6 +2167,8 @@ rs6000_debug_reg_global (void)
 	   "wk reg_class = %s\n"
 	   "wl reg_class = %s\n"
 	   "wm reg_class = %s\n"
+	   "wp reg_class = %s\n"
+	   "wq reg_class = %s\n"
 	   "wr reg_class = %s\n"
 	   "ws reg_class = %s\n"
 	   "wt reg_class = %s\n"
@@ -2190,6 +2192,8 @@ rs6000_debug_reg_global (void)
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wk]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]],
+	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wp]],
+	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wq]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
@@ -2856,6 +2860,13 @@ rs6000_init_hard_regno_mode_ok (bool glo
   if (TARGET_LFIWZX)
     rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;	/* DImode  */
 
+  if (TARGET_FLOAT128)
+    {
+      rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;	/* KFmode  */
+      if (rs6000_ieeequad)
+	rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS;	/* TFmode  */
+    }
+
   /* Set up the reload helper and direct move functions.  */
   if (TARGET_VSX || TARGET_ALTIVEC)
     {
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(revision 226275)
+++ gcc/config/rs6000/vsx.md	(working copy)
@@ -31,6 +31,11 @@ (define_mode_iterator VSX_LE [V2DF
 			      V1TI
 			      (TI	"VECTOR_MEM_VSX_P (TImode)")])
 
+;; Mode iterator to handle swapping words on little endian for the 128-bit
+;; types that goes in a single vector register.
+(define_mode_iterator VSX_LE_128 [(KF   "FLOAT128_VECTOR_P (KFmode)")
+				  (TF   "FLOAT128_VECTOR_P (TFmode)")])
+
 ;; Iterator for the 2 32-bit vector types
 (define_mode_iterator VSX_W [V4SF V4SI])
 
@@ -41,11 +46,31 @@ (define_mode_iterator VSX_DF [V2DF DF])
 (define_mode_iterator VSX_F [V4SF V2DF])
 
 ;; Iterator for logical types supported by VSX
-(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI])
+;; Note, IFmode won't actually be used since it isn't a VSX type, but it simplifies
+;; the code by using 128-bit iterators for floating point.
+(define_mode_iterator VSX_L [V16QI
+			     V8HI
+			     V4SI
+			     V2DI
+			     V4SF
+			     V2DF
+			     V1TI
+			     TI
+			     (KF	"FLOAT128_VECTOR_P (KFmode)")
+			     (TF	"FLOAT128_VECTOR_P (TFmode)")
+			     (IF	"FLOAT128_VECTOR_P (IFmode)")])
 
 ;; Iterator for memory move.  Handle TImode specially to allow
 ;; it to use gprs as well as vsx registers.
-(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI])
+(define_mode_iterator VSX_M [V16QI
+			     V8HI
+			     V4SI
+			     V2DI
+			     V4SF
+			     V2DF
+			     V1TI
+			     (KF	"FLOAT128_VECTOR_P (KFmode)")
+			     (TF	"FLOAT128_VECTOR_P (TFmode)")])
 
 (define_mode_iterator VSX_M2 [V16QI
 			      V8HI
@@ -54,6 +79,8 @@ (define_mode_iterator VSX_M2 [V16QI
 			      V4SF
 			      V2DF
 			      V1TI
+			      (KF	"FLOAT128_VECTOR_P (KFmode)")
+			      (TF	"FLOAT128_VECTOR_P (TFmode)")
 			      (TI	"TARGET_VSX_TIMODE")])
 
 ;; Map into the appropriate load/store name based on the type
@@ -64,6 +91,8 @@ (define_mode_attr VSm  [(V16QI "vw4")
 			(V2DF  "vd2")
 			(V2DI  "vd2")
 			(DF    "d")
+			(TF    "vd2")
+			(KF    "vd2")
 			(V1TI  "vd2")
 			(TI    "vd2")])
 
@@ -76,6 +105,8 @@ (define_mode_attr VSs	[(V16QI "sp")
 			 (V2DI  "dp")
 			 (DF    "dp")
 			 (SF	"sp")
+			 (TF    "dp")
+			 (KF    "dp")
 			 (V1TI  "dp")
 			 (TI    "dp")])
 
@@ -89,6 +120,8 @@ (define_mode_attr VSr	[(V16QI "v")
 			 (DI	"wi")
 			 (DF    "ws")
 			 (SF	"ww")
+			 (TF	"wp")
+			 (KF	"wq")
 			 (V1TI  "v")
 			 (TI    "wt")])
 
@@ -132,7 +165,9 @@ (define_mode_attr VSa	[(V16QI "wa")
 			 (DF    "ws")
 			 (SF	"ww")
 			 (V1TI	"wa")
-			 (TI    "wt")])
+			 (TI    "wt")
+			 (TF	"wp")
+			 (KF	"wq")])
 
 ;; Same size integer type for floating point data
 (define_mode_attr VSi [(V4SF  "v4si")
@@ -157,7 +192,8 @@ (define_mode_attr VSv	[(V16QI "v")
 			 (V2DI  "v")
 			 (V2DF  "v")
 			 (V1TI  "v")
-			 (DF    "s")])
+			 (DF    "s")
+			 (KF	"v")])
 
 ;; Appropriate type for add ops (and other simple FP ops)
 (define_mode_attr VStype_simple	[(V2DF "vecdouble")
@@ -623,6 +659,105 @@ (define_split
                      (const_int 6) (const_int 7)])))]
   "")
 
+;; Little endian word swapping for 128-bit types that are either scalars or the
+;; special V1TI container class, which it is not appropriate to use vec_select
+;; for the type.
+(define_insn "*vsx_le_permute_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
+	(rotate:VSX_LE_128
+	 (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
+	 (const_int 64)))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "@
+   xxpermdi %x0,%x1,%x1,2
+   lxvd2x %x0,%y1
+   stxvd2x %x1,%y0"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecperm,vecload,vecstore")])
+
+(define_insn_and_split "*vsx_le_undo_permute_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
+	(rotate:VSX_LE_128
+	 (rotate:VSX_LE_128
+	  (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
+	  (const_int 64))
+	 (const_int 64)))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "@
+   #
+   xxlor %x0,%x1"
+  ""
+  [(set (match_dup 0) (match_dup 1))]
+{
+  if (reload_completed && REGNO (operands[0]) == REGNO (operands[1]))
+    {
+      emit_note (NOTE_INSN_DELETED);
+      DONE;
+    }
+}
+  [(set_attr "length" "0,4")
+   (set_attr "type" "vecsimple")])
+
+(define_insn_and_split "*vsx_le_perm_load_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>")
+        (match_operand:VSX_LE_128 1 "memory_operand" "Z"))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "#"
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  [(set (match_dup 2)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 0)
+	(rotate:VSX_LE_128 (match_dup 2)
+			   (const_int 64)))]
+  "
+{
+  operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+                                       : operands[0];
+}
+  "
+  [(set_attr "type" "vecload")
+   (set_attr "length" "8")])
+
+(define_insn "*vsx_le_perm_store_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z")
+        (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>"))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "#"
+  [(set_attr "type" "vecstore")
+   (set_attr "length" "12")])
+
+(define_split
+  [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
+        (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+  [(set (match_dup 2)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 0)
+	(rotate:VSX_LE_128 (match_dup 2)
+			   (const_int 64)))]
+{
+  operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+                                       : operands[0];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+  [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
+        (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+  [(set (match_dup 1)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 0)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 1)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))]
+  "")
 
 (define_insn "*vsx_mov<mode>"
   [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?<VSa>,?<VSa>,wQ,?&r,??Y,??r,??r,<VSr>,?<VSa>,*r,v,wZ, v")
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 226275)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1496,6 +1496,8 @@ enum r6000_reg_class_enum {
   RS6000_CONSTRAINT_wk,		/* FPR/VSX register for DFmode direct moves. */
   RS6000_CONSTRAINT_wl,		/* FPR register for LFIWAX */
   RS6000_CONSTRAINT_wm,		/* VSX register for direct move */
+  RS6000_CONSTRAINT_wp,		/* VSX reg for IEEE 128-bit fp TFmode. */
+  RS6000_CONSTRAINT_wq,		/* VSX reg for IEEE 128-bit fp KFmode.  */
   RS6000_CONSTRAINT_wr,		/* GPR register if 64-bit  */
   RS6000_CONSTRAINT_ws,		/* VSX register for DF */
   RS6000_CONSTRAINT_wt,		/* VSX register for TImode */
Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 226275)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -167,10 +167,27 @@ (define_mode_iterator VF [V4SF])
 (define_mode_iterator V [V4SI V8HI V16QI V4SF])
 ;; Vec modes for move/logical/permute ops, include vector types for move not
 ;; otherwise handled by altivec (v2df, v2di, ti)
-(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI V1TI TI])
+(define_mode_iterator VM [V4SI
+			  V8HI
+			  V16QI
+			  V4SF
+			  V2DF
+			  V2DI
+			  V1TI
+			  TI
+			  (KF "FLOAT128_VECTOR_P (KFmode)")
+			  (TF "FLOAT128_VECTOR_P (TFmode)")])
 
 ;; Like VM, except don't do TImode
-(define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI V1TI])
+(define_mode_iterator VM2 [V4SI
+			   V8HI
+			   V16QI
+			   V4SF
+			   V2DF
+			   V2DI
+			   V1TI
+			   (KF "FLOAT128_VECTOR_P (KFmode)")
+			   (TF "FLOAT128_VECTOR_P (TFmode)")])
 
 (define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")])
 (define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")])
@@ -3488,3 +3505,32 @@ (define_peephole2
 				  (match_dup 3)]
 				 UNSPEC_BCD_ADD_SUB)
 		    (match_dup 4)))])])
+
+\f
+;; Return constant 0x80000000000000000000000000000000 in an Altivec register.
+
+(define_expand "altivec_high_bit"
+  [(set (match_dup 1)
+	(vec_duplicate:V16QI (const_int 7)))
+   (set (match_dup 2)
+	(ashift:V16QI (match_dup 1)
+		      (match_dup 1)))
+   (set (match_dup 3)
+	(match_dup 4))
+   (set (match_operand:V16QI 0 "register_operand" "")
+	(unspec:V16QI [(match_dup 2)
+		       (match_dup 3)
+		       (const_int 15)] UNSPEC_VSLDOI))]
+  "TARGET_ALTIVEC"
+{
+  if (can_create_pseudo_p ())
+    {
+      operands[1] = gen_reg_rtx (V16QImode);
+      operands[2] = gen_reg_rtx (V16QImode);
+      operands[3] = gen_reg_rtx (V16QImode);
+    }
+  else
+    operands[1] = operands[2] = operands[3] = operands[0];
+
+  operands[4] = CONST0_RTX (V16QImode);
+})
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	(revision 226275)
+++ gcc/doc/md.texi	(working copy)
@@ -3087,12 +3087,13 @@ Any VSX register if the -mvsx option was
 
 When using any of the register constraints (@code{wa}, @code{wd},
 @code{wf}, @code{wg}, @code{wh}, @code{wi}, @code{wj}, @code{wk},
-@code{wl}, @code{wm}, @code{ws}, @code{wt}, @code{wu}, @code{wv},
-@code{ww}, or @code{wy}) that take VSX registers, you must use
-@code{%x<n>} in the template so that the correct register is used.
-Otherwise the register number output in the assembly file will be
-incorrect if an Altivec register is an operand of a VSX instruction
-that expects VSX register numbering.
+@code{wl}, @code{wm}, @code{wp}, @code{wq}, @code{ws}, @code{wt},
+@code{wu}, @code{wv}, @code{ww}, or @code{wy})
+that take VSX registers, you must use @code{%x<n>} in the template so
+that the correct register is used.  Otherwise the register number
+output in the assembly file will be incorrect if an Altivec register
+is an operand of a VSX instruction that expects VSX register
+numbering.
 
 @smallexample
 asm ("xvadddp %x0,%x1,%x2" : "=wa" (v1) : "wa" (v2), "wa" (v3));
@@ -3136,6 +3137,12 @@ VSX register if direct move instructions
 @item wn
 No register (NO_REGS).
 
+@item wp
+VSX register to use for IEEE 128-bit floating point TFmode, or NO_REGS.
+
+@item wq
+VSX register to use for IEEE 128-bit floating point, or NO_REGS.
+
 @item wr
 General purpose register if 64-bit instructions are enabled or NO_REGS.
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
@ 2015-07-29 22:38 ` Segher Boessenkool
  2015-07-29 22:48   ` Michael Meissner
  2015-07-30 19:57 ` [PATCH], PowerPC IEEE 128-bit patch #4c (revised) Michael Meissner
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Segher Boessenkool @ 2015-07-29 22:38 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

On Wed, Jul 29, 2015 at 04:04:28PM -0400, Michael Meissner wrote:
> +;; Return constant 0x80000000000000000000000000000000 in an Altivec register.
> +
> +(define_expand "altivec_high_bit"
> +  [(set (match_dup 1)
> +	(vec_duplicate:V16QI (const_int 7)))
> +   (set (match_dup 2)
> +	(ashift:V16QI (match_dup 1)
> +		      (match_dup 1)))
> +   (set (match_dup 3)
> +	(match_dup 4))
> +   (set (match_operand:V16QI 0 "register_operand" "")
> +	(unspec:V16QI [(match_dup 2)
> +		       (match_dup 3)
> +		       (const_int 15)] UNSPEC_VSLDOI))]
> +  "TARGET_ALTIVEC"
> +{
> +  if (can_create_pseudo_p ())
> +    {
> +      operands[1] = gen_reg_rtx (V16QImode);
> +      operands[2] = gen_reg_rtx (V16QImode);
> +      operands[3] = gen_reg_rtx (V16QImode);
> +    }
> +  else
> +    operands[1] = operands[2] = operands[3] = operands[0];

This won't work (in the pattern you write to op 3 before reading from op 2).
Do you ever call this expander late, anyway?


Segher

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-07-29 22:38 ` Segher Boessenkool
@ 2015-07-29 22:48   ` Michael Meissner
  2015-07-29 22:56     ` Segher Boessenkool
  0 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-07-29 22:48 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Wed, Jul 29, 2015 at 04:59:23PM -0500, Segher Boessenkool wrote:
> On Wed, Jul 29, 2015 at 04:04:28PM -0400, Michael Meissner wrote:
> > +;; Return constant 0x80000000000000000000000000000000 in an Altivec register.
> > +
> > +(define_expand "altivec_high_bit"
> > +  [(set (match_dup 1)
> > +	(vec_duplicate:V16QI (const_int 7)))
> > +   (set (match_dup 2)
> > +	(ashift:V16QI (match_dup 1)
> > +		      (match_dup 1)))
> > +   (set (match_dup 3)
> > +	(match_dup 4))
> > +   (set (match_operand:V16QI 0 "register_operand" "")
> > +	(unspec:V16QI [(match_dup 2)
> > +		       (match_dup 3)
> > +		       (const_int 15)] UNSPEC_VSLDOI))]
> > +  "TARGET_ALTIVEC"
> > +{
> > +  if (can_create_pseudo_p ())
> > +    {
> > +      operands[1] = gen_reg_rtx (V16QImode);
> > +      operands[2] = gen_reg_rtx (V16QImode);
> > +      operands[3] = gen_reg_rtx (V16QImode);
> > +    }
> > +  else
> > +    operands[1] = operands[2] = operands[3] = operands[0];
> 
> This won't work (in the pattern you write to op 3 before reading from op 2).
> Do you ever call this expander late, anyway?

I'm not sure I follow you.  Without the patch lines the insns are as follows (I
put in blank lines to separate the insns):

(define_expand "altivec_high_bit"
  [(set (match_dup 1)
	(vec_duplicate:V16QI (const_int 7)))

   (set (match_dup 2)
	(ashift:V16QI (match_dup 1)
		      (match_dup 1)))

   (set (match_dup 3)
	(match_dup 4))

   (set (match_operand:V16QI 0 "register_operand" "")
	(unspec:V16QI [(match_dup 2)
		       (match_dup 3)
		       (const_int 15)] UNSPEC_VSLDOI))]
  "TARGET_ALTIVEC"
{
  if (can_create_pseudo_p ())
    {
      operands[1] = gen_reg_rtx (V16QImode);
      operands[2] = gen_reg_rtx (V16QImode);
      operands[3] = gen_reg_rtx (V16QImode);
    }
  else
    operands[1] = operands[2] = operands[3] = operands[0];

  operands[4] = CONST0_RTX (V16QImode);
})

The first insn sets operands[1] to be 0x07070707070707070707070707070707LL.

The second insn sets operands[2] to be operands[1] << operands[1], i.e.
0x80808080808080808080808080808080LL.

The third insn sets operands[3] to be 0.

The fourth does a double vector shift left 15 bytes, filing in 0's in the
bottom bits, which leaves the following in the register:
0x80000000000000000000000000000000LL

This is negative -0.0 in IEEE 128-bit, which is used to flip the sign bit.

The code is used for negate and absolute value (which is done during rtl
expansion). Here is the negate use case.

(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
   (clobber (match_scratch:V16QI 2 "=v"))]
  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
  "#"
  ""
  [(parallel [(set (match_dup 0)
		   (neg:TFIFKF (match_dup 1)))
	      (use (match_dup 2))])]
{
  if (GET_CODE (operands[2]) == SCRATCH)
    operands[2] = gen_reg_rtx (V16QImode);

  operands[3] = gen_reg_rtx (V16QImode);
  emit_insn (gen_altivec_high_bit (operands[2]));
}
  [(set_attr "length" "8")
   (set_attr "type" "vecsimple")])

(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
   (use (match_operand:V16QI 2 "register_operand" "=v"))]
  "TARGET_FLOAT128"
  "xxlxor %x0,%x1,%x2"
  [(set_attr "length" "4")
   (set_attr "type" "vecsimple")])


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-07-29 22:48   ` Michael Meissner
@ 2015-07-29 22:56     ` Segher Boessenkool
  2015-07-29 23:48       ` Michael Meissner
  0 siblings, 1 reply; 78+ messages in thread
From: Segher Boessenkool @ 2015-07-29 22:56 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

On Wed, Jul 29, 2015 at 06:38:45PM -0400, Michael Meissner wrote:
> On Wed, Jul 29, 2015 at 04:59:23PM -0500, Segher Boessenkool wrote:
> > On Wed, Jul 29, 2015 at 04:04:28PM -0400, Michael Meissner wrote:
> > > +;; Return constant 0x80000000000000000000000000000000 in an Altivec register.
> > > +
> > > +(define_expand "altivec_high_bit"
> > > +  [(set (match_dup 1)
> > > +	(vec_duplicate:V16QI (const_int 7)))
> > > +   (set (match_dup 2)
> > > +	(ashift:V16QI (match_dup 1)
> > > +		      (match_dup 1)))
> > > +   (set (match_dup 3)
> > > +	(match_dup 4))
> > > +   (set (match_operand:V16QI 0 "register_operand" "")
> > > +	(unspec:V16QI [(match_dup 2)
> > > +		       (match_dup 3)
> > > +		       (const_int 15)] UNSPEC_VSLDOI))]
> > > +  "TARGET_ALTIVEC"
> > > +{
> > > +  if (can_create_pseudo_p ())
> > > +    {
> > > +      operands[1] = gen_reg_rtx (V16QImode);
> > > +      operands[2] = gen_reg_rtx (V16QImode);
> > > +      operands[3] = gen_reg_rtx (V16QImode);
> > > +    }
> > > +  else
> > > +    operands[1] = operands[2] = operands[3] = operands[0];
> > 
> > This won't work (in the pattern you write to op 3 before reading from op 2).
> > Do you ever call this expander late, anyway?
> 
> I'm not sure I follow you.

I'm sorry, I meant that very last line I quoted, the !can_create_pseudo_p ()
one.  If that is executed operands[2] will be the same reg as operands[3],
and things fall apart.


Segher

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-07-29 22:56     ` Segher Boessenkool
@ 2015-07-29 23:48       ` Michael Meissner
  0 siblings, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-07-29 23:48 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Wed, Jul 29, 2015 at 05:46:42PM -0500, Segher Boessenkool wrote:
> On Wed, Jul 29, 2015 at 06:38:45PM -0400, Michael Meissner wrote:
> > On Wed, Jul 29, 2015 at 04:59:23PM -0500, Segher Boessenkool wrote:
> > > On Wed, Jul 29, 2015 at 04:04:28PM -0400, Michael Meissner wrote:
> > > > +;; Return constant 0x80000000000000000000000000000000 in an Altivec register.
> > > > +
> > > > +(define_expand "altivec_high_bit"
> > > > +  [(set (match_dup 1)
> > > > +	(vec_duplicate:V16QI (const_int 7)))
> > > > +   (set (match_dup 2)
> > > > +	(ashift:V16QI (match_dup 1)
> > > > +		      (match_dup 1)))
> > > > +   (set (match_dup 3)
> > > > +	(match_dup 4))
> > > > +   (set (match_operand:V16QI 0 "register_operand" "")
> > > > +	(unspec:V16QI [(match_dup 2)
> > > > +		       (match_dup 3)
> > > > +		       (const_int 15)] UNSPEC_VSLDOI))]
> > > > +  "TARGET_ALTIVEC"
> > > > +{
> > > > +  if (can_create_pseudo_p ())
> > > > +    {
> > > > +      operands[1] = gen_reg_rtx (V16QImode);
> > > > +      operands[2] = gen_reg_rtx (V16QImode);
> > > > +      operands[3] = gen_reg_rtx (V16QImode);
> > > > +    }
> > > > +  else
> > > > +    operands[1] = operands[2] = operands[3] = operands[0];
> > > 
> > > This won't work (in the pattern you write to op 3 before reading from op 2).
> > > Do you ever call this expander late, anyway?
> > 
> > I'm not sure I follow you.
> 
> I'm sorry, I meant that very last line I quoted, the !can_create_pseudo_p ()
> one.  If that is executed operands[2] will be the same reg as operands[3],
> and things fall apart.

Yes, you are right. I'll put an abort in there if we can't allocate
pseudos. But since it is called during RTL expansion of abskf2, negkf2, etc. we
won't run into it.  Thanks.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4c (revised)
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
  2015-07-29 22:38 ` Segher Boessenkool
@ 2015-07-30 19:57 ` Michael Meissner
  2015-08-01 19:48   ` David Edelsohn
  2015-07-31  2:49 ` [PATCH], PowerPC IEEE 128-bit patch #4 Joseph Myers
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-07-30 19:57 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 2264 bytes --]

Seger pointed out that the altivec_high_bit insn was not safe if it was called
when it could not allocate pseudos. I have removed that insn in this patch. I
will revise the patch.  I had meant to tie it in with easy_altivec_constant
originally, and I will do a patch with that change.

Is this revised patch ok to install?  There are no references to
altivec_high_bit in this patch set, so I just made sure it builds ok just
removing the insn.

2015-07-30  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/vector.md (VEC_L): Add KFmode and TFmode.
	(VEC_M): Likewise.
	(VEC_N): Likewise.
	(mov<mode>, VEC_M iterator): Add support for IEEE 128-bit floating
	point in VSX registers.

	* config/rs6000/constraints.md (wb constraint): Document unused
	w<x> constraint.
	(we constraint): Likewise.
	(wo constraint): Likewise.
	(wp constraint): New constraint for IEEE 128-bit floating point in
	VSX registers.
	(wq constraint): Likewise.

	* config/rs6000/predicates.md (easy_fp_constant): Add support for
	IEEE 128-bit floating point in VSX registers.
	(easy_scalar_constant): Likewise.

	* config/rs6000/rs6000.c (rs6000_debug_reg_global): Add new
	constraints (wp, wq) for IEEE 128-bit floating point in VSX
	registers.
	(rs6000_init_hard_regno_mode_ok): Likewise.

	* config/rs6000/vsx.md (VSX_LE_128): Add support for IEEE 128-bit
	floating point in VSX registers.
	(VSX_L): Likewise.
	(VSX_M): Likewise.
	(VSX_M2): Likewise.
	(VSm): Likewise.
	(VSs): Likewise.
	(VSr): Likewise.
	(VSa): Likewise.
	(VSv): Likewise.
	(vsx_le_permute_<mode>): Add support to properly swap bytes for
	IEEE 128-bit floating point in VSX registers on little endian.
	(vsx_le_undo_permute_<mode>): Likewise.
	(vsx_le_perm_load_<mode>): Likewise.
	(vsx_le_perm_store_<mode>): Likewise.
	(splitters for IEEE 128-bit fp moves): Likewise.

	* config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wp and
	wq constraints.

	* config/rs6000/altivec.md (VM): Add support for IEEE 128-bit
	floating point in VSX registers.
	(VM2): Likewise.

	* doc/md.text (Machine Constraints): Document wp and wq
	constraints on PowerPC.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch04c --]
[-- Type: text/plain, Size: 15865 bytes --]

Index: gcc/config/rs6000/vector.md
===================================================================
--- gcc/config/rs6000/vector.md	(revision 226275)
+++ gcc/config/rs6000/vector.md	(working copy)
@@ -36,13 +36,14 @@ (define_mode_iterator VEC_A [V16QI V8HI 
 (define_mode_iterator VEC_K [V16QI V8HI V4SI V4SF])
 
 ;; Vector logical modes
-(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI])
+(define_mode_iterator VEC_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI KF TF])
 
-;; Vector modes for moves.  Don't do TImode here.
-(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI])
+;; Vector modes for moves.  Don't do TImode or TFmode here, since their
+;; moves are handled elsewhere.
+(define_mode_iterator VEC_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI KF])
 
 ;; Vector modes for types that don't need a realignment under VSX
-(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI])
+(define_mode_iterator VEC_N [V4SI V4SF V2DI V2DF V1TI KF TF])
 
 ;; Vector comparison modes
 (define_mode_iterator VEC_C [V16QI V8HI V4SI V2DI V4SF V2DF])
@@ -95,12 +96,19 @@ (define_expand "mov<mode>"
 {
   if (can_create_pseudo_p ())
     {
-      if (CONSTANT_P (operands[1])
-	  && !easy_vector_constant (operands[1], <MODE>mode))
-	operands[1] = force_const_mem (<MODE>mode, operands[1]);
+      if (CONSTANT_P (operands[1]))
+	{
+	  if (FLOAT128_VECTOR_P (<MODE>mode))
+	    {
+	      if (!easy_fp_constant (operands[1], <MODE>mode))
+		operands[1] = force_const_mem (<MODE>mode, operands[1]);
+	    }
+	  else if (!easy_vector_constant (operands[1], <MODE>mode))
+	    operands[1] = force_const_mem (<MODE>mode, operands[1]);
+	}
 
-      else if (!vlogical_operand (operands[0], <MODE>mode)
-	       && !vlogical_operand (operands[1], <MODE>mode))
+      if (!vlogical_operand (operands[0], <MODE>mode)
+	  && !vlogical_operand (operands[1], <MODE>mode))
 	operands[1] = force_reg (<MODE>mode, operands[1]);
     }
   if (!BYTES_BIG_ENDIAN
Index: gcc/config/rs6000/constraints.md
===================================================================
--- gcc/config/rs6000/constraints.md	(revision 226275)
+++ gcc/config/rs6000/constraints.md	(working copy)
@@ -56,12 +56,16 @@ (define_register_constraint "z" "CA_REGS
 (define_register_constraint "wa" "rs6000_constraints[RS6000_CONSTRAINT_wa]"
   "Any VSX register if the -mvsx option was used or NO_REGS.")
 
+;; wb is not currently used
+
 ;; NOTE: For compatibility, "wc" is reserved to represent individual CR bits.
 ;; It is currently used for that purpose in LLVM.
 
 (define_register_constraint "wd" "rs6000_constraints[RS6000_CONSTRAINT_wd]"
   "VSX vector register to hold vector double data or NO_REGS.")
 
+;; we is not currently used
+
 (define_register_constraint "wf" "rs6000_constraints[RS6000_CONSTRAINT_wf]"
   "VSX vector register to hold vector float data or NO_REGS.")
 
@@ -93,6 +97,14 @@ (define_register_constraint "wm" "rs6000
 ;; There is a mode_attr that resolves to wm for SDmode and wn for SFmode
 (define_register_constraint "wn" "NO_REGS" "No register (NO_REGS).")
 
+;; wo is not currently used
+
+(define_register_constraint "wp" "rs6000_constraints[RS6000_CONSTRAINT_wp]"
+  "VSX register to use for IEEE 128-bit fp TFmode, or NO_REGS.")
+
+(define_register_constraint "wq" "rs6000_constraints[RS6000_CONSTRAINT_wq]"
+  "VSX register to use for IEEE 128-bit fp KFmode, or NO_REGS.")
+
 (define_register_constraint "wr" "rs6000_constraints[RS6000_CONSTRAINT_wr]"
   "General purpose register if 64-bit instructions are enabled or NO_REGS.")
 
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 226275)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -460,6 +460,8 @@ (define_predicate "easy_fp_constant"
 
   switch (mode)
     {
+    case KFmode:
+    case IFmode:
     case TFmode:
     case DFmode:
     case SFmode:
@@ -486,6 +488,12 @@ (define_predicate "easy_vector_constant"
   if (TARGET_PAIRED_FLOAT)
     return false;
 
+  /* Because IEEE 128-bit floating point is considered a vector type
+     in order to pass it in VSX registers, it might use this function
+     instead of easy_fp_constant.  */
+  if (FLOAT128_VECTOR_P (mode))
+    return easy_fp_constant (op, mode);
+
   if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
     {
       if (zero_constant (op, mode))
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 226275)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -2167,6 +2167,8 @@ rs6000_debug_reg_global (void)
 	   "wk reg_class = %s\n"
 	   "wl reg_class = %s\n"
 	   "wm reg_class = %s\n"
+	   "wp reg_class = %s\n"
+	   "wq reg_class = %s\n"
 	   "wr reg_class = %s\n"
 	   "ws reg_class = %s\n"
 	   "wt reg_class = %s\n"
@@ -2190,6 +2192,8 @@ rs6000_debug_reg_global (void)
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wk]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wm]],
+	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wp]],
+	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wq]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wr]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]],
 	   reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wt]],
@@ -2856,6 +2860,13 @@ rs6000_init_hard_regno_mode_ok (bool glo
   if (TARGET_LFIWZX)
     rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;	/* DImode  */
 
+  if (TARGET_FLOAT128)
+    {
+      rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;	/* KFmode  */
+      if (rs6000_ieeequad)
+	rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS;	/* TFmode  */
+    }
+
   /* Set up the reload helper and direct move functions.  */
   if (TARGET_VSX || TARGET_ALTIVEC)
     {
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(revision 226275)
+++ gcc/config/rs6000/vsx.md	(working copy)
@@ -31,6 +31,11 @@ (define_mode_iterator VSX_LE [V2DF
 			      V1TI
 			      (TI	"VECTOR_MEM_VSX_P (TImode)")])
 
+;; Mode iterator to handle swapping words on little endian for the 128-bit
+;; types that goes in a single vector register.
+(define_mode_iterator VSX_LE_128 [(KF   "FLOAT128_VECTOR_P (KFmode)")
+				  (TF   "FLOAT128_VECTOR_P (TFmode)")])
+
 ;; Iterator for the 2 32-bit vector types
 (define_mode_iterator VSX_W [V4SF V4SI])
 
@@ -41,11 +46,31 @@ (define_mode_iterator VSX_DF [V2DF DF])
 (define_mode_iterator VSX_F [V4SF V2DF])
 
 ;; Iterator for logical types supported by VSX
-(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF V1TI TI])
+;; Note, IFmode won't actually be used since it isn't a VSX type, but it simplifies
+;; the code by using 128-bit iterators for floating point.
+(define_mode_iterator VSX_L [V16QI
+			     V8HI
+			     V4SI
+			     V2DI
+			     V4SF
+			     V2DF
+			     V1TI
+			     TI
+			     (KF	"FLOAT128_VECTOR_P (KFmode)")
+			     (TF	"FLOAT128_VECTOR_P (TFmode)")
+			     (IF	"FLOAT128_VECTOR_P (IFmode)")])
 
 ;; Iterator for memory move.  Handle TImode specially to allow
 ;; it to use gprs as well as vsx registers.
-(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF V1TI])
+(define_mode_iterator VSX_M [V16QI
+			     V8HI
+			     V4SI
+			     V2DI
+			     V4SF
+			     V2DF
+			     V1TI
+			     (KF	"FLOAT128_VECTOR_P (KFmode)")
+			     (TF	"FLOAT128_VECTOR_P (TFmode)")])
 
 (define_mode_iterator VSX_M2 [V16QI
 			      V8HI
@@ -54,6 +79,8 @@ (define_mode_iterator VSX_M2 [V16QI
 			      V4SF
 			      V2DF
 			      V1TI
+			      (KF	"FLOAT128_VECTOR_P (KFmode)")
+			      (TF	"FLOAT128_VECTOR_P (TFmode)")
 			      (TI	"TARGET_VSX_TIMODE")])
 
 ;; Map into the appropriate load/store name based on the type
@@ -64,6 +91,8 @@ (define_mode_attr VSm  [(V16QI "vw4")
 			(V2DF  "vd2")
 			(V2DI  "vd2")
 			(DF    "d")
+			(TF    "vd2")
+			(KF    "vd2")
 			(V1TI  "vd2")
 			(TI    "vd2")])
 
@@ -76,6 +105,8 @@ (define_mode_attr VSs	[(V16QI "sp")
 			 (V2DI  "dp")
 			 (DF    "dp")
 			 (SF	"sp")
+			 (TF    "dp")
+			 (KF    "dp")
 			 (V1TI  "dp")
 			 (TI    "dp")])
 
@@ -89,6 +120,8 @@ (define_mode_attr VSr	[(V16QI "v")
 			 (DI	"wi")
 			 (DF    "ws")
 			 (SF	"ww")
+			 (TF	"wp")
+			 (KF	"wq")
 			 (V1TI  "v")
 			 (TI    "wt")])
 
@@ -132,7 +165,9 @@ (define_mode_attr VSa	[(V16QI "wa")
 			 (DF    "ws")
 			 (SF	"ww")
 			 (V1TI	"wa")
-			 (TI    "wt")])
+			 (TI    "wt")
+			 (TF	"wp")
+			 (KF	"wq")])
 
 ;; Same size integer type for floating point data
 (define_mode_attr VSi [(V4SF  "v4si")
@@ -157,7 +192,8 @@ (define_mode_attr VSv	[(V16QI "v")
 			 (V2DI  "v")
 			 (V2DF  "v")
 			 (V1TI  "v")
-			 (DF    "s")])
+			 (DF    "s")
+			 (KF	"v")])
 
 ;; Appropriate type for add ops (and other simple FP ops)
 (define_mode_attr VStype_simple	[(V2DF "vecdouble")
@@ -623,6 +659,105 @@ (define_split
                      (const_int 6) (const_int 7)])))]
   "")
 
+;; Little endian word swapping for 128-bit types that are either scalars or the
+;; special V1TI container class, which it is not appropriate to use vec_select
+;; for the type.
+(define_insn "*vsx_le_permute_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "nonimmediate_operand" "=<VSa>,<VSa>,Z")
+	(rotate:VSX_LE_128
+	 (match_operand:VSX_LE_128 1 "input_operand" "<VSa>,Z,<VSa>")
+	 (const_int 64)))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "@
+   xxpermdi %x0,%x1,%x1,2
+   lxvd2x %x0,%y1
+   stxvd2x %x1,%y0"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecperm,vecload,vecstore")])
+
+(define_insn_and_split "*vsx_le_undo_permute_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>,<VSa>")
+	(rotate:VSX_LE_128
+	 (rotate:VSX_LE_128
+	  (match_operand:VSX_LE_128 1 "vsx_register_operand" "0,<VSa>")
+	  (const_int 64))
+	 (const_int 64)))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "@
+   #
+   xxlor %x0,%x1"
+  ""
+  [(set (match_dup 0) (match_dup 1))]
+{
+  if (reload_completed && REGNO (operands[0]) == REGNO (operands[1]))
+    {
+      emit_note (NOTE_INSN_DELETED);
+      DONE;
+    }
+}
+  [(set_attr "length" "0,4")
+   (set_attr "type" "vecsimple")])
+
+(define_insn_and_split "*vsx_le_perm_load_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "vsx_register_operand" "=<VSa>")
+        (match_operand:VSX_LE_128 1 "memory_operand" "Z"))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "#"
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  [(set (match_dup 2)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 0)
+	(rotate:VSX_LE_128 (match_dup 2)
+			   (const_int 64)))]
+  "
+{
+  operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+                                       : operands[0];
+}
+  "
+  [(set_attr "type" "vecload")
+   (set_attr "length" "8")])
+
+(define_insn "*vsx_le_perm_store_<mode>"
+  [(set (match_operand:VSX_LE_128 0 "memory_operand" "=Z")
+        (match_operand:VSX_LE_128 1 "vsx_register_operand" "+<VSa>"))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX"
+  "#"
+  [(set_attr "type" "vecstore")
+   (set_attr "length" "12")])
+
+(define_split
+  [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
+        (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed"
+  [(set (match_dup 2)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 0)
+	(rotate:VSX_LE_128 (match_dup 2)
+			   (const_int 64)))]
+{
+  operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[0])
+                                       : operands[0];
+})
+
+;; The post-reload split requires that we re-permute the source
+;; register in case it is still live.
+(define_split
+  [(set (match_operand:VSX_LE_128 0 "memory_operand" "")
+        (match_operand:VSX_LE_128 1 "vsx_register_operand" ""))]
+  "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed"
+  [(set (match_dup 1)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 0)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))
+   (set (match_dup 1)
+	(rotate:VSX_LE_128 (match_dup 1)
+			   (const_int 64)))]
+  "")
 
 (define_insn "*vsx_mov<mode>"
   [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?<VSa>,?<VSa>,wQ,?&r,??Y,??r,??r,<VSr>,?<VSa>,*r,v,wZ, v")
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 226275)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1496,6 +1496,8 @@ enum r6000_reg_class_enum {
   RS6000_CONSTRAINT_wk,		/* FPR/VSX register for DFmode direct moves. */
   RS6000_CONSTRAINT_wl,		/* FPR register for LFIWAX */
   RS6000_CONSTRAINT_wm,		/* VSX register for direct move */
+  RS6000_CONSTRAINT_wp,		/* VSX reg for IEEE 128-bit fp TFmode. */
+  RS6000_CONSTRAINT_wq,		/* VSX reg for IEEE 128-bit fp KFmode.  */
   RS6000_CONSTRAINT_wr,		/* GPR register if 64-bit  */
   RS6000_CONSTRAINT_ws,		/* VSX register for DF */
   RS6000_CONSTRAINT_wt,		/* VSX register for TImode */
Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 226274)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -167,10 +167,27 @@ (define_mode_iterator VF [V4SF])
 (define_mode_iterator V [V4SI V8HI V16QI V4SF])
 ;; Vec modes for move/logical/permute ops, include vector types for move not
 ;; otherwise handled by altivec (v2df, v2di, ti)
-(define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI V1TI TI])
+(define_mode_iterator VM [V4SI
+			  V8HI
+			  V16QI
+			  V4SF
+			  V2DF
+			  V2DI
+			  V1TI
+			  TI
+			  (KF "FLOAT128_VECTOR_P (KFmode)")
+			  (TF "FLOAT128_VECTOR_P (TFmode)")])
 
 ;; Like VM, except don't do TImode
-(define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI V1TI])
+(define_mode_iterator VM2 [V4SI
+			   V8HI
+			   V16QI
+			   V4SF
+			   V2DF
+			   V2DI
+			   V1TI
+			   (KF "FLOAT128_VECTOR_P (KFmode)")
+			   (TF "FLOAT128_VECTOR_P (TFmode)")])
 
 (define_mode_attr VI_char [(V2DI "d") (V4SI "w") (V8HI "h") (V16QI "b")])
 (define_mode_attr VI_scalar [(V2DI "DI") (V4SI "SI") (V8HI "HI") (V16QI "QI")])
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	(revision 226275)
+++ gcc/doc/md.texi	(working copy)
@@ -3087,12 +3087,13 @@ Any VSX register if the -mvsx option was
 
 When using any of the register constraints (@code{wa}, @code{wd},
 @code{wf}, @code{wg}, @code{wh}, @code{wi}, @code{wj}, @code{wk},
-@code{wl}, @code{wm}, @code{ws}, @code{wt}, @code{wu}, @code{wv},
-@code{ww}, or @code{wy}) that take VSX registers, you must use
-@code{%x<n>} in the template so that the correct register is used.
-Otherwise the register number output in the assembly file will be
-incorrect if an Altivec register is an operand of a VSX instruction
-that expects VSX register numbering.
+@code{wl}, @code{wm}, @code{wp}, @code{wq}, @code{ws}, @code{wt},
+@code{wu}, @code{wv}, @code{ww}, or @code{wy})
+that take VSX registers, you must use @code{%x<n>} in the template so
+that the correct register is used.  Otherwise the register number
+output in the assembly file will be incorrect if an Altivec register
+is an operand of a VSX instruction that expects VSX register
+numbering.
 
 @smallexample
 asm ("xvadddp %x0,%x1,%x2" : "=wa" (v1) : "wa" (v2), "wa" (v3));
@@ -3136,6 +3137,12 @@ VSX register if direct move instructions
 @item wn
 No register (NO_REGS).
 
+@item wp
+VSX register to use for IEEE 128-bit floating point TFmode, or NO_REGS.
+
+@item wq
+VSX register to use for IEEE 128-bit floating point, or NO_REGS.
+
 @item wr
 General purpose register if 64-bit instructions are enabled or NO_REGS.
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
  2015-07-29 22:38 ` Segher Boessenkool
  2015-07-30 19:57 ` [PATCH], PowerPC IEEE 128-bit patch #4c (revised) Michael Meissner
@ 2015-07-31  2:49 ` Joseph Myers
  2015-08-03 19:02   ` Michael Meissner
  2015-08-14 15:47 ` [PATCH], PowerPC IEEE 128-bit patch #5 Michael Meissner
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Joseph Myers @ 2015-07-31  2:49 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

On Wed, 29 Jul 2015, Michael Meissner wrote:

>   #6	Add support for using different names for the 64/128-bit integer
> 	conversion to IBM extended double, to allow a future version to
> 	switch the default for what long double is. It is not expected that GCC
> 	6.x will make this switch, but we would like to eventually use the
> 	standard TF names for the library when the default change is made. If
> 	this isn't clear, the following names use 'tf' in them, when they use
> 	IBM extended double:

That would be for a completely separate ABI, incompatible with all 
existing objects both static and shared, since the existing ABI defines 
these names to have their existing meanings?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4c (revised)
  2015-07-30 19:57 ` [PATCH], PowerPC IEEE 128-bit patch #4c (revised) Michael Meissner
@ 2015-08-01 19:48   ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-08-01 19:48 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Thu, Jul 30, 2015 at 3:23 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> Seger pointed out that the altivec_high_bit insn was not safe if it was called
> when it could not allocate pseudos. I have removed that insn in this patch. I
> will revise the patch.  I had meant to tie it in with easy_altivec_constant
> originally, and I will do a patch with that change.
>
> Is this revised patch ok to install?  There are no references to
> altivec_high_bit in this patch set, so I just made sure it builds ok just
> removing the insn.
>
> 2015-07-30  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/vector.md (VEC_L): Add KFmode and TFmode.
>         (VEC_M): Likewise.
>         (VEC_N): Likewise.
>         (mov<mode>, VEC_M iterator): Add support for IEEE 128-bit floating
>         point in VSX registers.
>
>         * config/rs6000/constraints.md (wb constraint): Document unused
>         w<x> constraint.
>         (we constraint): Likewise.
>         (wo constraint): Likewise.
>         (wp constraint): New constraint for IEEE 128-bit floating point in
>         VSX registers.
>         (wq constraint): Likewise.
>
>         * config/rs6000/predicates.md (easy_fp_constant): Add support for
>         IEEE 128-bit floating point in VSX registers.
>         (easy_scalar_constant): Likewise.
>
>         * config/rs6000/rs6000.c (rs6000_debug_reg_global): Add new
>         constraints (wp, wq) for IEEE 128-bit floating point in VSX
>         registers.
>         (rs6000_init_hard_regno_mode_ok): Likewise.
>
>         * config/rs6000/vsx.md (VSX_LE_128): Add support for IEEE 128-bit
>         floating point in VSX registers.
>         (VSX_L): Likewise.
>         (VSX_M): Likewise.
>         (VSX_M2): Likewise.
>         (VSm): Likewise.
>         (VSs): Likewise.
>         (VSr): Likewise.
>         (VSa): Likewise.
>         (VSv): Likewise.
>         (vsx_le_permute_<mode>): Add support to properly swap bytes for
>         IEEE 128-bit floating point in VSX registers on little endian.
>         (vsx_le_undo_permute_<mode>): Likewise.
>         (vsx_le_perm_load_<mode>): Likewise.
>         (vsx_le_perm_store_<mode>): Likewise.
>         (splitters for IEEE 128-bit fp moves): Likewise.
>
>         * config/rs6000/rs6000.h (enum r6000_reg_class_enum): Add wp and
>         wq constraints.
>
>         * config/rs6000/altivec.md (VM): Add support for IEEE 128-bit
>         floating point in VSX registers.
>         (VM2): Likewise.
>
>         * doc/md.text (Machine Constraints): Document wp and wq
>         constraints on PowerPC.

This is okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-07-31  2:49 ` [PATCH], PowerPC IEEE 128-bit patch #4 Joseph Myers
@ 2015-08-03 19:02   ` Michael Meissner
  2015-08-03 21:18     ` Joseph Myers
  0 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-08-03 19:02 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Fri, Jul 31, 2015 at 12:43:20AM +0000, Joseph Myers wrote:
> On Wed, 29 Jul 2015, Michael Meissner wrote:
> 
> >   #6	Add support for using different names for the 64/128-bit integer
> > 	conversion to IBM extended double, to allow a future version to
> > 	switch the default for what long double is. It is not expected that GCC
> > 	6.x will make this switch, but we would like to eventually use the
> > 	standard TF names for the library when the default change is made. If
> > 	this isn't clear, the following names use 'tf' in them, when they use
> > 	IBM extended double:
> 
> That would be for a completely separate ABI, incompatible with all 
> existing objects both static and shared, since the existing ABI defines 
> these names to have their existing meanings?

The OpenPower 1.1 ABI for little endian PowerPC 64-bit does not mention the
names at all.  This ABI leaves it open whether long double is IBM extended
double or IEEE 128-bit floating point. One of the goals of these patches is
someday in the future change the default.

A lot of work, particularly in the library space needs to be done to change the
default. Until we can make the switch, users that want IEEE 128-bit support
will need to use __float128.

The intention of theese changes (currently unwritten) is to change the existing
problematical names that use TF in their name to be something else, and provide
via a weak reference an alias for the old name. So if for example, we change
the default in GCC 7.0, code compiled by GCC 6.0 would work because it uses say
__gcc_ltoq to call convert a 64-bit integer to IBM extended double instead of
__floatditf. Older code that refers to __floatditf would still work fine.

Then sometime later (such as GCC 8.0) we could make __floatditf be a weak
reference to __floatdikt.

If you have any ideas of how to do this seemlessly, please let me know.  Steve
Monroe and David Edelsohn requested that I explore that some date in the
future, we will be able to use the standard names.

I tend to be skeptical that we can do it without running into some
incompatibility, and I feel that we just have to live with the existing TF
names, and not use TF for IEEE 128-bit.

Currently, I'm using KF for the IEEE 128-bit functions, even if long double is
mapped to IEEE 128-bit instead of long double.

Another wrinkle is the 32-bit RTEMS port actually uses IEEE 128-bit floating
point with the standard names, because they never used the IBM extended
double.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #4
  2015-08-03 19:02   ` Michael Meissner
@ 2015-08-03 21:18     ` Joseph Myers
  0 siblings, 0 replies; 78+ messages in thread
From: Joseph Myers @ 2015-08-03 21:18 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

On Mon, 3 Aug 2015, Michael Meissner wrote:

> The intention of theese changes (currently unwritten) is to change the existing
> problematical names that use TF in their name to be something else, and provide
> via a weak reference an alias for the old name. So if for example, we change
> the default in GCC 7.0, code compiled by GCC 6.0 would work because it uses say
> __gcc_ltoq to call convert a 64-bit integer to IBM extended double instead of
> __floatditf. Older code that refers to __floatditf would still work fine.

But as those names are in the implementation namespace and aren't 
user-visible, I don't see the point in such a change (other than as part 
of a complete new incompatible ABI which gets its own copies of libgcc, 
libstdc++, libc, libm and other affected libraries).  Of course it *can* 
be done via symbol versioning to keep working with existing binaries / 
shared libraries using the existing symbols from libgcc, but the libgcc 
build system doesn't make that sort of target-specific symbol versioning 
particularly convenient.  And as usual with symbol versioning, you'd break 
compatibility with existing static libraries / .o files.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #5
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
                   ` (2 preceding siblings ...)
  2015-07-31  2:49 ` [PATCH], PowerPC IEEE 128-bit patch #4 Joseph Myers
@ 2015-08-14 15:47 ` Michael Meissner
  2015-08-19 12:47   ` Segher Boessenkool
  2015-08-14 15:49 ` [PATCH], PowerPC IEEE 128-bit patch #6 Michael Meissner
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-08-14 15:47 UTC (permalink / raw)
  To: gcc-patches, dje.gcc, Michael Meissner

[-- Attachment #1: Type: text/plain, Size: 3826 bytes --]

There are 3 patches left in the basic IEEE 128-bit floating point support for
the compiler. I will submit these at the same time. They are split to make the
review process similar.  Patch #5 and #6 are indpendent of each other and can
be applied in either order. Patch #7 assumes that patches 1-6 have been
applied.

Patch #5 adds the following:
 * Support for the reload handlers that will be enabled in patch #7.
 * Adds IFmode/KFmode to other iterators as appropriate.
 * Adds the basic negate, absolute value, and negative absolute value support.
 * Adds the insns for the 128-bit pack/unpack routines.

Patch #6 adds the following:
 * Adds support for comparisons.
 * Updates the cannot change mode support.

Patch #7 finishes up the initial basic support.
 * It defines macros for IEEE 128-bit floating point users.
 * It defines the basic move support.
 * It sets up the calling sequence.
 * It registers the __float128 and __ibm128 keywords.
 * It sets up the various handler functions.
 * It adds 'q' and 'Q' as the suffix for IEEE 128-bit floating point.
 * It adds target attribute/pragma support for the IEEE 128-bit options.
 * It treats IEEE 128-bit in VSX register modes as vector.
 * It uses a unique mangling for IEEE 128-bit in VSX registers.
 * It moves vector modes tieable above scalar floating point.
 * It adds a simple minded test to make sure IEEE args are passed as vectors.

Things to be done:
 * Work with GDB to add debug support.
 * Work with GLIBC to add basic software emulation support.
 * Work with GLIBC on other IEEE 128-bit support.
 * Look into Complex support.
 * Look into libquadmath support.
 * Enable -mfloat128-software if -mvsx.
 * Add more tests.
 * Fix bugs that show up if -mabi=ieeelongdouble is used.

Each patch bootstraps without error and has no regressions. Are they ok to
install in the trunk?

This is patch #5:

2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
	predicate for only GPR hard registers.

	* config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
	modes to iterators. Add new iterators for moving 128-bit values in
	scalar FPR registers and VSX registers.
	(FMOVE128): Likewise.
	(FMOVE128_FPR): Likewise.
	(FMOVE128_GPR): Likewise.
	(FMOVE128_VSX): Likewise.
	(FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
	in VSX registers.
	(IFKF): Likewise.
	(IBM128): Likewise.
	(TFIFKF): Likewise.
	(RELOAD): Add IEEE 128-bit floating point modes.
	(signbittf2): Convert TF insns to add support for new IEEE 128-bit
	floating point in VSX registers modes.
	(signbit<mode>2, IBM128 iterator): Likewise.
	(mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
	(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
	(negtf2): Likewise.
	(neg<mode>2, TFIFKF iterator): Likewise.
	(negtf2_internal): Likewise.
	(abstf2): Likewise.
	(abs<mode>2, TFIFKF iterator): Likewise.
	(ieee_128bit_negative_zero): New IEEE 128-bit floating point in
	VSX insn support for negate, absolute value, and negative absolute
	value.
	(ieee_128bit_vsx_neg<mode>2): Likewise.
	(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
	(ieee_128bit_vsx_abs<mode>2): Likewise.
	(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
	(ieee_128bit_vsx_nabs<mode>2): Likewise.
	(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
	(FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
	floating point in VSX registers.
	(unpack<mode>_dm): Likewise.
	(unpack<mode>_nodm): Likewise.
	(pack<mode>): Likewise.
	(unpackv1ti): Likewise.
	(unpack<mode>, FMOVE128_VSX iterator): Likewise.
	(packv1ti): Likewise.
	(pack<mode>, FMOVE128_VSX iterator): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch05b --]
[-- Type: text/plain, Size: 15980 bytes --]

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 226869)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -239,6 +239,25 @@ (define_predicate "int_reg_operand"
   return INT_REGNO_P (REGNO (op));
 })
 
+;; Like int_reg_operand, but don't return true for pseudo registers
+(define_predicate "int_reg_operand_not_pseudo"
+  (match_operand 0 "register_operand")
+{
+  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (!REG_P (op))
+    return 0;
+
+  if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
+    return 0;
+
+  return INT_REGNO_P (REGNO (op));
+})
+
 ;; Like int_reg_operand, but only return true for base registers
 (define_predicate "base_reg_operand"
   (match_operand 0 "int_reg_operand")
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 226869)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -348,6 +348,8 @@ (define_mode_iterator FP [
    && TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
+  (IF "TARGET_FLOAT128")
+  (KF "TARGET_FLOAT128")
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
@@ -365,9 +367,14 @@ (define_mode_iterator FMA_F [
 (define_mode_iterator FMOVE32 [SF SD])
 (define_mode_iterator FMOVE64 [DF DD])
 (define_mode_iterator FMOVE64X [DI DF DD])
-(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128")
+(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128")
+				(IF "TARGET_LONG_DOUBLE_128")
 				(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
 
+(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)")
+				    (IF "FLOAT128_2REG_P (IFmode)")
+				    (TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
+
 ; Iterators for 128 bit types for direct move
 (define_mode_iterator FMOVE128_GPR [(TI    "TARGET_VSX_TIMODE")
 				    (V16QI "")
@@ -376,7 +383,13 @@ (define_mode_iterator FMOVE128_GPR [(TI 
 				    (V4SF  "")
 				    (V2DI  "")
 				    (V2DF  "")
-				    (V1TI  "")])
+				    (V1TI  "")
+				    (KF    "")
+				    (TF    "")
+				    (IF    "")])
+
+; Iterator for 128-bit VSX types for pack/unpack
+(define_mode_iterator FMOVE128_VSX [V1TI KF])
 
 ; Whether a floating point move is ok, don't allow SD without hardware FP
 (define_mode_attr fmove_ok [(SF "")
@@ -432,6 +445,25 @@ (define_mode_iterator RECIPF [SF DF V4SF
 ; Iterator for just SF/DF
 (define_mode_iterator SFDF [SF DF])
 
+; Iterator for float128 floating conversions
+(define_mode_iterator FLOAT128_SFDFTF [
+    (SF "TARGET_FLOAT128")
+    (DF "TARGET_FLOAT128")
+    (TF "FLOAT128_IBM_P (TFmode)")
+    (IF "TARGET_FLOAT128")])
+
+; Iterator for special 128-bit floating point.  This is for non-default
+; conversions, so TFmode is not used here.
+(define_mode_iterator IFKF [IF KF])
+
+; Iterator for 128-bit floating point that uses the IBM double-double format
+(define_mode_iterator IBM128 [IF TF])
+
+; Iterator for 128-bit floating point
+(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128")
+			      (IF "TARGET_FLOAT128")
+			      (TF "TARGET_LONG_DOUBLE_128")])
+
 ; SF/DF suffix for traditional floating instructions
 (define_mode_attr Ftrad		[(SF "s") (DF "")])
 
@@ -596,7 +628,7 @@ (define_mode_attr BOOL_REGS_UNARY	[(TI	"
 ;; Reload iterator for creating the function to allocate a base register to
 ;; supplement addressing modes.
 (define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
-			      SF SD SI DF DD DI TI PTI])
+			      SF SD SI DF DD DI TI PTI KF IF TF])
 
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
@@ -4216,19 +4248,18 @@ (define_insn "*truncdfsf2_fpr"
 ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
 ;; builtins.c and optabs.c that are not correct for IBM long double
 ;; when little-endian.
-(define_expand "signbittf2"
+(define_expand "signbit<mode>2"
   [(set (match_dup 2)
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
+	(float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "")))
    (set (match_dup 3)
    	(subreg:DI (match_dup 2) 0))
    (set (match_dup 4)
    	(match_dup 5))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
   	(match_dup 6))]
-  "!TARGET_IEEEQUAD
+  "FLOAT128_IBM_P (<MODE>mode)
    && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)"
 {
   operands[2] = gen_reg_rtx (DFmode);
   operands[3] = gen_reg_rtx (DImode);
@@ -6402,9 +6433,10 @@ (define_expand "mov<mode>"
 ;; problematical.  Don't allow direct move for this case.
 
 (define_insn_and_split "*mov<mode>_64bit_dm"
-  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
-	(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
+   && FLOAT128_2REG_P (<MODE>mode)
    && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
@@ -6427,9 +6459,12 @@ (define_insn_and_split "*movtd_64bit_nod
   [(set_attr "length" "8,8,8,8,12,12,8")])
 
 (define_insn_and_split "*mov<mode>_32bit"
-  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
-	(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
+   && (FLOAT128_2REG_P (<MODE>mode)
+       || int_reg_operand_not_pseudo (operands[0], <MODE>mode)
+       || int_reg_operand_not_pseudo (operands[1], <MODE>mode))
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
   "#"
@@ -6663,20 +6698,37 @@ (define_insn_and_split "*fix_trunctfsi2_
   DONE;
 })
 
-(define_expand "negtf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
-  "")
+(define_expand "neg<mode>2"
+  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  "FLOAT128_IEEE_P (<MODE>mode)
+   || (FLOAT128_IBM_P (<MODE>mode)
+       && TARGET_HARD_FLOAT
+       && (TARGET_FPRS || TARGET_E500_DOUBLE))"
+  "
+{
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      if (TARGET_FLOAT128)
+	emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1]));
+      else
+	{
+	  rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
+	  rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST,
+						<MODE>mode, 1,
+						operands[1], <MODE>mode);
+
+	  if (target && !rtx_equal_p (target, operands[0]))
+	    emit_move_insn (operands[0], target);
+	}
+      DONE;
+    }
+}")
 
 (define_insn "negtf2_internal"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=d")
 	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
   "*
 {
   if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
@@ -6687,16 +6739,29 @@ (define_insn "negtf2_internal"
   [(set_attr "type" "fp")
    (set_attr "length" "8")])
 
-(define_expand "abstf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
+(define_expand "abs<mode>2"
+  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  "FLOAT128_IEEE_P (<MODE>mode)
+   || (FLOAT128_IBM_P (<MODE>mode)
+       && TARGET_HARD_FLOAT
+       && (TARGET_FPRS || TARGET_E500_DOUBLE))"
   "
 {
-  rtx label = gen_label_rtx ();
+  rtx label;
+
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      if (TARGET_FLOAT128)
+	{
+	  emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1]));
+	  DONE;
+	}
+      else
+	FAIL;
+    }
+
+  label = gen_label_rtx ();
   if (TARGET_E500_DOUBLE)
     {
       if (flag_finite_math_only && !flag_trapping_math)
@@ -6732,6 +6797,129 @@ (define_expand "abstf2_internal"
   operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
   operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
 }")
+
+\f
+;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector
+;; register
+
+(define_expand "ieee_128bit_negative_zero"
+  [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
+  "TARGET_FLOAT128"
+{
+  rtvec v = rtvec_alloc (16);
+  int i, high;
+
+  for (i = 0; i < 16; i++)
+    RTVEC_ELT (v, i) = const0_rtx;
+
+  high = (BYTES_BIG_ENDIAN) ? 0 : 15;
+  RTVEC_ELT (v, high) = GEN_INT (0x80);
+
+  rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v));
+  DONE;
+})
+
+;; IEEE 128-bit negate
+
+;; We have 2 insns here for negate and absolute value.  The first uses
+;; match_scratch so that phases like combine can recognize neg/abs as generic
+;; insns, and second insn after the first split pass loads up the bit to
+;; twiddle the sign bit.  Later GCSE passes can then combine multiple uses of
+;; neg/abs to create the constant just once.
+
+(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (neg:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlxor %x0,%x1,%x2"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecsimple")])
+
+;; IEEE 128-bit absolute value
+(define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (abs:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlandc %x0,%x1,%x2"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecsimple")])
+
+;; IEEE 128-bit negative absolute value
+(define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF
+	 (abs:TFIFKF
+	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (abs:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF
+	 (abs:TFIFKF
+	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlor %x0,%x1,%x2"
+  [(set_attr "length" "4")
+   (set_attr "type" "vecsimple")])
+
 \f
 ;; Reload helper functions used by rs6000_secondary_reload.  The patterns all
 ;; must have 3 arguments, and scratch register constraint must be a single
@@ -12134,7 +12322,10 @@ (define_insn "div<div_extend>_<mode>"
 ;; Pack/unpack 128-bit floating point types that take 2 scalar registers
 
 ; Type of the 64-bit part when packing/unpacking 128-bit floating point types
-(define_mode_attr FP128_64 [(TF "DF") (TD "DI")])
+(define_mode_attr FP128_64 [(TF "DF")
+			    (IF "DF")
+			    (TD "DI")
+			    (KF "DI")])
 
 (define_expand "unpack<mode>"
   [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
@@ -12142,7 +12333,7 @@ (define_expand "unpack<mode>"
 	 [(match_operand:FMOVE128 1 "register_operand" "")
 	  (match_operand:QI 2 "const_0_to_1_operand" "")]
 	 UNSPEC_UNPACK_128BIT))]
-  ""
+  "FLOAT128_2REG_P (<MODE>mode)"
   "")
 
 (define_insn_and_split "unpack<mode>_dm"
@@ -12151,7 +12342,7 @@ (define_insn_and_split "unpack<mode>_dm"
 	 [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 3))]
@@ -12175,7 +12366,7 @@ (define_insn_and_split "unpack<mode>_nod
 	 [(match_operand:FMOVE128 1 "register_operand" "d,d")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE"
+  "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 3))]
@@ -12199,7 +12390,7 @@ (define_insn_and_split "pack<mode>"
 	 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
 	  (match_operand:<FP128_64> 2 "register_operand" "d,d")]
 	 UNSPEC_PACK_128BIT))]
-  ""
+  "FLOAT128_2REG_P (<MODE>mode)"
   "@
    fmr %L0,%2
    #"
@@ -12219,12 +12410,12 @@ (define_insn_and_split "pack<mode>"
   [(set_attr "type" "fp,fp")
    (set_attr "length" "4,8")])
 
-(define_insn "unpackv1ti"
+(define_insn "unpack<mode>"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
-	(unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa")
+	(unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa")
 		    (match_operand:QI 2 "const_0_to_1_operand" "O,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "TARGET_VSX"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
 {
   if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
     return ASM_COMMENT_START " xxpermdi to same register";
@@ -12235,9 +12426,9 @@ (define_insn "unpackv1ti"
   [(set_attr "type" "vecperm")
    (set_attr "length" "4")])
 
-(define_insn "packv1ti"
-  [(set (match_operand:V1TI 0 "register_operand" "=wa")
-	(unspec:V1TI
+(define_insn "pack<mode>"
+  [(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa")
+	(unspec:FMOVE128_VSX
 	 [(match_operand:DI 1 "register_operand" "d")
 	  (match_operand:DI 2 "register_operand" "d")]
 	 UNSPEC_PACK_128BIT))]

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [PATCH], PowerPC IEEE 128-bit patch #6
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
                   ` (3 preceding siblings ...)
  2015-08-14 15:47 ` [PATCH], PowerPC IEEE 128-bit patch #5 Michael Meissner
@ 2015-08-14 15:49 ` Michael Meissner
  2015-08-26 13:57   ` David Edelsohn
  2015-08-14 15:56 ` [PATCH], PowerPC IEEE 128-bit patch #7 Michael Meissner
  2015-09-16 22:50 ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised) Michael Meissner
  6 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-08-14 15:49 UTC (permalink / raw)
  To: gcc-patches, dje.gcc, Michael Meissner

[-- Attachment #1: Type: text/plain, Size: 3206 bytes --]

There are 3 patches left in the basic IEEE 128-bit floating point support for
the compiler. I will submit these at the same time. They are split to make the
review process similar.  Patch #5 and #6 are indpendent of each other and can
be applied in either order. Patch #7 assumes that patches 1-6 have been
applied.

Patch #5 adds the following:
 * Support for the reload handlers that will be enabled in patch #7.
 * Adds IFmode/KFmode to other iterators as appropriate.
 * Adds the basic negate, absolute value, and negative absolute value support.
 * Adds the insns for the 128-bit pack/unpack routines.

Patch #6 adds the following:
 * Adds support for comparisons.
 * Updates the cannot change mode support.

Patch #7 finishes up the initial basic support.
 * It defines macros for IEEE 128-bit floating point users.
 * It defines the basic move support.
 * It sets up the calling sequence.
 * It registers the __float128 and __ibm128 keywords.
 * It sets up the various handler functions.
 * It adds 'q' and 'Q' as the suffix for IEEE 128-bit floating point.
 * It adds target attribute/pragma support for the IEEE 128-bit options.
 * It treats IEEE 128-bit in VSX register modes as vector.
 * It uses a unique mangling for IEEE 128-bit in VSX registers.
 * It moves vector modes tieable above scalar floating point.
 * It adds a simple minded test to make sure IEEE args are passed as vectors.

Things to be done:
 * Work with GDB to add debug support.
 * Work with GLIBC to add basic software emulation support.
 * Work with GLIBC on other IEEE 128-bit support.
 * Look into Complex support.
 * Look into libquadmath support.
 * Enable -mfloat128-software if -mvsx.
 * Add more tests.
 * Fix bugs that show up if -mabi=ieeelongdouble is used.

Each patch bootstraps without error and has no regressions. Are they ok to
install in the trunk?

This is patch #6:

2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert):
	Add declaration.

	* config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a
	comment.
	(rs6000_cannot_change_mode_class): Add support for IEEE 128-bit
	floating point in VSX registers.
	(rs6000_output_move_128bit): Always print out the set insn if we
	can't generate an appropriate 128-bit move.
	(rs6000_generate_compare): Add support for IEEE 128-bit floating
	point in VSX registers comparisons.
	(rs6000_expand_float128_convert): Likewise.

	* config/rs6000/rs6000.md (extenddftf2): Add support for IEEE
	128-bit floating point in VSX registers.
	(extenddftf2_internal): Likewise.
	(trunctfdf2): Likewise.
	(trunctfdf2_internal2): Likewise.
	(fix_trunc_helper): Likewise.
	(fix_trunctfdi2"): Likewise.
	(floatditf2): Likewise.
	(floatuns<mode>tf2): Likewise.
	(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
	(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
	(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(float<SDI:mode><IFKF:mode>2): Likewise.
	(floatuns<SDI:mode><IFKF:mode>2): Likewise.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch06 --]
[-- Type: text/plain, Size: 1186 bytes --]

2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert):
	Add declaration.

	* config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a
	comment.
	(rs6000_cannot_change_mode_class): Add support for IEEE 128-bit
	floating point in VSX registers.
	(rs6000_output_move_128bit): Always print out the set insn if we
	can't generate an appropriate 128-bit move.
	(rs6000_generate_compare): Add support for IEEE 128-bit floating
	point in VSX registers comparisons.
	(rs6000_expand_float128_convert): Likewise.

	* config/rs6000/rs6000.md (extenddftf2): Add support for IEEE
	128-bit floating point in VSX registers.
	(extenddftf2_internal): Likewise.
	(trunctfdf2): Likewise.
	(trunctfdf2_internal2): Likewise.
	(fix_trunc_helper): Likewise.
	(fix_trunctfdi2"): Likewise.
	(floatditf2): Likewise.
	(floatuns<mode>tf2): Likewise.
	(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
	(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
	(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(float<SDI:mode><IFKF:mode>2): Likewise.
	(floatuns<SDI:mode><IFKF:mode>2): Likewise.


^ permalink raw reply	[flat|nested] 78+ messages in thread

* [PATCH], PowerPC IEEE 128-bit patch #7
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
                   ` (4 preceding siblings ...)
  2015-08-14 15:49 ` [PATCH], PowerPC IEEE 128-bit patch #6 Michael Meissner
@ 2015-08-14 15:56 ` Michael Meissner
  2015-08-14 16:24   ` Michael Meissner
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
  2015-09-16 22:50 ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised) Michael Meissner
  6 siblings, 2 replies; 78+ messages in thread
From: Michael Meissner @ 2015-08-14 15:56 UTC (permalink / raw)
  To: gcc-patches, dje.gcc, Michael Meissner

[-- Attachment #1: Type: text/plain, Size: 4291 bytes --]

There are 3 patches left in the basic IEEE 128-bit floating point support for
the compiler. I will submit these at the same time. They are split to make the
review process similar.  Patch #5 and #6 are indpendent of each other and can
be applied in either order. Patch #7 assumes that patches 1-6 have been
applied.

Patch #5 adds the following:
 * Support for the reload handlers that will be enabled in patch #7.
 * Adds IFmode/KFmode to other iterators as appropriate.
 * Adds the basic negate, absolute value, and negative absolute value support.
 * Adds the insns for the 128-bit pack/unpack routines.

Patch #6 adds the following:
 * Adds support for comparisons.
 * Updates the cannot change mode support.

Patch #7 finishes up the initial basic support.
 * It defines macros for IEEE 128-bit floating point users.
 * It defines the basic move support.
 * It sets up the calling sequence.
 * It registers the __float128 and __ibm128 keywords.
 * It sets up the various handler functions.
 * It adds 'q' and 'Q' as the suffix for IEEE 128-bit floating point.
 * It adds target attribute/pragma support for the IEEE 128-bit options.
 * It treats IEEE 128-bit in VSX register modes as vector.
 * It uses a unique mangling for IEEE 128-bit in VSX registers.
 * It moves vector modes tieable above scalar floating point.
 * It adds a simple minded test to make sure IEEE args are passed as vectors.

Things to be done:
 * Work with GDB to add debug support.
 * Work with GLIBC to add basic software emulation support.
 * Work with GLIBC on other IEEE 128-bit support.
 * Look into Complex support.
 * Look into libquadmath support.
 * Enable -mfloat128-software if -mvsx.
 * Add more tests.
 * Fix bugs that show up if -mabi=ieeelongdouble is used.

Each patch bootstraps without error and has no regressions. Are they ok to
install in the trunk?

This is patch #7:

[gcc]
2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define user
	macros for IEEE 128-bit floating point in VSX registers.

	* config/rs6000/rs6000.c (TARGET_C_MODE_FOR_SUFFIX): Add 'q' or
	'Q' as the suffix for IEEE 128-bit floating point in VSX
	registers.
	(rs6000_c_mode_for_suffix): Likewise.
	(rs6000_init_hard_regno_mode_ok): Set up IEEE 128-bit floating
	point in VSX register mode support.
	(rs6000_gen_le_vsx_permute): Use ROTATE instead of VEC_SELECT for
	IEEE 128-bit floating point in VSX registers.
	(init_cumulative_args): When calling the library support
	functions, suppress passing values to IEEE 128-bit floating point
	in VSX registers in both the GPRs and VSX registers.
	(rs6000_function_arg): Likewise.
	(rs6000_arg_partial_bytes): Likewise.
	(rs6000_init_builtins): Likewise.
	(init_float128_ibm): Split 128-bit floating point support into two
	functions, and add support for IEEE 128-bit floating point in VSX
	registers.
	(init_float128_ieee): Likewise.
	(rs6000_init_libfuncs): Likewise.
	(rs6000_mangle_type): Use U10__float128 as the mangled type for
	IEEE 128-bit floating point in VSX registers.
	(struct rs6000_opt_var): Fix typo.
	(struct rs6000_float128_var): Add target attribute and pragma
	support for the IEEE 128-bit floating point in VSX registers.
	(rs6000_float128_vars): Likewise.
	(rs6000_inner_target_options): Likewise.

	* config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Treat IEEE 128-bit
	floating point in vector registers as a vector type.
	(MODES_TIEABLE_P): Move vector tests above floating point scalar
	tests, so that IEEE 128-bit floating point in VSX registers ties
	like a vector operand and not a scalar floating point operand.
	(struct rs6000_args): Add libcall field to support IEEE 128-bit
	floating point in VSX registers.

	* doc/extend.texi (additional floating types): Document PowerPC
	use of __float128 and __ibm128 types.

	* doc/invoke.texi (RS/6000 and PowerPC Options): Document
	-mfloat128-software and -mfloat128-none.

[gcc/testsuite]
2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/float128-call.c: New function, test whether
	IEEE 128-bit floating point in VSX registers is passed correctly.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07b --]
[-- Type: text/plain, Size: 27937 bytes --]

Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 226838)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -410,6 +410,10 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
+  if (TARGET_FLOAT128)
+    builtin_define ("__FLOAT128__");
+  if (TARGET_FLOAT128 == FLOAT128_SW)
+    builtin_define ("__FLOAT128_SOFTWARE__");
 
   if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM)
     {
@@ -483,6 +487,11 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     {
       builtin_define ("__LONG_DOUBLE_128__");
       builtin_define ("__LONGDOUBLE128");
+
+      if (TARGET_IEEEQUAD)
+	builtin_define ("__LONG_DOUBLE_IEEE128__");
+      else
+	builtin_define ("__LONG_DOUBLE_IBM128__");
     }
 
   switch (TARGET_CMODEL)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 226872)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1688,6 +1688,9 @@ static const struct attribute_spec rs600
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_C_MODE_FOR_SUFFIX
+#define TARGET_C_MODE_FOR_SUFFIX rs6000_c_mode_for_suffix
 \f
 
 /* Processor table.  */
@@ -2671,6 +2674,20 @@ rs6000_init_hard_regno_mode_ok (bool glo
       align32 = 128;
     }
 
+  /* KF mode (ieee 128-bit) where we can pass it as a vector.  We do not have
+     arithmetic, so only set the memory modes.  */
+  if (TARGET_FLOAT128)
+    {
+      rs6000_vector_mem[KFmode] = VECTOR_VSX;
+      rs6000_vector_align[KFmode] = 128;
+
+      if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
+	{
+	  rs6000_vector_mem[TFmode] = VECTOR_VSX;
+	  rs6000_vector_align[TFmode] = 128;
+	}
+    }
+
   /* V2DF mode, VSX only.  */
   if (TARGET_VSX)
     {
@@ -2887,6 +2904,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_di_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_di_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_di_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_di_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_di_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_di_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_di_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_di_store;
@@ -2894,6 +2913,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_di_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_di_load;
 
+	  if (TARGET_IEEEQUAD && TARGET_FLOAT128)
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_di_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_di_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -2947,6 +2972,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_si_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_si_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_si_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_si_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_si_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_si_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_si_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_si_store;
@@ -2954,6 +2981,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_si_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_si_load;
 
+	  if (TARGET_IEEEQUAD && TARGET_FLOAT128)
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_si_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_si_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -8421,8 +8454,14 @@ rs6000_const_vec (machine_mode mode)
 rtx
 rs6000_gen_le_vsx_permute (rtx source, machine_mode mode)
 {
-  rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
-  return gen_rtx_VEC_SELECT (mode, source, par);
+  /* Use ROTATE instead of VEC_SELECT on IEEE 128-bit floating point.  */
+  if (FLOAT128_VECTOR_P (mode))
+    return gen_rtx_ROTATE (mode, source, GEN_INT (64));
+  else
+    {
+      rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
+      return gen_rtx_VEC_SELECT (mode, source, par);
+    }
 }
 
 /* Emit a little-endian load from vector memory location SOURCE to VSX
@@ -9401,6 +9440,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      ? CALL_LIBCALL : CALL_NORMAL);
   cum->sysv_gregno = GP_ARG_MIN_REG;
   cum->stdarg = stdarg_p (fntype);
+  cum->libcall = libcall;
 
   cum->nargs_prototype = 0;
   if (incoming || cum->prototype)
@@ -10563,9 +10603,11 @@ rs6000_function_arg (cumulative_args_t c
       rtx r, off;
       int i, k = 0;
 
-      /* Do we also need to pass this argument in the parameter
-	 save area?  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* Do we also need to pass this argument in the parameter save area?
+	 Library support functions for IEEE 128-bit are assumed to not need the
+	 value passed both in GPRs and in vector registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	{
 	  int align_words = (cum->words + 1) & ~1;
 	  k = rs6000_psave_function_arg (mode, type, align_words, rvec);
@@ -10796,11 +10838,14 @@ rs6000_arg_partial_bytes (cumulative_arg
 
   if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
     {
-      /* If we are passing this arg in the fixed parameter save area
-         (gprs or memory) as well as VRs, we do not use the partial
-	 bytes mechanism; instead, rs6000_function_arg will return a
-	 PARALLEL including a memory element as necessary.  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* If we are passing this arg in the fixed parameter save area (gprs or
+         memory) as well as VRs, we do not use the partial bytes mechanism;
+         instead, rs6000_function_arg will return a PARALLEL including a memory
+         element as necessary.  Library support functions for IEEE 128-bit are
+         assumed to not need the value passed both in GPRs and in vector
+         registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	return 0;
 
       /* Otherwise, we pass in VRs only.  Check for partial copies.  */
@@ -14480,6 +14525,14 @@ rs6000_init_builtins (void)
   layout_type (ibm128_float_type_node);
   SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode);
 
+  if (TARGET_FLOAT128)
+    {
+      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+					      "__float128");
+      lang_hooks.types.register_builtin_type (ibm128_float_type_node,
+					      "__ibm128");
+    }
+
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
   builtin_mode_to_type[QImode][0] = integer_type_node;
@@ -15984,78 +16037,150 @@ rs6000_common_init_builtins (void)
     }
 }
 
+/* Set up AIX/Darwin/64-bit Linux quad floating point routines.  */
 static void
-rs6000_init_libfuncs (void)
+init_float128_ibm (machine_mode mode)
 {
-  if (!TARGET_IEEEQUAD)
-      /* AIX/Darwin/64-bit Linux quad floating point routines.  */
-    if (!TARGET_XL_COMPAT)
-      {
-	set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
-	set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
-	set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
+  if (!TARGET_XL_COMPAT)
+    {
+      set_optab_libfunc (add_optab, mode, "__gcc_qadd");
+      set_optab_libfunc (sub_optab, mode, "__gcc_qsub");
+      set_optab_libfunc (smul_optab, mode, "__gcc_qmul");
+      set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv");
 
-	if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
-	  {
-	    set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
-	    set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
-	    set_optab_libfunc (ne_optab, TFmode, "__gcc_qne");
-	    set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt");
-	    set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
-	    set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
-	    set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
-
-	    set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
-	    set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
-	    set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos");
-	    set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod");
-	    set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi");
-	    set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou");
-	    set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
-	    set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
-	  }
+      if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
+	{
+	  set_optab_libfunc (neg_optab, mode, "__gcc_qneg");
+	  set_optab_libfunc (eq_optab, mode, "__gcc_qeq");
+	  set_optab_libfunc (ne_optab, mode, "__gcc_qne");
+	  set_optab_libfunc (gt_optab, mode, "__gcc_qgt");
+	  set_optab_libfunc (ge_optab, mode, "__gcc_qge");
+	  set_optab_libfunc (lt_optab, mode, "__gcc_qlt");
+	  set_optab_libfunc (le_optab, mode, "__gcc_qle");
 
-	if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
-	  set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
-      }
-    else
-      {
-	set_optab_libfunc (add_optab, TFmode, "_xlqadd");
-	set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
-	set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
-      }
+	  set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq");
+	  set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq");
+	  set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos");
+	  set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod");
+	  set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi");
+	  set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou");
+	  set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq");
+	  set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq");
+	}
+
+      if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
+	set_optab_libfunc (unord_optab, mode, "__gcc_qunord");
+    }
   else
     {
-      /* 32-bit SVR4 quad floating point routines.  */
+      set_optab_libfunc (add_optab, mode, "_xlqadd");
+      set_optab_libfunc (sub_optab, mode, "_xlqsub");
+      set_optab_libfunc (smul_optab, mode, "_xlqmul");
+      set_optab_libfunc (sdiv_optab, mode, "_xlqdiv");
+    }
+}
+
+/* Set up IEEE 128-bit floating point routines.  Use different names if the
+   arguments can be passed in a vector register.  The historical PowerPC
+   implementation of IEEE 128-bit floating point used _q_<op> for the names, so
+   continue to use that if we can't pass IEEE 128-bit in a VSX vector register.
 
-      set_optab_libfunc (add_optab, TFmode, "_q_add");
-      set_optab_libfunc (sub_optab, TFmode, "_q_sub");
-      set_optab_libfunc (neg_optab, TFmode, "_q_neg");
-      set_optab_libfunc (smul_optab, TFmode, "_q_mul");
-      set_optab_libfunc (sdiv_optab, TFmode, "_q_div");
+   Add _vector to clarify that this function is called with the argument in a
+   vector register, and _fpr when we are not passing IEEE 128-bit in a vector
+   register.  */
+
+static void
+init_float128_ieee (machine_mode mode)
+{
+  if (FLOAT128_VECTOR_P (mode))
+    {
+      set_optab_libfunc (add_optab, mode, "__addkf3");
+      set_optab_libfunc (sub_optab, mode, "__subkf3");
+      set_optab_libfunc (neg_optab, mode, "__negkf2");
+      set_optab_libfunc (smul_optab, mode, "__mulkf3");
+      set_optab_libfunc (sdiv_optab, mode, "__divkf3");
+      set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2");
+      set_optab_libfunc (abs_optab, mode, "__abstkf2");
+
+      set_optab_libfunc (eq_optab, mode, "__eqkf2");
+      set_optab_libfunc (ne_optab, mode, "__nekf2");
+      set_optab_libfunc (gt_optab, mode, "__gtkf2");
+      set_optab_libfunc (ge_optab, mode, "__gekf2");
+      set_optab_libfunc (lt_optab, mode, "__ltkf2");
+      set_optab_libfunc (le_optab, mode, "__lekf2");
+      set_optab_libfunc (unord_optab, mode, "__unordkf2");
+      set_optab_libfunc (cmp_optab, mode, "__cmpkf2");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2");
+      set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2");
+
+      set_conv_libfunc (sfix_optab, SImode, mode, "__fixkfsi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "__fixunskfsi");
+      set_conv_libfunc (sfix_optab, DImode, mode, "__fixkfdi");
+      set_conv_libfunc (ufix_optab, DImode, mode, "__fixunskfdi");
+
+      set_conv_libfunc (sfloat_optab, mode, SImode, "__floatsikf");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "__floatunsikf");
+      set_conv_libfunc (sfloat_optab, mode, DImode, "__floatdikf");
+      set_conv_libfunc (ufloat_optab, mode, DImode, "__floatundikf");
+
+      if (mode == KFmode)
+	{
+	  set_conv_libfunc (sext_optab, IFmode, KFmode, "__extendkftf2");
+	  set_conv_libfunc (trunc_optab, KFmode, IFmode, "__trunctfkf2");
+
+	  if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
+	    {
+	      set_conv_libfunc (sext_optab, TFmode, KFmode, "__extendkftf2");
+	      set_conv_libfunc (trunc_optab, mode, KFmode, "__trunctfkf2");
+	    }
+	}
+    }
+
+  else
+    {
+      set_optab_libfunc (add_optab, mode, "_q_add");
+      set_optab_libfunc (sub_optab, mode, "_q_sub");
+      set_optab_libfunc (neg_optab, mode, "_q_neg");
+      set_optab_libfunc (smul_optab, mode, "_q_mul");
+      set_optab_libfunc (sdiv_optab, mode, "_q_div");
       if (TARGET_PPC_GPOPT)
-	set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
+	set_optab_libfunc (sqrt_optab, mode, "_q_sqrt");
 
-      set_optab_libfunc (eq_optab, TFmode, "_q_feq");
-      set_optab_libfunc (ne_optab, TFmode, "_q_fne");
-      set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
-      set_optab_libfunc (ge_optab, TFmode, "_q_fge");
-      set_optab_libfunc (lt_optab, TFmode, "_q_flt");
-      set_optab_libfunc (le_optab, TFmode, "_q_fle");
-
-      set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
-      set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
-      set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
-      set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
-      set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
-      set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
-      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
-      set_conv_libfunc (ufloat_optab, TFmode, SImode, "_q_utoq");
+      set_optab_libfunc (eq_optab, mode, "_q_feq");
+      set_optab_libfunc (ne_optab, mode, "_q_fne");
+      set_optab_libfunc (gt_optab, mode, "_q_fgt");
+      set_optab_libfunc (ge_optab, mode, "_q_fge");
+      set_optab_libfunc (lt_optab, mode, "_q_flt");
+      set_optab_libfunc (le_optab, mode, "_q_fle");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "_q_stoq");
+      set_conv_libfunc (sext_optab, mode, DFmode, "_q_dtoq");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "_q_qtos");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "_q_qtod");
+      set_conv_libfunc (sfix_optab, SImode, mode, "_q_qtoi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "_q_qtou");
+      set_conv_libfunc (sfloat_optab, mode, SImode, "_q_itoq");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "_q_utoq");
     }
 }
 
+static void
+rs6000_init_libfuncs (void)
+{
+  /* AIX/Darwin/64-bit Linux quad floating point routines.  */
+  init_float128_ibm (IFmode);
+  if (!TARGET_IEEEQUAD)
+    init_float128_ibm (TFmode);
+
+  /* IEEE 128-bit including 32-bit SVR4 quad floating point routines.  */
+  init_float128_ieee (KFmode);
+  if (TARGET_IEEEQUAD)
+    init_float128_ieee (TFmode);
+}
+
 \f
 /* Expand a block clear operation, and return 1 if successful.  Return 0
    if we should let the compiler generate normal code.
@@ -29763,9 +29888,13 @@ rs6000_mangle_type (const_tree type)
   if (type == bool_int_type_node) return "U6__booli";
   if (type == bool_long_type_node) return "U6__booll";
 
+  /* Use a unique name for __float128 rather than trying to use "e" or "g".  */
+  if (type == ieee128_float_type_node && TARGET_FLOAT128)
+    return "U10__float128";
+
   /* Mangle IBM extended float long double as `g' (__float128) on
      powerpc*-linux where long-double-64 previously was the default.  */
-  if (TYPE_MAIN_VARIANT (type) == long_double_type_node
+  if (type == long_double_type_node
       && TARGET_ELF
       && TARGET_LONG_DOUBLE_128
       && !TARGET_IEEEQUAD)
@@ -33014,6 +33143,26 @@ rs6000_vector_mode_supported_p (machine_
     return false;
 }
 
+/* Target hook for c_mode_for_suffix.  */
+static machine_mode
+rs6000_c_mode_for_suffix (char suffix)
+{
+  if (TARGET_FLOAT128 && TARGET_LONG_DOUBLE_128)
+    {
+      if (suffix == 'q' || suffix == 'Q')
+	return (TARGET_IEEEQUAD) ? TFmode : KFmode;
+
+      /* At the moment, we are not defining a suffix for IBM extended double.
+	 If/when the default for -mabi=ieeelongdouble is changed, and we want
+	 to support __ibm128 constants in legacy library code, we may need to
+	 re-evalaute this decision.  Currently, c-lex.c only supports 'w' and
+	 'q' as machine dependent suffixes.  The x86_64 port uses 'w' for
+	 __float80 constants.  */
+    }
+
+  return VOIDmode;
+}
+
 /* Target hook for invalid_arg_for_unprototyped_fn. */
 static const char *
 invalid_arg_for_unprototyped_fn (const_tree typelist, const_tree funcdecl, const_tree val)
@@ -33175,7 +33324,7 @@ static struct rs6000_opt_mask const rs60
 struct rs6000_opt_var {
   const char *name;		/* option name */
   size_t global_offset;		/* offset of the option in global_options.  */
-  size_t target_offset;		/* offset of the option in target optiosn.  */
+  size_t target_offset;		/* offset of the option in target options.  */
 };
 
 static struct rs6000_opt_var const rs6000_opt_vars[] =
@@ -33230,6 +33379,21 @@ static struct rs6000_opt_var const rs600
     offsetof (struct cl_target_option, x_rs6000_warn_cell_microcode), },
 };
 
+/* Float128 options we want to support inside attribute((target)) and #pragma
+   GCC target operations.  */
+
+struct rs6000_float128_var {
+  const char *name;		/* option name.  */
+  enum float128_type_t type;	/* float128 type.  */
+};
+
+static struct rs6000_float128_var const rs6000_float128_vars[] =
+{
+  { "float128-none",		FLOAT128_NONE },
+  { "float128-software",	FLOAT128_SW },
+  { "float128-sw",		FLOAT128_SW },
+};
+
 /* Inner function to handle attribute((target("..."))) and #pragma GCC target
    parsing.  Return true if there were no errors.  */
 
@@ -33322,6 +33486,18 @@ rs6000_inner_target_options (tree args, 
 		    break;
 		  }
 
+	      if (error_p && !not_valid_p && !invert)
+		{
+		  for (i = 0; i < ARRAY_SIZE (rs6000_float128_vars); i++)
+		    if (strcmp (r, rs6000_float128_vars[i].name) == 0)
+		      {
+			TARGET_FLOAT128 = rs6000_float128_vars[i].type;
+			error_p = false;
+			not_valid_p = false;
+			break;
+		      }
+		}
+
 	      if (error_p && !not_valid_p)
 		{
 		  for (i = 0; i < ARRAY_SIZE (rs6000_opt_vars); i++)
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 226838)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1217,11 +1217,16 @@ enum data_align { align_abi, align_opt, 
 	 ((MODE) == V4SFmode		\
 	  || (MODE) == V2DFmode)	\
 
-#define ALTIVEC_VECTOR_MODE(MODE)	\
-	 ((MODE) == V16QImode		\
-	  || (MODE) == V8HImode		\
-	  || (MODE) == V4SFmode		\
-	  || (MODE) == V4SImode)
+/* Note KFmode and possibly TFmode (i.e. IEEE 128-bit floating point) are not
+   really a vector, but we want to treat it as a vector for moves, and
+   such.  */
+
+#define ALTIVEC_VECTOR_MODE(MODE)					\
+  ((MODE) == V16QImode							\
+   || (MODE) == V8HImode						\
+   || (MODE) == V4SFmode						\
+   || (MODE) == V4SImode						\
+   || FLOAT128_VECTOR_P (MODE))
 
 #define ALTIVEC_OR_VSX_VECTOR_MODE(MODE)				\
   (ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)			\
@@ -1248,12 +1253,19 @@ enum data_align { align_abi, align_opt, 
 
    PTImode cannot tie with other modes because PTImode is restricted to even
    GPR registers, and TImode can go in any GPR as well as VSX registers (PR
-   57744).  */
+   57744).
+
+   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
+   128-bit floating point on VSX systems ties with other vectors.  */
 #define MODES_TIEABLE_P(MODE1, MODE2)		\
   ((MODE1) == PTImode				\
    ? (MODE2) == PTImode				\
    : (MODE2) == PTImode				\
    ? 0						\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
+   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   ? 0						\
    : SCALAR_FLOAT_MODE_P (MODE1)		\
    ? SCALAR_FLOAT_MODE_P (MODE2)		\
    : SCALAR_FLOAT_MODE_P (MODE2)		\
@@ -1266,10 +1278,6 @@ enum data_align { align_abi, align_opt, 
    ? SPE_VECTOR_MODE (MODE2)			\
    : SPE_VECTOR_MODE (MODE2)			\
    ? 0						\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
-   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   ? 0						\
    : 1)
 
 /* Post-reload, we can't use any new AltiVec registers, as we already
@@ -1801,6 +1809,7 @@ typedef struct rs6000_args
 				   GPR space (darwin64) */
   int named;			/* false for varargs params */
   int escapes;			/* if function visible outside tu */
+  int libcall;			/* If this is a compiler generated call.  */
 } CUMULATIVE_ARGS;
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 226838)
+++ gcc/doc/extend.texi	(working copy)
@@ -929,6 +929,7 @@ examine and set these two fictitious var
 @cindex additional floating types
 @cindex @code{__float80} data type
 @cindex @code{__float128} data type
+@cindex @code{__ibm128} data type
 @cindex @code{w} floating point suffix
 @cindex @code{q} floating point suffix
 @cindex @code{W} floating point suffix
@@ -941,19 +942,39 @@ Support for additional types includes th
 add, subtract, multiply, divide; unary arithmetic operators;
 relational operators; equality operators; and conversions to and from
 integer and other floating types.  Use a suffix @samp{w} or @samp{W}
-in a literal constant of type @code{__float80} and @samp{q} or @samp{Q}
-for @code{_float128}.  You can declare complex types using the
-corresponding internal complex type, @code{XCmode} for @code{__float80}
-type and @code{TCmode} for @code{__float128} type:
+in a literal constant of type @code{__float80} or type
+@code{__ibm128}.  Use a suffix @samp{q} or @samp{Q} for @code{_float128}.
+
+On the i386, x86_64, IA-64, and HP-UX targets, you can declare complex
+types using the corresponding internal complex type, @code{XCmode} for
+@code{__float80} type and @code{TCmode} for @code{__float128} type:
 
 @smallexample
 typedef _Complex float __attribute__((mode(TC))) _Complex128;
 typedef _Complex float __attribute__((mode(XC))) _Complex80;
 @end smallexample
 
+On PowerPC Linux, Freebsd and Darwin systems, the default for
+@code{long double} is to use the IBM extended floating point format
+that uses a pair of @code{double} values to extend the precision.
+This means that the mode @code{TCmode} was already used by the
+traditional IBM long double format, and you would need to use the mode
+@code{KCmode}:
+
+@smallexample
+typedef _Complex float __attribute__((mode(KC))) _Complex128;
+@end smallexample
+
 Not all targets support additional floating-point types.  @code{__float80}
 and @code{__float128} types are supported on x86 and IA-64 targets.
-The @code{__float128} type is supported on hppa HP-UX targets.
+The @code{__float128} type is supported on hppa HP-UX.
+The @code{__float128} type is supported on PowerPC systems by default
+if the vector scalar instruction set (VSX) is enabled.
+
+On the PowerPC, @code{__ibm128} provides access to the IBM extended
+double format, and it is intended to be used by the library functions
+that handle conversions if/when long double is changed to be IEEE
+128-bit floating point.
 
 @node Half-Precision
 @section Half-Precision Floating Point
@@ -13318,6 +13339,8 @@ uint64_t __builtin_ppc_get_timebase ();
 unsigned long __builtin_ppc_mftb ();
 double __builtin_unpack_longdouble (long double, int);
 long double __builtin_pack_longdouble (double, double);
+double __builtin_unpack_ibm128 (long double, int);
+__ibm128 __builtin_pack_ibm128 (double, double);
 @end smallexample
 
 The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 226838)
+++ gcc/doc/invoke.texi	(working copy)
@@ -940,7 +940,8 @@ See RS/6000 and PowerPC Options.
 -mquad-memory-atomic -mno-quad-memory-atomic @gol
 -mcompat-align-parm -mno-compat-align-parm @gol
 -mupper-regs-df -mno-upper-regs-df -mupper-regs-sf -mno-upper-regs-sf @gol
--mupper-regs -mno-upper-regs}
+-mupper-regs -mno-upper-regs @gol
+-mfloat128-software -mfloat128-none}
 
 @emph{RX Options}
 @gccoptlist{-m64bit-doubles  -m32bit-doubles  -fpu  -nofpu@gol
@@ -19410,6 +19411,20 @@ floating point register set, depending o
 If the @option{-mno-upper-regs} option is used, it turns off both
 @option{-mupper-regs-sf} and @option{-mupper-regs-df} options.
 
+@item -mfloat128-software
+@opindex mfloat128-software
+Enable the @var{__float128} keyword for IEEE 128-bit floating point
+and use software emulation for IEEE 128-bit floating point.
+@option{-mfloat128-software} option is enabled by default with either
+of the the @option{-mcpu=power7} or @option{-mcpu=power8} options.
+
+The VSX instruction set must be enabled to use the
+@option{-mfloat128-software} option.
+
+@item -mfloat128-none
+@opindex mfloat128-none
+Disable the use of the @var{__float128} keyword.
+
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
 @opindex mfloat-gprs
Index: gcc/testsuite/gcc.target/powerpc/float128-call.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-call.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-call.c	(revision 0)
@@ -0,0 +1,27 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-O2 -mcpu=power7 -mfloat128-software -mno-regnames" } */
+
+#ifndef __FLOAT128_SOFTWARE__
+#error "-mfloat128-software is not supported."
+#endif
+
+#ifdef __LONG_DOUBLE_IEEE128__
+#define TYPE long double
+#define ONE  1.0L
+
+#else
+#define TYPE __float128
+#define ONE  1.0Q
+#endif
+
+/* Test to make sure vector registers are used for passing IEEE 128-bit
+   floating point values and returning them. Also make sure the 'q' suffix is
+   handled.  */
+TYPE one (void) { return ONE; }
+void store (TYPE a, TYPE *p) { *p = a; }
+
+/* { dg-final { scan-assembler "lxvd2x 34"  } } */
+/* { dg-final { scan-assembler "stxvd2x 34" } } */

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7
  2015-08-14 15:56 ` [PATCH], PowerPC IEEE 128-bit patch #7 Michael Meissner
@ 2015-08-14 16:24   ` Michael Meissner
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
  1 sibling, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-08-14 16:24 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

I meant to say splitting the patches was meant to make the reviewing simpler,
not similar.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #5
  2015-08-14 15:47 ` [PATCH], PowerPC IEEE 128-bit patch #5 Michael Meissner
@ 2015-08-19 12:47   ` Segher Boessenkool
  2015-08-25 23:33     ` Michael Meissner
  0 siblings, 1 reply; 78+ messages in thread
From: Segher Boessenkool @ 2015-08-19 12:47 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

On Fri, Aug 14, 2015 at 11:46:03AM -0400, Michael Meissner wrote:
> +;; Like int_reg_operand, but don't return true for pseudo registers
> +(define_predicate "int_reg_operand_not_pseudo"
> +  (match_operand 0 "register_operand")
> +{
> +  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
> +    return 0;
> +
> +  if (GET_CODE (op) == SUBREG)
> +    op = SUBREG_REG (op);
> +
> +  if (!REG_P (op))
> +    return 0;
> +
> +  if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
> +    return 0;
> +
> +  return INT_REGNO_P (REGNO (op));
> +})

Since you use this only once, maybe it is easier (to read, etc.) if you
just test it there?  Hard regs do not get subregs.

> +(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
> +  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
> +	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
> +   (clobber (match_scratch:V16QI 2 "=v"))]
> +  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
> +  "#"
> +  "&& 1"
> +  [(parallel [(set (match_dup 0)
> +		   (neg:TFIFKF (match_dup 1)))
> +	      (use (match_dup 2))])]
> +{
> +  if (GET_CODE (operands[2]) == SCRATCH)
> +    operands[2] = gen_reg_rtx (V16QImode);
> +
> +  operands[3] = gen_reg_rtx (V16QImode);
> +  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
> +}
> +  [(set_attr "length" "8")
> +   (set_attr "type" "vecsimple")])

Where is operands[3] used?  I guess that whole line should be deleted?

> +(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
> +  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
> +	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
> +   (use (match_operand:V16QI 2 "register_operand" "=v"))]
> +  "TARGET_FLOAT128"
> +  "xxlxor %x0,%x1,%x2"
> +  [(set_attr "length" "4")
> +   (set_attr "type" "vecsimple")])

Length 4 is default, you can just leave it out (like we do for most
machine insns already).


Segher

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #5
  2015-08-19 12:47   ` Segher Boessenkool
@ 2015-08-25 23:33     ` Michael Meissner
  2015-08-26 13:16       ` David Edelsohn
  0 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-08-25 23:33 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 4444 bytes --]

On Wed, Aug 19, 2015 at 07:41:24AM -0500, Segher Boessenkool wrote:
> On Fri, Aug 14, 2015 at 11:46:03AM -0400, Michael Meissner wrote:
> > +;; Like int_reg_operand, but don't return true for pseudo registers
> > +(define_predicate "int_reg_operand_not_pseudo"
> > +  (match_operand 0 "register_operand")
> > +{
> > +  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
> > +    return 0;
> > +
> > +  if (GET_CODE (op) == SUBREG)
> > +    op = SUBREG_REG (op);
> > +
> > +  if (!REG_P (op))
> > +    return 0;
> > +
> > +  if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
> > +    return 0;
> > +
> > +  return INT_REGNO_P (REGNO (op));
> > +})
> 
> Since you use this only once, maybe it is easier (to read, etc.) if you
> just test it there?  Hard regs do not get subregs.

I was worried about hard regs appearing before reload, and possibly being
subregs, so I'll remove the SUBREG test.

> > +(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
> > +  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
> > +	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
> > +   (clobber (match_scratch:V16QI 2 "=v"))]
> > +  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
> > +  "#"
> > +  "&& 1"
> > +  [(parallel [(set (match_dup 0)
> > +		   (neg:TFIFKF (match_dup 1)))
> > +	      (use (match_dup 2))])]
> > +{
> > +  if (GET_CODE (operands[2]) == SCRATCH)
> > +    operands[2] = gen_reg_rtx (V16QImode);
> > +
> > +  operands[3] = gen_reg_rtx (V16QImode);
> > +  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
> > +}
> > +  [(set_attr "length" "8")
> > +   (set_attr "type" "vecsimple")])
> 
> Where is operands[3] used?  I guess that whole line should be deleted?

Good catch. It was from the earlier patch before the fix for PR 67071, which
added better support for vector constants that can be constructed with several
vector operations, including a vector octet shift.

> > +(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
> > +  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
> > +	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
> > +   (use (match_operand:V16QI 2 "register_operand" "=v"))]
> > +  "TARGET_FLOAT128"
> > +  "xxlxor %x0,%x1,%x2"
> > +  [(set_attr "length" "4")
> > +   (set_attr "type" "vecsimple")])
> 
> Length 4 is default, you can just leave it out (like we do for most
> machine insns already).

Ok, though I tend to always put them in.

Here is the revised patch. Is it ok to install?

2015-08-25  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
	predicate for only GPR hard registers.

	* config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
	modes to iterators. Add new iterators for moving 128-bit values in
	scalar FPR registers and VSX registers.
	(FMOVE128): Likewise.
	(FMOVE128_FPR): Likewise.
	(FMOVE128_GPR): Likewise.
	(FMOVE128_VSX): Likewise.
	(FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
	in VSX registers.
	(IFKF): Likewise.
	(IBM128): Likewise.
	(TFIFKF): Likewise.
	(RELOAD): Add IEEE 128-bit floating point modes.
	(signbittf2): Convert TF insns to add support for new IEEE 128-bit
	floating point in VSX registers modes.
	(signbit<mode>2, IBM128 iterator): Likewise.
	(mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
	(mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
	(negtf2): Likewise.
	(neg<mode>2, TFIFKF iterator): Likewise.
	(negtf2_internal): Likewise.
	(abstf2): Likewise.
	(abs<mode>2, TFIFKF iterator): Likewise.
	(ieee_128bit_negative_zero): New IEEE 128-bit floating point in
	VSX insn support for negate, absolute value, and negative absolute
	value.
	(ieee_128bit_vsx_neg<mode>2): Likewise.
	(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
	(ieee_128bit_vsx_abs<mode>2): Likewise.
	(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
	(ieee_128bit_vsx_nabs<mode>2): Likewise.
	(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
	(FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
	floating point in VSX registers.
	(unpack<mode>_dm): Likewise.
	(unpack<mode>_nodm): Likewise.
	(pack<mode>): Likewise.
	(unpackv1ti): Likewise.
	(unpack<mode>, FMOVE128_VSX iterator): Likewise.
	(packv1ti): Likewise.
	(pack<mode>, FMOVE128_VSX iterator): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch05d --]
[-- Type: text/plain, Size: 16181 bytes --]

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 227180)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -239,6 +239,25 @@ (define_predicate "int_reg_operand"
   return INT_REGNO_P (REGNO (op));
 })
 
+;; Like int_reg_operand, but don't return true for pseudo registers
+(define_predicate "int_reg_operand_not_pseudo"
+  (match_operand 0 "register_operand")
+{
+  if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode))
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (!REG_P (op))
+    return 0;
+
+  if (REGNO (op) >= FIRST_PSEUDO_REGISTER)
+    return 0;
+
+  return INT_REGNO_P (REGNO (op));
+})
+
 ;; Like int_reg_operand, but only return true for base registers
 (define_predicate "base_reg_operand"
   (match_operand 0 "int_reg_operand")
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 227180)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -348,6 +348,8 @@ (define_mode_iterator FP [
    && TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
+  (IF "TARGET_FLOAT128")
+  (KF "TARGET_FLOAT128")
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
@@ -365,9 +367,14 @@ (define_mode_iterator FMA_F [
 (define_mode_iterator FMOVE32 [SF SD])
 (define_mode_iterator FMOVE64 [DF DD])
 (define_mode_iterator FMOVE64X [DI DF DD])
-(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128")
+(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128")
+				(IF "TARGET_LONG_DOUBLE_128")
 				(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
 
+(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)")
+				    (IF "FLOAT128_2REG_P (IFmode)")
+				    (TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
+
 ; Iterators for 128 bit types for direct move
 (define_mode_iterator FMOVE128_GPR [(TI    "TARGET_VSX_TIMODE")
 				    (V16QI "")
@@ -376,7 +383,13 @@ (define_mode_iterator FMOVE128_GPR [(TI 
 				    (V4SF  "")
 				    (V2DI  "")
 				    (V2DF  "")
-				    (V1TI  "")])
+				    (V1TI  "")
+				    (KF    "")
+				    (TF    "")
+				    (IF    "")])
+
+; Iterator for 128-bit VSX types for pack/unpack
+(define_mode_iterator FMOVE128_VSX [V1TI KF])
 
 ; Whether a floating point move is ok, don't allow SD without hardware FP
 (define_mode_attr fmove_ok [(SF "")
@@ -432,6 +445,25 @@ (define_mode_iterator RECIPF [SF DF V4SF
 ; Iterator for just SF/DF
 (define_mode_iterator SFDF [SF DF])
 
+; Iterator for float128 floating conversions
+(define_mode_iterator FLOAT128_SFDFTF [
+    (SF "TARGET_FLOAT128")
+    (DF "TARGET_FLOAT128")
+    (TF "FLOAT128_IBM_P (TFmode)")
+    (IF "TARGET_FLOAT128")])
+
+; Iterator for special 128-bit floating point.  This is for non-default
+; conversions, so TFmode is not used here.
+(define_mode_iterator IFKF [IF KF])
+
+; Iterator for 128-bit floating point that uses the IBM double-double format
+(define_mode_iterator IBM128 [IF TF])
+
+; Iterator for 128-bit floating point
+(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128")
+			      (IF "TARGET_FLOAT128")
+			      (TF "TARGET_LONG_DOUBLE_128")])
+
 ; SF/DF suffix for traditional floating instructions
 (define_mode_attr Ftrad		[(SF "s") (DF "")])
 
@@ -596,7 +628,7 @@ (define_mode_attr BOOL_REGS_UNARY	[(TI	"
 ;; Reload iterator for creating the function to allocate a base register to
 ;; supplement addressing modes.
 (define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI
-			      SF SD SI DF DD DI TI PTI])
+			      SF SD SI DF DD DI TI PTI KF IF TF])
 
 \f
 ;; Start with fixed-point load and store insns.  Here we put only the more
@@ -4216,19 +4248,18 @@ (define_insn "*truncdfsf2_fpr"
 ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
 ;; builtins.c and optabs.c that are not correct for IBM long double
 ;; when little-endian.
-(define_expand "signbittf2"
+(define_expand "signbit<mode>2"
   [(set (match_dup 2)
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
+	(float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "")))
    (set (match_dup 3)
    	(subreg:DI (match_dup 2) 0))
    (set (match_dup 4)
    	(match_dup 5))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
   	(match_dup 6))]
-  "!TARGET_IEEEQUAD
+  "FLOAT128_IBM_P (<MODE>mode)
    && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
+   && (TARGET_FPRS || TARGET_E500_DOUBLE)"
 {
   operands[2] = gen_reg_rtx (DFmode);
   operands[3] = gen_reg_rtx (DImode);
@@ -6402,9 +6433,10 @@ (define_expand "mov<mode>"
 ;; problematical.  Don't allow direct move for this case.
 
 (define_insn_and_split "*mov<mode>_64bit_dm"
-  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
-	(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64
+   && FLOAT128_2REG_P (<MODE>mode)
    && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN)
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
@@ -6427,9 +6459,12 @@ (define_insn_and_split "*movtd_64bit_nod
   [(set_attr "length" "8,8,8,8,12,12,8")])
 
 (define_insn_and_split "*mov<mode>_32bit"
-  [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
-	(match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r"))]
+  [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r")
+	(match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64
+   && (FLOAT128_2REG_P (<MODE>mode)
+       || int_reg_operand_not_pseudo (operands[0], <MODE>mode)
+       || int_reg_operand_not_pseudo (operands[1], <MODE>mode))
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
   "#"
@@ -6663,20 +6698,37 @@ (define_insn_and_split "*fix_trunctfsi2_
   DONE;
 })
 
-(define_expand "negtf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
-  "")
+(define_expand "neg<mode>2"
+  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  "FLOAT128_IEEE_P (<MODE>mode)
+   || (FLOAT128_IBM_P (<MODE>mode)
+       && TARGET_HARD_FLOAT
+       && (TARGET_FPRS || TARGET_E500_DOUBLE))"
+  "
+{
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      if (TARGET_FLOAT128)
+	emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1]));
+      else
+	{
+	  rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
+	  rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST,
+						<MODE>mode, 1,
+						operands[1], <MODE>mode);
+
+	  if (target && !rtx_equal_p (target, operands[0]))
+	    emit_move_insn (operands[0], target);
+	}
+      DONE;
+    }
+}")
 
 (define_insn "negtf2_internal"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=d")
 	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
   "*
 {
   if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
@@ -6687,16 +6739,29 @@ (define_insn "negtf2_internal"
   [(set_attr "type" "fp")
    (set_attr "length" "8")])
 
-(define_expand "abstf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
-   && (TARGET_FPRS || TARGET_E500_DOUBLE)
-   && TARGET_LONG_DOUBLE_128"
+(define_expand "abs<mode>2"
+  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  "FLOAT128_IEEE_P (<MODE>mode)
+   || (FLOAT128_IBM_P (<MODE>mode)
+       && TARGET_HARD_FLOAT
+       && (TARGET_FPRS || TARGET_E500_DOUBLE))"
   "
 {
-  rtx label = gen_label_rtx ();
+  rtx label;
+
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    {
+      if (TARGET_FLOAT128)
+	{
+	  emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1]));
+	  DONE;
+	}
+      else
+	FAIL;
+    }
+
+  label = gen_label_rtx ();
   if (TARGET_E500_DOUBLE)
     {
       if (flag_finite_math_only && !flag_trapping_math)
@@ -6732,6 +6797,126 @@ (define_expand "abstf2_internal"
   operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
   operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
 }")
+
+\f
+;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector
+;; register
+
+(define_expand "ieee_128bit_negative_zero"
+  [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
+  "TARGET_FLOAT128"
+{
+  rtvec v = rtvec_alloc (16);
+  int i, high;
+
+  for (i = 0; i < 16; i++)
+    RTVEC_ELT (v, i) = const0_rtx;
+
+  high = (BYTES_BIG_ENDIAN) ? 0 : 15;
+  RTVEC_ELT (v, high) = GEN_INT (0x80);
+
+  rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v));
+  DONE;
+})
+
+;; IEEE 128-bit negate
+
+;; We have 2 insns here for negate and absolute value.  The first uses
+;; match_scratch so that phases like combine can recognize neg/abs as generic
+;; insns, and second insn after the first split pass loads up the bit to
+;; twiddle the sign bit.  Later GCSE passes can then combine multiple uses of
+;; neg/abs to create the constant just once.
+
+(define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (neg:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlxor %x0,%x1,%x2"
+  [(set_attr "type" "vecsimple")])
+
+;; IEEE 128-bit absolute value
+(define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (abs:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlandc %x0,%x1,%x2"
+  [(set_attr "type" "vecsimple")])
+
+;; IEEE 128-bit negative absolute value
+(define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF
+	 (abs:TFIFKF
+	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+   (clobber (match_scratch:V16QI 2 "=v"))]
+  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "#"
+  "&& 1"
+  [(parallel [(set (match_dup 0)
+		   (abs:TFIFKF (match_dup 1)))
+	      (use (match_dup 2))])]
+{
+  if (GET_CODE (operands[2]) == SCRATCH)
+    operands[2] = gen_reg_rtx (V16QImode);
+
+  operands[3] = gen_reg_rtx (V16QImode);
+  emit_insn (gen_ieee_128bit_negative_zero (operands[2]));
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecsimple")])
+
+(define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
+  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
+	(neg:TFIFKF
+	 (abs:TFIFKF
+	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+   (use (match_operand:V16QI 2 "register_operand" "=v"))]
+  "TARGET_FLOAT128"
+  "xxlor %x0,%x1,%x2"
+  [(set_attr "type" "vecsimple")])
+
 \f
 ;; Reload helper functions used by rs6000_secondary_reload.  The patterns all
 ;; must have 3 arguments, and scratch register constraint must be a single
@@ -12134,7 +12319,10 @@ (define_insn "div<div_extend>_<mode>"
 ;; Pack/unpack 128-bit floating point types that take 2 scalar registers
 
 ; Type of the 64-bit part when packing/unpacking 128-bit floating point types
-(define_mode_attr FP128_64 [(TF "DF") (TD "DI")])
+(define_mode_attr FP128_64 [(TF "DF")
+			    (IF "DF")
+			    (TD "DI")
+			    (KF "DI")])
 
 (define_expand "unpack<mode>"
   [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
@@ -12142,7 +12330,7 @@ (define_expand "unpack<mode>"
 	 [(match_operand:FMOVE128 1 "register_operand" "")
 	  (match_operand:QI 2 "const_0_to_1_operand" "")]
 	 UNSPEC_UNPACK_128BIT))]
-  ""
+  "FLOAT128_2REG_P (<MODE>mode)"
   "")
 
 (define_insn_and_split "unpack<mode>_dm"
@@ -12151,7 +12339,7 @@ (define_insn_and_split "unpack<mode>_dm"
 	 [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
+  "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 3))]
@@ -12175,7 +12363,7 @@ (define_insn_and_split "unpack<mode>_nod
 	 [(match_operand:FMOVE128 1 "register_operand" "d,d")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE"
+  "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 3))]
@@ -12199,7 +12387,7 @@ (define_insn_and_split "pack<mode>"
 	 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
 	  (match_operand:<FP128_64> 2 "register_operand" "d,d")]
 	 UNSPEC_PACK_128BIT))]
-  ""
+  "FLOAT128_2REG_P (<MODE>mode)"
   "@
    fmr %L0,%2
    #"
@@ -12219,12 +12407,12 @@ (define_insn_and_split "pack<mode>"
   [(set_attr "type" "fp,fp")
    (set_attr "length" "4,8")])
 
-(define_insn "unpackv1ti"
+(define_insn "unpack<mode>"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
-	(unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa")
+	(unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa")
 		    (match_operand:QI 2 "const_0_to_1_operand" "O,i")]
 	 UNSPEC_UNPACK_128BIT))]
-  "TARGET_VSX"
+  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
 {
   if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0)
     return ASM_COMMENT_START " xxpermdi to same register";
@@ -12232,19 +12420,17 @@ (define_insn "unpackv1ti"
   operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3);
   return "xxpermdi %x0,%x1,%x1,%3";
 }
-  [(set_attr "type" "vecperm")
-   (set_attr "length" "4")])
+  [(set_attr "type" "vecperm")])
 
-(define_insn "packv1ti"
-  [(set (match_operand:V1TI 0 "register_operand" "=wa")
-	(unspec:V1TI
+(define_insn "pack<mode>"
+  [(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa")
+	(unspec:FMOVE128_VSX
 	 [(match_operand:DI 1 "register_operand" "d")
 	  (match_operand:DI 2 "register_operand" "d")]
 	 UNSPEC_PACK_128BIT))]
   "TARGET_VSX"
   "xxpermdi %x0,%x1,%x2,0"
-  [(set_attr "type" "vecperm")
-   (set_attr "length" "4")])
+  [(set_attr "type" "vecperm")])
 
 \f
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #5
  2015-08-25 23:33     ` Michael Meissner
@ 2015-08-26 13:16       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-08-26 13:16 UTC (permalink / raw)
  To: Michael Meissner, Segher Boessenkool, GCC Patches

On Tue, Aug 25, 2015 at 7:20 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:

> Here is the revised patch. Is it ok to install?
>
> 2015-08-25  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/predicates.md (int_reg_operand_not_pseudo): New
>         predicate for only GPR hard registers.
>
>         * config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point
>         modes to iterators. Add new iterators for moving 128-bit values in
>         scalar FPR registers and VSX registers.
>         (FMOVE128): Likewise.
>         (FMOVE128_FPR): Likewise.
>         (FMOVE128_GPR): Likewise.
>         (FMOVE128_VSX): Likewise.
>         (FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point
>         in VSX registers.
>         (IFKF): Likewise.
>         (IBM128): Likewise.
>         (TFIFKF): Likewise.
>         (RELOAD): Add IEEE 128-bit floating point modes.
>         (signbittf2): Convert TF insns to add support for new IEEE 128-bit
>         floating point in VSX registers modes.
>         (signbit<mode>2, IBM128 iterator): Likewise.
>         (mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise.
>         (mov<mode>_32bit, FMOVE128_FPR iterator): Likewise.
>         (negtf2): Likewise.
>         (neg<mode>2, TFIFKF iterator): Likewise.
>         (negtf2_internal): Likewise.
>         (abstf2): Likewise.
>         (abs<mode>2, TFIFKF iterator): Likewise.
>         (ieee_128bit_negative_zero): New IEEE 128-bit floating point in
>         VSX insn support for negate, absolute value, and negative absolute
>         value.
>         (ieee_128bit_vsx_neg<mode>2): Likewise.
>         (ieee_128bit_vsx_neg<mode>2_internal): Likewise.
>         (ieee_128bit_vsx_abs<mode>2): Likewise.
>         (ieee_128bit_vsx_abs<mode>2_internal): Likewise.
>         (ieee_128bit_vsx_nabs<mode>2): Likewise.
>         (ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
>         (FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit
>         floating point in VSX registers.
>         (unpack<mode>_dm): Likewise.
>         (unpack<mode>_nodm): Likewise.
>         (pack<mode>): Likewise.
>         (unpackv1ti): Likewise.
>         (unpack<mode>, FMOVE128_VSX iterator): Likewise.
>         (packv1ti): Likewise.
>         (pack<mode>, FMOVE128_VSX iterator): Likewise.

The revised patch is okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #6
  2015-08-14 15:49 ` [PATCH], PowerPC IEEE 128-bit patch #6 Michael Meissner
@ 2015-08-26 13:57   ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-08-26 13:57 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Aug 14, 2015 at 11:47 AM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:

> This is patch #6:
>
> 2015-08-13  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert):
>         Add declaration.
>
>         * config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a
>         comment.
>         (rs6000_cannot_change_mode_class): Add support for IEEE 128-bit
>         floating point in VSX registers.
>         (rs6000_output_move_128bit): Always print out the set insn if we
>         can't generate an appropriate 128-bit move.
>         (rs6000_generate_compare): Add support for IEEE 128-bit floating
>         point in VSX registers comparisons.
>         (rs6000_expand_float128_convert): Likewise.
>
>         * config/rs6000/rs6000.md (extenddftf2): Add support for IEEE
>         128-bit floating point in VSX registers.
>         (extenddftf2_internal): Likewise.
>         (trunctfdf2): Likewise.
>         (trunctfdf2_internal2): Likewise.
>         (fix_trunc_helper): Likewise.
>         (fix_trunctfdi2"): Likewise.
>         (floatditf2): Likewise.
>         (floatuns<mode>tf2): Likewise.
>         (extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
>         (trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
>         (fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
>         (fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
>         (float<SDI:mode><IFKF:mode>2): Likewise.
>         (floatuns<SDI:mode><IFKF:mode>2): Likewise.

This patch is okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [PATCH], PowerPC IEEE 128-bit patch #7 (revised)
  2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
                   ` (5 preceding siblings ...)
  2015-08-14 15:56 ` [PATCH], PowerPC IEEE 128-bit patch #7 Michael Meissner
@ 2015-09-16 22:50 ` Michael Meissner
  2015-09-22  0:19   ` Michael Meissner
  2015-10-08 19:04   ` [Patch] PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
  6 siblings, 2 replies; 78+ messages in thread
From: Michael Meissner @ 2015-09-16 22:50 UTC (permalink / raw)
  To: gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 4955 bytes --]

This is a revised patch that adds the parts to enable generation of IEEE
128-bit floating point support in the PowerPC backend.

The major user visible change of this patch is to change the switch from
-mfloat128-software and -mfloat128-none to just -mfloat128 and -mno-float128.
I also revised some of the support functions in rs6000.c to work better with
future patches.

In working on the future patches, I also noticed that I had allowed the
conversion routines to support target being a memory address (via the
nonimmediate_operand predicate), and I restricted it to register.

The next patch will be to libgcc to enable building the emulation routines, so
that you can use IEEE 128-bit floating point. It is expected that initially
these patches will be a temporary measure until the glibc team takes ownership
of the emulation functions (the soft-fp directory of libgcc comes from glibc).

Once the libgcc routines are in place, I will then submit a patch to flip the
default, so that enabling VSX options will enable -mfloat128 by default.

I expect there to be various additional patches as things come up as well.  Of
the top of my head, I will probably be adding built-in functions for sqrt and
abs.  I also want to tackle making _Complex __float128 work without having to
use attributes.

The patch has been bootstrapped on a Power7 big endian system and a Power8
little endian system with no regressions. I also built compilers with/without
the changes targetting power5 as a default and there were no regressions there
either.  Are these patches ok to install on the trunk?

[gcc]
2015-09-14  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-cpus.h (POWERPC_MASKS): Add -mfloat128.

	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define new
	macros to identify if __float128 is available, and whether long
	double is IBM extended double or IEEE 128-bit floating point.

	* config/rs6000/rs6000.opt (-mfloat128): Change IEEE 128-bit
	switches from -mfloat128-none and -mfloat128-software to
	-mfloat128 and -mno-float128.
	(-mfloat128-): Delete.
	(float128_type_t): Delete.

	* config/rs6000/rs6000.c (rs6000_c_mode_for_suffix): Define 'q'
	and 'Q' as the suffixes for __float128 constants.
	(TARGET_C_MODE_FOR_SUFFIX): Likewise.
	(rs6000_hard_regno_mode_ok): Remove tests disallowing IEEE 128-bit
	floating point modes from GPRs if not -mfloat128.
	(rs6000_debug_reg_global): Delete debug support for
	-mfloat128-software and -mfloat128-none.
	(rs6000_setup_reg_addr_masks): IEEE 128-bit in floating point is
	not suitable for auto increment or decrement.
	(rs6000_init_hard_regno_mode_ok): Enable VSX constraints and
	addressing for IEEE 128-bit floating point in VSX registers.
	(rs6000_option_override_internal): Update test for __float128
	support.
	(rs6000_gen_le_vsx_permute): Add support for -mfloat128.
	(init_cumulative_args): Likewise.
	(rs6000_function_arg): Likewise.
	(rs6000_arg_partial_bytes): Likewise.
	(rs6000_init_builtins): Rework __float128 support.
	(init_float128_ibm): Add __float128 support. Split support into
	separate functions for IEEE 128-bit floating point and IBM
	extended double support.
	(init_float128_ieee): Likewise.
	(rs6000_init_libfuncs): Likewise.
	(rs6000_expand_float128_convert): Use switch statements to handle
	different types.
	(rs6000_mangle_type): Add __float128 mangling support.
	(rs6000_scalar_mode_supported_p): Rework __float128 support.
	(rs6000_opt_masks): Add -mfloat128 support.
	(chain_contains_only_swaps): Use ALTIVEC_OR_VSX_VECTOR_MODE
	instead of VECTOR_MODE_P in order to treat IEEE1 28-bit floating
	point in VSX registers like vector types, and treat it like a
	128-bit integer.
	(mark_swaps_for_removal): Likewise.
	(rs6000_analyze_swaps): Likewise.

	* config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Include __float128
	modes as 'vector' modes.
	(MODES_TIEABLE_P): Move checking for vector modes above scalar
	floating point, so that __float128 types tie with vector types.
	(struct rs6000_args): Add libcall field for __float128 support
	functions.

	* config/rs6000/rs6000.md (extend<FLOAT128_SFDFTF:mode><IFKF:mode>2):
	Require target to be a register, not a memory operand.
	(trunk<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.

	* config/rs6000/rs6000-opts.h (enum float128_type_t): Delete,
	switch to -mfloat128 and -mno-float128 from -mfloat128-software
	and -mfloat128-none.

	* doc/extend.texi (additional floating types): Document PowerPC
	use of __float128 and __ibm128 types.

	* doc/invoke.texi (RS/6000 and PowerPC Options): Document
	-mfloat128 and -mno-float128.

[gcc/testsuite]
2015-09-14  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/float128-call.c: New function, test whether
	IEEE 128-bit floating point in VSX registers is passed correctly.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07b --]
[-- Type: text/plain, Size: 39504 bytes --]

Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 227594)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -80,6 +80,7 @@
 				 | OPTION_MASK_DIRECT_MOVE		\
 				 | OPTION_MASK_DLMZB			\
 				 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX	\
+				 | OPTION_MASK_FLOAT128			\
 				 | OPTION_MASK_FPRND			\
 				 | OPTION_MASK_HTM			\
 				 | OPTION_MASK_ISEL			\
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 227594)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -410,6 +410,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
+  if (TARGET_FLOAT128)
+    builtin_define ("__FLOAT128__");
 
   if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM)
     {
@@ -483,6 +485,11 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     {
       builtin_define ("__LONG_DOUBLE_128__");
       builtin_define ("__LONGDOUBLE128");
+
+      if (TARGET_IEEEQUAD)
+	builtin_define ("__LONG_DOUBLE_IEEE128__");
+      else
+	builtin_define ("__LONG_DOUBLE_IBM128__");
     }
 
   switch (TARGET_CMODEL)
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 227594)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -601,18 +601,6 @@ moptimize-swaps
 Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
 Analyze and remove doubleword swaps from VSX computations.
 
-mfloat128-
-Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save
--mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used.
-
-Enum
-Name(float128_type_t) Type(enum float128_type_t)
-
-EnumValue
-Enum(float128_type_t) String(none) Value(FLOAT128_NONE)
-
-EnumValue
-Enum(float128_type_t) String(software) Value(FLOAT128_SW)
-
-EnumValue
-Enum(float128_type_t) String(sw) Value(FLOAT128_SW)
+mfloat128
+Target Report Mask(FLOAT128) Var(rs6000_isa_flags)
+Enable/disable IEEE 128-bit floating point via the __float128 keyword.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 227594)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1688,6 +1688,9 @@ static const struct attribute_spec rs600
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_C_MODE_FOR_SUFFIX
+#define TARGET_C_MODE_FOR_SUFFIX rs6000_c_mode_for_suffix
 \f
 
 /* Processor table.  */
@@ -1786,16 +1789,6 @@ rs6000_hard_regno_mode_ok (int regno, ma
 	    && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO)
 	    && ((regno & 1) == 0));
 
-  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
-     types from going in any registers.  Similarly if __float128 is not
-     supported, don't allow __float128/__ibm128 types.  */
-  if (!TARGET_LONG_DOUBLE_128
-      && (mode == TFmode || mode == KFmode || mode == IFmode))
-    return false;
-
-  if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
-    return false;
-
   /* VSX registers that overlap the FPR registers are larger than for non-VSX
      implementations.  Don't allow an item to be split between a FP register
      and an Altivec register.  Allow TImode in all VSX registers if the user
@@ -2069,7 +2062,6 @@ rs6000_debug_reg_global (void)
   const char *trace_str;
   const char *abi_str;
   const char *cmodel_str;
-  const char *float128_str;
   struct cl_target_option cl_opts;
 
   /* Modes we want tieable information on.  */
@@ -2435,15 +2427,6 @@ rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_S, "e500_double",
 	   (TARGET_E500_DOUBLE ? "true" : "false"));
 
-  switch (TARGET_FLOAT128)
-    {
-    case FLOAT128_NONE:	float128_str = "none";		break;
-    case FLOAT128_SW:	float128_str = "software";	break;
-    default:		float128_str = "unknown";	break;
-    }
-
-  fprintf (stderr, DEBUG_FMT_S, "float128", float128_str);
-
   if (TARGET_LINK_STACK)
     fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
 
@@ -2526,6 +2509,7 @@ rs6000_setup_reg_addr_masks (void)
 		  && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
 		  && GET_MODE_SIZE (m2) <= 8
 		  && !VECTOR_MODE_P (m2)
+		  && !FLOAT128_VECTOR_P (m2)
 		  && !COMPLEX_MODE_P (m2)
 		  && !indexed_only_p
 		  && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m2) == 8))
@@ -2671,6 +2655,20 @@ rs6000_init_hard_regno_mode_ok (bool glo
       align32 = 128;
     }
 
+  /* KF mode (ieee 128-bit) where we can pass it as a vector.  We do not have
+     arithmetic, so only set the memory modes.  */
+  if (TARGET_FLOAT128)
+    {
+      rs6000_vector_mem[KFmode] = VECTOR_VSX;
+      rs6000_vector_align[KFmode] = 128;
+
+      if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
+	{
+	  rs6000_vector_mem[TFmode] = VECTOR_VSX;
+	  rs6000_vector_align[TFmode] = 128;
+	}
+    }
+
   /* V2DF mode, VSX only.  */
   if (TARGET_VSX)
     {
@@ -2864,7 +2862,7 @@ rs6000_init_hard_regno_mode_ok (bool glo
   if (TARGET_FLOAT128)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;	/* KFmode  */
-      if (rs6000_ieeequad)
+      if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
 	rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS;	/* TFmode  */
     }
 
@@ -2887,6 +2885,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_di_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_di_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_di_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_di_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_di_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_di_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_di_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_di_store;
@@ -2894,6 +2894,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_di_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_di_load;
 
+	  if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 && TARGET_FLOAT128)
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_di_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_di_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -2947,6 +2953,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_si_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_si_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_si_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_si_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_si_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_si_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_si_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_si_store;
@@ -2954,6 +2962,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_si_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_si_load;
 
+	  if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 && TARGET_FLOAT128)
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_si_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_si_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -3709,13 +3723,6 @@ rs6000_option_override_internal (bool gl
       && optimize >= 3)
     rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN;
 
-  /* Set the appropriate IEEE 128-bit floating option.  Do not enable float128
-     support by default until the libgcc support is added.  */
-  if (TARGET_FLOAT128 == FLOAT128_UNSET)
-    TARGET_FLOAT128 = FLOAT128_NONE;
-  else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX)
-    error ("-mfloat128-software requires VSX support");
-
   /* Set -mallow-movmisalign to explicitly on if we have full ISA 2.07
      support. If we only have ISA 2.06 support, and the user did not specify
      the switch, leave it set to -1 so the movmisalign patterns are enabled,
@@ -3755,6 +3762,15 @@ rs6000_option_override_internal (bool gl
 	}
     }
 
+  /* __float128 requires VSX support.  */
+  if (TARGET_FLOAT128 && !TARGET_VSX)
+    {
+      if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) != 0)
+	error ("-mfloat128 requires VSX support");
+
+      rs6000_isa_flags &= ~OPTION_MASK_FLOAT128;
+    }
+
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
 
@@ -3835,7 +3851,8 @@ rs6000_option_override_internal (bool gl
      unless the altivec ABI was set.  This is set by default for 64-bit, but
      not for 32-bit.  */
   if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
-    rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC)
+    rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC
+			   | OPTION_MASK_FLOAT128)
 			  & ~rs6000_isa_flags_explicit);
 
   /* Enable Altivec ABI for AIX -maltivec.  */
@@ -8444,8 +8461,14 @@ rs6000_const_vec (machine_mode mode)
 rtx
 rs6000_gen_le_vsx_permute (rtx source, machine_mode mode)
 {
-  rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
-  return gen_rtx_VEC_SELECT (mode, source, par);
+  /* Use ROTATE instead of VEC_SELECT on IEEE 128-bit floating point.  */
+  if (FLOAT128_VECTOR_P (mode))
+    return gen_rtx_ROTATE (mode, source, GEN_INT (64));
+  else
+    {
+      rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
+      return gen_rtx_VEC_SELECT (mode, source, par);
+    }
 }
 
 /* Emit a little-endian load from vector memory location SOURCE to VSX
@@ -9424,6 +9447,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      ? CALL_LIBCALL : CALL_NORMAL);
   cum->sysv_gregno = GP_ARG_MIN_REG;
   cum->stdarg = stdarg_p (fntype);
+  cum->libcall = libcall;
 
   cum->nargs_prototype = 0;
   if (incoming || cum->prototype)
@@ -10586,9 +10610,11 @@ rs6000_function_arg (cumulative_args_t c
       rtx r, off;
       int i, k = 0;
 
-      /* Do we also need to pass this argument in the parameter
-	 save area?  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* Do we also need to pass this argument in the parameter save area?
+	 Library support functions for IEEE 128-bit are assumed to not need the
+	 value passed both in GPRs and in vector registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	{
 	  int align_words = (cum->words + 1) & ~1;
 	  k = rs6000_psave_function_arg (mode, type, align_words, rvec);
@@ -10819,11 +10845,14 @@ rs6000_arg_partial_bytes (cumulative_arg
 
   if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
     {
-      /* If we are passing this arg in the fixed parameter save area
-         (gprs or memory) as well as VRs, we do not use the partial
-	 bytes mechanism; instead, rs6000_function_arg will return a
-	 PARALLEL including a memory element as necessary.  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* If we are passing this arg in the fixed parameter save area (gprs or
+         memory) as well as VRs, we do not use the partial bytes mechanism;
+         instead, rs6000_function_arg will return a PARALLEL including a memory
+         element as necessary.  Library support functions for IEEE 128-bit are
+         assumed to not need the value passed both in GPRs and in vector
+         registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	return 0;
 
       /* Otherwise, we pass in VRs only.  Check for partial copies.  */
@@ -14408,8 +14437,6 @@ rs6000_init_builtins (void)
   tree tdecl;
   tree ftype;
   machine_mode mode;
-  machine_mode ieee128_mode;
-  machine_mode ibm128_mode;
 
   if (TARGET_DEBUG_BUILTIN)
     fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n",
@@ -14482,26 +14509,24 @@ rs6000_init_builtins (void)
      TFmode will be either IEEE 128-bit floating point or the IBM double-double
      format that uses a pair of doubles, depending on the switches and
      defaults.  */
-  if (TARGET_IEEEQUAD)
-    {
-      ieee128_mode = TFmode;
-      ibm128_mode = IFmode;
-    }
-  else
+  if (TARGET_FLOAT128)
     {
-      ieee128_mode = KFmode;
-      ibm128_mode = TFmode;
-    }
+      ibm128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ibm128_float_type_node) = 128;
+      layout_type (ibm128_float_type_node);
+      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+
+      ieee128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ieee128_float_type_node) = 128;
+      layout_type (ieee128_float_type_node);
+      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
 
-  ieee128_float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (ieee128_float_type_node) = 128;
-  layout_type (ieee128_float_type_node);
-  SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode);
+      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+					      "__float128");
 
-  ibm128_float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (ibm128_float_type_node) = 128;
-  layout_type (ibm128_float_type_node);
-  SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode);
+      lang_hooks.types.register_builtin_type (ibm128_float_type_node,
+					      "__ibm128");
+    }
 
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
@@ -16007,75 +16032,155 @@ rs6000_common_init_builtins (void)
     }
 }
 
+/* Set up AIX/Darwin/64-bit Linux quad floating point routines.  */
 static void
-rs6000_init_libfuncs (void)
+init_float128_ibm (machine_mode mode)
 {
-  if (!TARGET_IEEEQUAD)
-      /* AIX/Darwin/64-bit Linux quad floating point routines.  */
-    if (!TARGET_XL_COMPAT)
-      {
-	set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
-	set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
-	set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
+  if (!TARGET_XL_COMPAT)
+    {
+      set_optab_libfunc (add_optab, mode, "__gcc_qadd");
+      set_optab_libfunc (sub_optab, mode, "__gcc_qsub");
+      set_optab_libfunc (smul_optab, mode, "__gcc_qmul");
+      set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv");
 
-	if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
-	  {
-	    set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
-	    set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
-	    set_optab_libfunc (ne_optab, TFmode, "__gcc_qne");
-	    set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt");
-	    set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
-	    set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
-	    set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
-
-	    set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
-	    set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
-	    set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos");
-	    set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod");
-	    set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi");
-	    set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou");
-	    set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
-	    set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
-	  }
+      if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
+	{
+	  set_optab_libfunc (neg_optab, mode, "__gcc_qneg");
+	  set_optab_libfunc (eq_optab, mode, "__gcc_qeq");
+	  set_optab_libfunc (ne_optab, mode, "__gcc_qne");
+	  set_optab_libfunc (gt_optab, mode, "__gcc_qgt");
+	  set_optab_libfunc (ge_optab, mode, "__gcc_qge");
+	  set_optab_libfunc (lt_optab, mode, "__gcc_qlt");
+	  set_optab_libfunc (le_optab, mode, "__gcc_qle");
 
-	if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
-	  set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
-      }
-    else
-      {
-	set_optab_libfunc (add_optab, TFmode, "_xlqadd");
-	set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
-	set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
-      }
+	  set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq");
+	  set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq");
+	  set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos");
+	  set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod");
+	  set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi");
+	  set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou");
+	  set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq");
+	  set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq");
+	}
+
+      if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
+	set_optab_libfunc (unord_optab, mode, "__gcc_qunord");
+    }
   else
     {
-      /* 32-bit SVR4 quad floating point routines.  */
+      set_optab_libfunc (add_optab, mode, "_xlqadd");
+      set_optab_libfunc (sub_optab, mode, "_xlqsub");
+      set_optab_libfunc (smul_optab, mode, "_xlqmul");
+      set_optab_libfunc (sdiv_optab, mode, "_xlqdiv");
+    }
+}
+
+/* Set up IEEE 128-bit floating point routines.  Use different names if the
+   arguments can be passed in a vector register.  The historical PowerPC
+   implementation of IEEE 128-bit floating point used _q_<op> for the names, so
+   continue to use that if we can't pass IEEE 128-bit in a VSX vector register.
+
+   Add _vector to clarify that this function is called with the argument in a
+   vector register, and _fpr when we are not passing IEEE 128-bit in a vector
+   register.  */
+
+static void
+init_float128_ieee (machine_mode mode)
+{
+  if (FLOAT128_VECTOR_P (mode))
+    {
+      set_optab_libfunc (add_optab, mode, "__addkf3");
+      set_optab_libfunc (sub_optab, mode, "__subkf3");
+      set_optab_libfunc (neg_optab, mode, "__negkf2");
+      set_optab_libfunc (smul_optab, mode, "__mulkf3");
+      set_optab_libfunc (sdiv_optab, mode, "__divkf3");
+      set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2");
+      set_optab_libfunc (abs_optab, mode, "__abstkf2");
+
+      set_optab_libfunc (eq_optab, mode, "__eqkf2");
+      set_optab_libfunc (ne_optab, mode, "__nekf2");
+      set_optab_libfunc (gt_optab, mode, "__gtkf2");
+      set_optab_libfunc (ge_optab, mode, "__gekf2");
+      set_optab_libfunc (lt_optab, mode, "__ltkf2");
+      set_optab_libfunc (le_optab, mode, "__lekf2");
+      set_optab_libfunc (unord_optab, mode, "__unordkf2");
+      set_optab_libfunc (cmp_optab, mode, "__cmpkf2");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2");
+      set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2");
+
+      set_conv_libfunc (sfix_optab, SImode, mode, "__fixkfsi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "__fixunskfsi");
+      set_conv_libfunc (sfix_optab, DImode, mode, "__fixkfdi");
+      set_conv_libfunc (ufix_optab, DImode, mode, "__fixunskfdi");
+
+      set_conv_libfunc (sfloat_optab, mode, SImode, "__floatsikf");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "__floatunsikf");
+      set_conv_libfunc (sfloat_optab, mode, DImode, "__floatdikf");
+      set_conv_libfunc (ufloat_optab, mode, DImode, "__floatundikf");
+
+      if (mode == KFmode)
+	{
+	  set_conv_libfunc (sext_optab, IFmode, KFmode, "__extendkftf2");
+	  set_conv_libfunc (trunc_optab, KFmode, IFmode, "__trunctfkf2");
+
+	  if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
+	    {
+	      set_conv_libfunc (sext_optab, TFmode, KFmode, "__extendkftf2");
+	      set_conv_libfunc (trunc_optab, mode, KFmode, "__trunctfkf2");
+	    }
+	}
+    }
 
-      set_optab_libfunc (add_optab, TFmode, "_q_add");
-      set_optab_libfunc (sub_optab, TFmode, "_q_sub");
-      set_optab_libfunc (neg_optab, TFmode, "_q_neg");
-      set_optab_libfunc (smul_optab, TFmode, "_q_mul");
-      set_optab_libfunc (sdiv_optab, TFmode, "_q_div");
+  else
+    {
+      set_optab_libfunc (add_optab, mode, "_q_add");
+      set_optab_libfunc (sub_optab, mode, "_q_sub");
+      set_optab_libfunc (neg_optab, mode, "_q_neg");
+      set_optab_libfunc (smul_optab, mode, "_q_mul");
+      set_optab_libfunc (sdiv_optab, mode, "_q_div");
       if (TARGET_PPC_GPOPT)
-	set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
+	set_optab_libfunc (sqrt_optab, mode, "_q_sqrt");
+
+      set_optab_libfunc (eq_optab, mode, "_q_feq");
+      set_optab_libfunc (ne_optab, mode, "_q_fne");
+      set_optab_libfunc (gt_optab, mode, "_q_fgt");
+      set_optab_libfunc (ge_optab, mode, "_q_fge");
+      set_optab_libfunc (lt_optab, mode, "_q_flt");
+      set_optab_libfunc (le_optab, mode, "_q_fle");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "_q_stoq");
+      set_conv_libfunc (sext_optab, mode, DFmode, "_q_dtoq");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "_q_qtos");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "_q_qtod");
+      set_conv_libfunc (sfix_optab, SImode, mode, "_q_qtoi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "_q_qtou");
+      set_conv_libfunc (sfloat_optab, mode, SImode, "_q_itoq");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "_q_utoq");
+    }
+}
+
+static void
+rs6000_init_libfuncs (void)
+{
+  /* __float128 support.  */
+  if (TARGET_FLOAT128)
+    {
+      init_float128_ibm (IFmode);
+      init_float128_ieee (KFmode);
+    }
 
-      set_optab_libfunc (eq_optab, TFmode, "_q_feq");
-      set_optab_libfunc (ne_optab, TFmode, "_q_fne");
-      set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
-      set_optab_libfunc (ge_optab, TFmode, "_q_fge");
-      set_optab_libfunc (lt_optab, TFmode, "_q_flt");
-      set_optab_libfunc (le_optab, TFmode, "_q_fle");
-
-      set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
-      set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
-      set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
-      set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
-      set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
-      set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
-      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
-      set_conv_libfunc (ufloat_optab, TFmode, SImode, "_q_utoq");
+  /* AIX/Darwin/64-bit Linux quad floating point routines.  */
+  if (TARGET_LONG_DOUBLE_128)
+    {
+      if (!TARGET_IEEEQUAD)
+	init_float128_ibm (TFmode);
+
+      /* IEEE 128-bit including 32-bit SVR4 quad floating point routines.  */
+      else
+	init_float128_ieee (TFmode);
     }
 }
 
@@ -20141,7 +20246,7 @@ rs6000_generate_compare (rtx cmp, machin
   return gen_rtx_fmt_ee (code, VOIDmode, compare_result, const0_rtx);
 }
 
-
+\f
 /* Expand floating point conversion to/from __float128 and __ibm128.  */
 
 void
@@ -20150,60 +20255,105 @@ rs6000_expand_float128_convert (rtx dest
   machine_mode dest_mode = GET_MODE (dest);
   machine_mode src_mode = GET_MODE (src);
   convert_optab cvt = unknown_optab;
+  bool do_move = false;
   rtx libfunc = NULL_RTX;
   rtx dest2;
 
   if (dest_mode == src_mode)
     gcc_unreachable ();
 
+  /* Convert to IEEE 128-bit floating point.  */
   if (FLOAT128_IEEE_P (dest_mode))
     {
-      if (src_mode == SFmode
-	  || src_mode == DFmode
-	  || FLOAT128_IBM_P (src_mode))
-	cvt = sext_optab;
+      switch (src_mode)
+	{
+	case DFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (src_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	case SFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (FLOAT128_IEEE_P (src_mode))
-	emit_move_insn (dest, gen_lowpart (dest_mode, src));
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (src_mode))
+	    cvt = sext_optab;
+	  else
+	    do_move = true;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Convert from IEEE 128-bit floating point.  */
   else if (FLOAT128_IEEE_P (src_mode))
     {
-      if (dest_mode == SFmode
-	  || dest_mode == DFmode
-	  || FLOAT128_IBM_P (dest_mode))
-	cvt = trunc_optab;
+      switch (dest_mode)
+	{
+	case DFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (dest_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	case SFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (dest_mode))
+	    cvt = trunc_optab;
+	  else
+	    do_move = true;
+	  break;
+
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
   else
     gcc_unreachable ();
 
-  gcc_assert (cvt != unknown_optab);
-  libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
-  gcc_assert (libfunc != NULL_RTX);
-
-  dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
-				   src_mode);
-
-  gcc_assert (dest != NULL_RTX);
-  if (!rtx_equal_p (dest, dest2))
-    emit_move_insn (dest, dest2);
+  /* Handle conversion between TFmode/KFmode.  */
+  if (do_move)
+    emit_move_insn (dest, gen_lowpart (dest_mode, src));
+
+  /* Call an external function to do the conversion.  */
+  else if (cvt != unknown_optab)
+    {
+      libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
+      gcc_assert (libfunc != NULL_RTX);
+
+      dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
+				       src_mode);
+
+      gcc_assert (dest2 != NULL_RTX);
+      if (!rtx_equal_p (dest, dest2))
+	emit_move_insn (dest, dest2);
+    }
+
+  else
+    gcc_unreachable ();
 
   return;
 }
 
+\f
 /* Emit the RTL for an sISEL pattern.  */
 
 void
@@ -29800,6 +29950,21 @@ rs6000_mangle_type (const_tree type)
   if (type == bool_int_type_node) return "U6__booli";
   if (type == bool_long_type_node) return "U6__booll";
 
+  /* Use a unique name for __float128 rather than trying to use "e" or "g". Use
+     "g" for IBM extended double, no matter whether it is long double (using
+     -mabi=ibmlongdouble) or the distinct __ibm128 type.  */
+  if (TARGET_FLOAT128)
+    {
+      if (type == ieee128_float_type_node)
+	return "U10__float128";
+
+      if (type == ibm128_float_type_node)
+	return "g";
+
+      if (type == long_double_type_node && TARGET_LONG_DOUBLE_128)
+	return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
+    }
+
   /* Mangle IBM extended float long double as `g' (__float128) on
      powerpc*-linux where long-double-64 previously was the default.  */
   if (TYPE_MAIN_VARIANT (type) == long_double_type_node
@@ -33023,8 +33188,8 @@ rs6000_scalar_mode_supported_p (machine_
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
-  else if (mode == KFmode)
-    return TARGET_FLOAT128;
+  else if (TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+    return true;
   else
     return default_scalar_mode_supported_p (mode);
 }
@@ -33050,6 +33215,26 @@ rs6000_vector_mode_supported_p (machine_
     return false;
 }
 
+/* Target hook for c_mode_for_suffix.  */
+static machine_mode
+rs6000_c_mode_for_suffix (char suffix)
+{
+  if (TARGET_FLOAT128)
+    {
+      if (suffix == 'q' || suffix == 'Q')
+	return (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) ? TFmode : KFmode;
+
+      /* At the moment, we are not defining a suffix for IBM extended double.
+	 If/when the default for -mabi=ieeelongdouble is changed, and we want
+	 to support __ibm128 constants in legacy library code, we may need to
+	 re-evalaute this decision.  Currently, c-lex.c only supports 'w' and
+	 'q' as machine dependent suffixes.  The x86_64 port uses 'w' for
+	 __float80 constants.  */
+    }
+
+  return VOIDmode;
+}
+
 /* Target hook for invalid_arg_for_unprototyped_fn. */
 static const char *
 invalid_arg_for_unprototyped_fn (const_tree typelist, const_tree funcdecl, const_tree val)
@@ -33135,6 +33320,7 @@ static struct rs6000_opt_mask const rs60
   { "dlmzb",			OPTION_MASK_DLMZB,		false, true  },
   { "efficient-unaligned-vsx",	OPTION_MASK_EFFICIENT_UNALIGNED_VSX,
 								false, true  },
+  { "float128",			OPTION_MASK_FLOAT128,		false, true  },
   { "fprnd",			OPTION_MASK_FPRND,		false, true  },
   { "hard-dfp",			OPTION_MASK_DFP,		false, true  },
   { "htm",			OPTION_MASK_HTM,		false, true  },
@@ -33213,7 +33399,7 @@ static struct rs6000_opt_mask const rs60
 struct rs6000_opt_var {
   const char *name;		/* option name */
   size_t global_offset;		/* offset of the option in global_options.  */
-  size_t target_offset;		/* offset of the option in target optiosn.  */
+  size_t target_offset;		/* offset of the option in target options.  */
 };
 
 static struct rs6000_opt_var const rs6000_opt_vars[] =
@@ -35431,7 +35617,7 @@ chain_contains_only_swaps (swap_web_entr
 
   for (; link; link = link->next)
     {
-      if (!VECTOR_MODE_P (GET_MODE (DF_REF_REG (link->ref))))
+      if (!ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (DF_REF_REG (link->ref))))
 	continue;
 
       if (DF_REF_IS_ARTIFICIAL (link->ref))
@@ -35530,7 +35716,7 @@ mark_swaps_for_removal (swap_web_entry *
 	{
 	  /* Ignore uses for addressability.  */
 	  machine_mode mode = GET_MODE (DF_REF_REG (use));
-	  if (!VECTOR_MODE_P (mode))
+	  if (!ALTIVEC_OR_VSX_VECTOR_MODE (mode))
 	    continue;
 
 	  struct df_link *link = DF_REF_CHAIN (use);
@@ -35939,10 +36125,11 @@ rs6000_analyze_swaps (function *fun)
 		    mode = V4SImode;
 		}
 
-	      if (VECTOR_MODE_P (mode) || mode == TImode)
+	      if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
 		{
 		  insn_entry[uid].is_relevant = 1;
-		  if (mode == TImode || mode == V1TImode)
+		  if (mode == TImode || mode == V1TImode
+		      || FLOAT128_VECTOR_P (mode))
 		    insn_entry[uid].is_128_int = 1;
 		  if (DF_REF_INSN_INFO (mention))
 		    insn_entry[uid].contains_subreg
@@ -35963,13 +36150,14 @@ rs6000_analyze_swaps (function *fun)
 		 isn't sufficient to ensure we union the call into the
 		 web with the parameter setup code.  */
 	      if (mode == DImode && GET_CODE (insn) == SET
-		  && VECTOR_MODE_P (GET_MODE (SET_DEST (insn))))
+		  && ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (SET_DEST (insn))))
 		mode = GET_MODE (SET_DEST (insn));
 
-	      if (VECTOR_MODE_P (mode) || mode == TImode)
+	      if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
 		{
 		  insn_entry[uid].is_relevant = 1;
-		  if (mode == TImode || mode == V1TImode)
+		  if (mode == TImode || mode == V1TImode
+		      || FLOAT128_VECTOR_P (mode))
 		    insn_entry[uid].is_128_int = 1;
 		  if (DF_REF_INSN_INFO (mention))
 		    insn_entry[uid].contains_subreg
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 227594)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1217,11 +1217,16 @@ enum data_align { align_abi, align_opt, 
 	 ((MODE) == V4SFmode		\
 	  || (MODE) == V2DFmode)	\
 
-#define ALTIVEC_VECTOR_MODE(MODE)	\
-	 ((MODE) == V16QImode		\
-	  || (MODE) == V8HImode		\
-	  || (MODE) == V4SFmode		\
-	  || (MODE) == V4SImode)
+/* Note KFmode and possibly TFmode (i.e. IEEE 128-bit floating point) are not
+   really a vector, but we want to treat it as a vector for moves, and
+   such.  */
+
+#define ALTIVEC_VECTOR_MODE(MODE)					\
+  ((MODE) == V16QImode							\
+   || (MODE) == V8HImode						\
+   || (MODE) == V4SFmode						\
+   || (MODE) == V4SImode						\
+   || FLOAT128_VECTOR_P (MODE))
 
 #define ALTIVEC_OR_VSX_VECTOR_MODE(MODE)				\
   (ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)			\
@@ -1248,12 +1253,19 @@ enum data_align { align_abi, align_opt, 
 
    PTImode cannot tie with other modes because PTImode is restricted to even
    GPR registers, and TImode can go in any GPR as well as VSX registers (PR
-   57744).  */
+   57744).
+
+   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
+   128-bit floating point on VSX systems ties with other vectors.  */
 #define MODES_TIEABLE_P(MODE1, MODE2)		\
   ((MODE1) == PTImode				\
    ? (MODE2) == PTImode				\
    : (MODE2) == PTImode				\
    ? 0						\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
+   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   ? 0						\
    : SCALAR_FLOAT_MODE_P (MODE1)		\
    ? SCALAR_FLOAT_MODE_P (MODE2)		\
    : SCALAR_FLOAT_MODE_P (MODE2)		\
@@ -1266,10 +1278,6 @@ enum data_align { align_abi, align_opt, 
    ? SPE_VECTOR_MODE (MODE2)			\
    : SPE_VECTOR_MODE (MODE2)			\
    ? 0						\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
-   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   ? 0						\
    : 1)
 
 /* Post-reload, we can't use any new AltiVec registers, as we already
@@ -1801,6 +1809,7 @@ typedef struct rs6000_args
 				   GPR space (darwin64) */
   int named;			/* false for varargs params */
   int escapes;			/* if function visible outside tu */
+  int libcall;			/* If this is a compiler generated call.  */
 } CUMULATIVE_ARGS;
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 227594)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -6956,7 +6956,7 @@ (define_insn "*ieee_128bit_vsx_nabs<mode
 ;; Float128 conversion functions.  These expand to library function calls.
 
 (define_expand "extend<FLOAT128_SFDFTF:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
+  [(set (match_operand:IFKF 0 "gpc_reg_operand" "")
 	(float_extend:IFKF
 	 (match_operand:FLOAT128_SFDFTF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
@@ -6966,7 +6966,7 @@ (define_expand "extend<FLOAT128_SFDFTF:m
 })
 
 (define_expand "trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2"
-  [(set (match_operand:FLOAT128_SFDFTF 0 "nonimmediate_operand" "")
+  [(set (match_operand:FLOAT128_SFDFTF 0 "gpc_reg_operand" "")
 	(float_truncate:FLOAT128_SFDFTF
 	 (match_operand:IFKF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(revision 227594)
+++ gcc/config/rs6000/rs6000-opts.h	(working copy)
@@ -80,14 +80,6 @@ enum fpu_type_t
 };
 
 
-/* Float128 support.  */
-enum float128_type_t
-{
-  FLOAT128_UNSET	= -1,	/* Initial value.  */
-  FLOAT128_NONE,		/* No __float128 support.  */
-  FLOAT128_SW			/* software __float128 support.  */
-};
-
 /* Types of costly dependences.  */
 enum rs6000_dependence_cost
 {
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 227594)
+++ gcc/doc/extend.texi	(working copy)
@@ -929,6 +929,7 @@ examine and set these two fictitious var
 @cindex additional floating types
 @cindex @code{__float80} data type
 @cindex @code{__float128} data type
+@cindex @code{__ibm128} data type
 @cindex @code{w} floating point suffix
 @cindex @code{q} floating point suffix
 @cindex @code{W} floating point suffix
@@ -941,19 +942,39 @@ Support for additional types includes th
 add, subtract, multiply, divide; unary arithmetic operators;
 relational operators; equality operators; and conversions to and from
 integer and other floating types.  Use a suffix @samp{w} or @samp{W}
-in a literal constant of type @code{__float80} and @samp{q} or @samp{Q}
-for @code{_float128}.  You can declare complex types using the
-corresponding internal complex type, @code{XCmode} for @code{__float80}
-type and @code{TCmode} for @code{__float128} type:
+in a literal constant of type @code{__float80} or type
+@code{__ibm128}.  Use a suffix @samp{q} or @samp{Q} for @code{_float128}.
+
+On the i386, x86_64, IA-64, and HP-UX targets, you can declare complex
+types using the corresponding internal complex type, @code{XCmode} for
+@code{__float80} type and @code{TCmode} for @code{__float128} type:
 
 @smallexample
 typedef _Complex float __attribute__((mode(TC))) _Complex128;
 typedef _Complex float __attribute__((mode(XC))) _Complex80;
 @end smallexample
 
+On PowerPC Linux, Freebsd and Darwin systems, the default for
+@code{long double} is to use the IBM extended floating point format
+that uses a pair of @code{double} values to extend the precision.
+This means that the mode @code{TCmode} was already used by the
+traditional IBM long double format, and you would need to use the mode
+@code{KCmode}:
+
+@smallexample
+typedef _Complex float __attribute__((mode(KC))) _Complex128;
+@end smallexample
+
 Not all targets support additional floating-point types.  @code{__float80}
 and @code{__float128} types are supported on x86 and IA-64 targets.
-The @code{__float128} type is supported on hppa HP-UX targets.
+The @code{__float128} type is supported on hppa HP-UX.
+The @code{__float128} type is supported on PowerPC systems by default
+if the vector scalar instruction set (VSX) is enabled.
+
+On the PowerPC, @code{__ibm128} provides access to the IBM extended
+double format, and it is intended to be used by the library functions
+that handle conversions if/when long double is changed to be IEEE
+128-bit floating point.
 
 @node Half-Precision
 @section Half-Precision Floating Point
@@ -13326,6 +13347,8 @@ uint64_t __builtin_ppc_get_timebase ();
 unsigned long __builtin_ppc_mftb ();
 double __builtin_unpack_longdouble (long double, int);
 long double __builtin_pack_longdouble (double, double);
+double __builtin_unpack_ibm128 (long double, int);
+__ibm128 __builtin_pack_ibm128 (double, double);
 @end smallexample
 
 The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 227594)
+++ gcc/doc/invoke.texi	(working copy)
@@ -940,7 +940,8 @@ See RS/6000 and PowerPC Options.
 -mquad-memory-atomic -mno-quad-memory-atomic @gol
 -mcompat-align-parm -mno-compat-align-parm @gol
 -mupper-regs-df -mno-upper-regs-df -mupper-regs-sf -mno-upper-regs-sf @gol
--mupper-regs -mno-upper-regs}
+-mupper-regs -mno-upper-regs @gol
+-mfloat128 -mno-float128}
 
 @emph{RX Options}
 @gccoptlist{-m64bit-doubles  -m32bit-doubles  -fpu  -nofpu@gol
@@ -19338,6 +19339,17 @@ floating point register set, depending o
 If the @option{-mno-upper-regs} option is used, it turns off both
 @option{-mupper-regs-sf} and @option{-mupper-regs-df} options.
 
+@item -mfloat128
+@itemx -mno-float128
+@opindex mfloat128
+@opindex mno-float128
+Enable/disable the @var{__float128} keyword for IEEE 128-bit floating point
+and use software emulation for IEEE 128-bit floating point.
+
+The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7}, or
+@option{-mcpu=power8}) must be enabled to use the @option{-mfloat128}
+option.
+
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
 @opindex mfloat-gprs

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised)
  2015-09-16 22:50 ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised) Michael Meissner
@ 2015-09-22  0:19   ` Michael Meissner
  2015-10-08 19:04   ` [Patch] PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
  1 sibling, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-09-22  0:19 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

A heads up. I just found some places in the IEEE 128-bit floating point code
where it doesn't handle conversions to/from __ibm128.  Nor does it generate the
same names for -mabi=ieeelongdouble.  I will submit a revised patch when it is
ready.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* [Patch] PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-09-16 22:50 ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised) Michael Meissner
  2015-09-22  0:19   ` Michael Meissner
@ 2015-10-08 19:04   ` Michael Meissner
  2015-10-08 21:30     ` Joseph Myers
  1 sibling, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-08 19:04 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 9859 bytes --]

This is the revised patch #7 for the IEEE 128-bit software floating point
support in the PowerPC. I have tested this on big endian power7 (both 32/64
bit) and little endian power8 with no regressions. Is this ok to install in the
trunk?

This patch should allow __float128 support on VSX systems, but it won't be
usable until patch #8 goes in that adds support in libgcc. It is expected that
we will need to update the glibc sources (which are where the master definition
for the soft-fp directory comes from) to add kf mode support for IEEE 128-bit
floating point. I have intermediate patches that add the support by using sed
to transform the <...>tf<...> names into <...>kf<...>.

At a high level, the changes in this patch are:

1) As we discussed previously, the option name is changed from
-mfloat128-software and -mfloat128-none to be -mfloat128 and -mno-float128.

2) Add defines so that the user can determine if __float128 is available, and
what is the default format for long double.

3) I removed the code I previously had to disallow IFmode/KFmode if -mfloat128
is not enabled.

4) Like other vector types, don't allow pre-increment and pre-decrement memory
forms that reload eventually has to fix up.

5) Add IEEE 128-bit register allocation, and call/return as vector types. In a
few places, I had to modify tests against VECTOR_TYPE_P to use
ALTIVEC_OR_VSX_VECTOR_MODE, since the IEEE 128-bit floating point types aren't
considered a vector type by the machine independent portion of the compiler.

6) Add support for all of the emulator names. In this version of the patch, I
added support for converting between the various decimal types and __float128
(but so far those new emulated functions have not been written). In addition, I
modified the compare function to have 2 variants, __cmpukf2 which is intended
to mimic the behavior of the 'fcmpu' instruction, and __cmpokf2 which is
intended to mimic the behaviour of the 'fcmpo' instruction. At the present
time, I have not written the __cmpokf2 function, and the compiler does not
currently generated 'fcmpo'.

7) I added support for the 'q' and 'Q' suffix for explict __float128 constants.

8) I reordered the tests in MODES_TIEABLE_P so that vector types are tested
before scalar floating point types, so that __float128 pairs with vector
double, but not with long double (if IBM extended double is the long double
format) and __ibm128.

9) I updated the documentation for the new switch and for the __float128 and
__ibm128 keywords.

10) I went through rs6000.md and cloned all of the support for the 128-bit
types, so that you can use the right operation on KFmode for IEEE types, IFmode
for IBM types, and TFmode will be treated as KFmode if -mabi=ieeelongdouble and
IFmode if -mabi=ibmlongdouble.

[gcc]
2015-10-06  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add -mfloat128.

	* config/rs6000/rs6000.opt (-mfloat128): Replace the switches
	-mfloat128-{software,none} with -m{,no-}float128.

	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Add defines
	to tell users whether __float128 is available, and whether long
	double is IBM extended double or IEEE 128-bit floating point.

	* config/rs6000/rs6000.c (TARGET_C_MODE_FOR_SUFFIX): Define.
	(rs6000_hard_regno_mode_ok): Remove code not allowing 128-bit
	floating types from any register if the appropriate option is not
	used.
	(rs6000_debug_reg_global): Delete -mfloat128-{software,none}
	debugging.
	(rs6000_setup_reg_addr_masks): Don't allow pre-increment or
	pre-decrement on IEEE 128-bit floating point.
	(rs6000_init_hard_regno_mode_ok): Add support for IEEE 128-bit
	floating point types.
	(rs6000_option_override_internal): Replace the switches
	-mfloat128-{software,none} with -m{,no-}float128, and move the
	tests to be closer to other ISA 2.06/2.07 options.
	(rs6000_gen_le_vsx_permute): Add support for IEEE 128-bit floating
	point.
	(init_cumulative_args): Assume that IEEE 128-bit floating point
	emulation routines have prototypes, and don't need to pass the
	arguments in the save area as well as the Altivec register set.
	(rs6000_function_arg): Likewise.
	(rs6000_arg_partial_bytes): Likewise.
	(rs6000_init_builtins): Set up ieee128_float_type_node to always
	use KFmode, and ibm128_float_type_node to always use IFmode.
	(init_float128_ibm): Split rs6000_init_libfuncs into 2 functions,
	one for IEEE 128-bit floating point, and one for IBM extended
	double floating point. For IFmode, use the traditional IBM
	extended double names. For TFmode, if -mabi=ieeelongdouble, use
	the names for KFmode.
	(init_float128_ieee): Likewise.
	(rs6000_init_libfuncs): Likewise.
	(rs6000_generate_compare): For IEEE 128-bit floating point, use
	the compare function that matches the fcmpu instruction.
	(rs6000_expand_float128_convert): Restructure code. Add support
	for using plain move if the underlying type is the same. Deal with
	src and dest being in memory.
	(rs6000_mangle_type): Use U10__float128 for IEEE 128-bit floating
	point.
	(rs6000_scalar_mode_supported_p): Add IFmode if -mfloat128.
	(rs6000_c_mode_for_suffix): Add 'q' and 'Q' suffixes for IEEE
	128-bit floating point.
	(rs6000_opt_masks): Add -mfloat128.
	(struct rs6000_opt_var): Fix typo in comment.
	(chain_contains_only_swaps): Change from VECTOR_MODE_P to
	ALTIVEC_OR_VSX_VECTOR_MODE to add IEEE 128-bit floating point
	values in VSX registers.
	(mark_swaps_for_removal): Likewise.
	(rs6000_analyze_swaps): Likewise.

	* config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Add IEEE 128-bit
	floating point types that go in VSX registers.
	(MODES_TIEABLE_P): Move vector tests above floating point scalar
	tests, so that IEEE 128-bit floating point values in VSX tie with
	other vector types.
	(struct rs6000_args): Add libcall field.

	* config/rs6000/rs6000.md (FP iterator): Allow IEEE 128-bit
	floating point.
	(FLOAT128_SFDFTF iterator): Delete, rework conversion insns.
	(IFKF iterator): Delete, replace with IBM128 iterator. Add
	explicit FLOAT128_IBM_P (<mode>) tests.
	(IBM128 iterator): Likewise.
	(IEEE128 iterator): New iterator for IEEE 128-bit floating point
	support.
	(TFIFKF iterator): Delete, replace with FLOAT128 iterator.
	(FLOAT128 iterator): Likewise.
	(signbit<mode>2): Add IEEE 128-bit floating point support.
	(extenddftf2): 	Rework IEEE 128-bit floating point code. Use
	iterators to make IFmode and KFmode patterns to mirror the TFmode
	patterns. Delete FLOAT128_SFDFTF, IFKF and TFIFKF iterators. Add
	IEEE128, and FLOAT128 iterators.
	(extenddf<mode>2): Likewise.
	(extenddftf2_fprs): Likewise.
	(extenddf<mode>2_fprs): Likewise.
	(extenddf<mode>2_vsx): Likewise.
	(extenddftf2_internal): Likewise.
	(extendsftf2): Likewise.
	(extendsf<mode>2): Likewise.
	(trunctfdf2): Rework 128-bit floating point truncation patterns.
	(trunc<mode>df2): Likewise.
	(trunctfdf2_internal1): Likewise.
	(trunc<mode>df2_internal1): Likewise.
	(trunctfdf2_internal2): Likewise.
	(trunc<mode>df2_internal2): Likewise.
	(trunctfsf2): Likewise.
	(trunc<mode>sf2): Likewise.
	(trunctfsf2_fprs): Likewise.
	(trunc<mode>sf2_fprs): Likewise.
	(floatsitf2): Rework conversion patterns from 32-bit integer types
	to 128-bit floating point.
	(floatsi<mode>2): Likewise.
	(fix_trunc_helper): Rework conversions patterns from 128-bit
	floating point types to integers.
	(fix_trunc_helper<mode>): Likewise.
	(fix_trunctfsi2): Likewise.
	(fix_trunc<mode>si2): Likewise.
	(fix_trunctfsi2_fprs): Likewise.
	(fix_trunc<mode>si2_fprs): Likewise.
	(fix_trunctfsi2_internal): Likewise.
	(fix_trunc<mode>si2_internal): Likewise.
	(fix_trunctfdi2): Likewise.
	(fix_trunc<mode>di2): Likewise.
	(fixuns_trunctf<mode>2): Likewise.
	(fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
	(floatditf2): Rework conversion patterns from 64-bit integer types
	to 128-bit floating point.
	(floatdi<mode>2): Likewise.
	(floatuns<mode>tf2): Likewise.
	(floatuns<IEEE128:mode><SDI:mode>2): Likewise.
	(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Rework conversions
	between 128-bit floating point types.
	(extendifkf2): Likewise.
	(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
	(extendtfkf2): Likewise.
	(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(extendtfkf2): Likewise.
	(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(trunciftf2): Likewise.
	(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(truncifkf2): Likewise.
	(float<SDI:mode><IFKF:mode>2): Likewise.
	(trunckftf2): Likewise.
	(floatuns<SDI:mode><IFKF:mode>2): Likewise.
	(trunctfif2): Likewise.
	(neg<mode>2): Rework IEEE 128-bit floating point negation and
	absolute value.
	(negtf2_internal): Likewise.
	(neg<mode>2_internal): Likewise.
	(abs<mode>2): Likewise.
	(abstf2_internal): Likewise.
	(abs<mode>2_internal): Likewise.
	(ieee_128bit_vsx_neg<mode>2): Likewise.
	(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
	(ieee_128bit_vsx_abs<mode>2): Likewise.
	(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
	(ieee_128bit_vsx_nabs<mode>2): Likewise.
	(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
	(cmptf_internal1): Add IFmode 128-bit comparison.
	(cmp<mode>_internal1): Likewise.

	* config/rs6000/rs6000-opts.h (enum float128_type_t):
	Delete. Switch from -mfloat128-{none,software} to
	-m{,no-}float128.

	* config/rs6000/predicates.md (reg_or_indexed_operand): Allow
	SUBREG's.

	* doc/extend.texi (additional floating types): Document PowerPC
	use of __float128 and __ibm128 types.

	* doc/invoke.texi (RS/6000 and PowerPC Options): Document
	-mfloat128 and -mno-float128.

[gcc/testsuite]
2015-10-06  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/float128-call.c: New function, test whether
	IEEE 128-bit floating point in VSX registers is passed correctly.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07b --]
[-- Type: text/plain, Size: 73852 bytes --]

Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 228506)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -80,6 +80,7 @@
 				 | OPTION_MASK_DIRECT_MOVE		\
 				 | OPTION_MASK_DLMZB			\
 				 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX	\
+				 | OPTION_MASK_FLOAT128			\
 				 | OPTION_MASK_FPRND			\
 				 | OPTION_MASK_HTM			\
 				 | OPTION_MASK_ISEL			\
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 228506)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -601,18 +601,6 @@ moptimize-swaps
 Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
 Analyze and remove doubleword swaps from VSX computations.
 
-mfloat128-
-Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save
--mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used.
-
-Enum
-Name(float128_type_t) Type(enum float128_type_t)
-
-EnumValue
-Enum(float128_type_t) String(none) Value(FLOAT128_NONE)
-
-EnumValue
-Enum(float128_type_t) String(software) Value(FLOAT128_SW)
-
-EnumValue
-Enum(float128_type_t) String(sw) Value(FLOAT128_SW)
+mfloat128
+Target Report Mask(FLOAT128) Var(rs6000_isa_flags)
+Enable/disable IEEE 128-bit floating point via the __float128 keyword.
Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 228506)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -410,6 +410,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
+  if (TARGET_FLOAT128)
+    builtin_define ("__FLOAT128__");
 
   if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM)
     {
@@ -483,6 +485,11 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     {
       builtin_define ("__LONG_DOUBLE_128__");
       builtin_define ("__LONGDOUBLE128");
+
+      if (TARGET_IEEEQUAD)
+	builtin_define ("__LONG_DOUBLE_IEEE128__");
+      else
+	builtin_define ("__LONG_DOUBLE_IBM128__");
     }
 
   switch (TARGET_CMODEL)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 228506)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1690,6 +1690,9 @@ static const struct attribute_spec rs600
 #define TARGET_LIBGCC_SHIFT_COUNT_MODE rs6000_abi_word_mode
 #undef TARGET_UNWIND_WORD_MODE
 #define TARGET_UNWIND_WORD_MODE rs6000_abi_word_mode
+
+#undef TARGET_C_MODE_FOR_SUFFIX
+#define TARGET_C_MODE_FOR_SUFFIX rs6000_c_mode_for_suffix
 \f
 
 /* Processor table.  */
@@ -1788,16 +1791,6 @@ rs6000_hard_regno_mode_ok (int regno, ma
 	    && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO)
 	    && ((regno & 1) == 0));
 
-  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
-     types from going in any registers.  Similarly if __float128 is not
-     supported, don't allow __float128/__ibm128 types.  */
-  if (!TARGET_LONG_DOUBLE_128
-      && (mode == TFmode || mode == KFmode || mode == IFmode))
-    return false;
-
-  if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
-    return false;
-
   /* VSX registers that overlap the FPR registers are larger than for non-VSX
      implementations.  Don't allow an item to be split between a FP register
      and an Altivec register.  Allow TImode in all VSX registers if the user
@@ -2071,7 +2064,6 @@ rs6000_debug_reg_global (void)
   const char *trace_str;
   const char *abi_str;
   const char *cmodel_str;
-  const char *float128_str;
   struct cl_target_option cl_opts;
 
   /* Modes we want tieable information on.  */
@@ -2437,15 +2429,6 @@ rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_S, "e500_double",
 	   (TARGET_E500_DOUBLE ? "true" : "false"));
 
-  switch (TARGET_FLOAT128)
-    {
-    case FLOAT128_NONE:	float128_str = "none";		break;
-    case FLOAT128_SW:	float128_str = "software";	break;
-    default:		float128_str = "unknown";	break;
-    }
-
-  fprintf (stderr, DEBUG_FMT_S, "float128", float128_str);
-
   if (TARGET_LINK_STACK)
     fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
 
@@ -2528,6 +2511,7 @@ rs6000_setup_reg_addr_masks (void)
 		  && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
 		  && GET_MODE_SIZE (m2) <= 8
 		  && !VECTOR_MODE_P (m2)
+		  && !FLOAT128_VECTOR_P (m2)
 		  && !COMPLEX_MODE_P (m2)
 		  && !indexed_only_p
 		  && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m2) == 8))
@@ -2673,6 +2657,20 @@ rs6000_init_hard_regno_mode_ok (bool glo
       align32 = 128;
     }
 
+  /* KF mode (IEEE 128-bit in VSX registers).  We do not have arithmetic, so
+     only set the memory modes.  Include TFmode if -mabi=ieeelongdouble.  */
+  if (TARGET_FLOAT128)
+    {
+      rs6000_vector_mem[KFmode] = VECTOR_VSX;
+      rs6000_vector_align[KFmode] = 128;
+
+      if (FLOAT128_IEEE_P (TFmode))
+	{
+	  rs6000_vector_mem[TFmode] = VECTOR_VSX;
+	  rs6000_vector_align[TFmode] = 128;
+	}
+    }
+
   /* V2DF mode, VSX only.  */
   if (TARGET_VSX)
     {
@@ -2866,7 +2864,7 @@ rs6000_init_hard_regno_mode_ok (bool glo
   if (TARGET_FLOAT128)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;	/* KFmode  */
-      if (rs6000_ieeequad)
+      if (FLOAT128_IEEE_P (TFmode))
 	rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS;	/* TFmode  */
     }
 
@@ -2889,6 +2887,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_di_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_di_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_di_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_di_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_di_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_di_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_di_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_di_store;
@@ -2896,6 +2896,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_di_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_di_load;
 
+	  if (FLOAT128_IEEE_P (TFmode))
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_di_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_di_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -2949,6 +2955,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_si_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_si_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_si_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_si_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_si_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_si_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_si_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_si_store;
@@ -2956,6 +2964,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_si_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_si_load;
 
+	  if (FLOAT128_IEEE_P (TFmode))
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_si_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_si_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -3711,13 +3725,6 @@ rs6000_option_override_internal (bool gl
       && optimize >= 3)
     rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN;
 
-  /* Set the appropriate IEEE 128-bit floating option.  Do not enable float128
-     support by default until the libgcc support is added.  */
-  if (TARGET_FLOAT128 == FLOAT128_UNSET)
-    TARGET_FLOAT128 = FLOAT128_NONE;
-  else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX)
-    error ("-mfloat128-software requires VSX support");
-
   /* Set -mallow-movmisalign to explicitly on if we have full ISA 2.07
      support. If we only have ISA 2.06 support, and the user did not specify
      the switch, leave it set to -1 so the movmisalign patterns are enabled,
@@ -3757,6 +3764,15 @@ rs6000_option_override_internal (bool gl
 	}
     }
 
+  /* __float128 requires VSX support.  */
+  if (TARGET_FLOAT128 && !TARGET_VSX)
+    {
+      if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) != 0)
+	error ("-mfloat128 requires VSX support");
+
+      rs6000_isa_flags &= ~OPTION_MASK_FLOAT128;
+    }
+
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
 
@@ -3837,7 +3853,8 @@ rs6000_option_override_internal (bool gl
      unless the altivec ABI was set.  This is set by default for 64-bit, but
      not for 32-bit.  */
   if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
-    rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC)
+    rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC
+			   | OPTION_MASK_FLOAT128)
 			  & ~rs6000_isa_flags_explicit);
 
   /* Enable Altivec ABI for AIX -maltivec.  */
@@ -8467,8 +8484,14 @@ rs6000_const_vec (machine_mode mode)
 rtx
 rs6000_gen_le_vsx_permute (rtx source, machine_mode mode)
 {
-  rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
-  return gen_rtx_VEC_SELECT (mode, source, par);
+  /* Use ROTATE instead of VEC_SELECT on IEEE 128-bit floating point.  */
+  if (FLOAT128_VECTOR_P (mode))
+    return gen_rtx_ROTATE (mode, source, GEN_INT (64));
+  else
+    {
+      rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
+      return gen_rtx_VEC_SELECT (mode, source, par);
+    }
 }
 
 /* Emit a little-endian load from vector memory location SOURCE to VSX
@@ -9447,6 +9470,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      ? CALL_LIBCALL : CALL_NORMAL);
   cum->sysv_gregno = GP_ARG_MIN_REG;
   cum->stdarg = stdarg_p (fntype);
+  cum->libcall = libcall;
 
   cum->nargs_prototype = 0;
   if (incoming || cum->prototype)
@@ -10609,9 +10633,11 @@ rs6000_function_arg (cumulative_args_t c
       rtx r, off;
       int i, k = 0;
 
-      /* Do we also need to pass this argument in the parameter
-	 save area?  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* Do we also need to pass this argument in the parameter save area?
+	 Library support functions for IEEE 128-bit are assumed to not need the
+	 value passed both in GPRs and in vector registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	{
 	  int align_words = (cum->words + 1) & ~1;
 	  k = rs6000_psave_function_arg (mode, type, align_words, rvec);
@@ -10842,11 +10868,14 @@ rs6000_arg_partial_bytes (cumulative_arg
 
   if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
     {
-      /* If we are passing this arg in the fixed parameter save area
-         (gprs or memory) as well as VRs, we do not use the partial
-	 bytes mechanism; instead, rs6000_function_arg will return a
-	 PARALLEL including a memory element as necessary.  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* If we are passing this arg in the fixed parameter save area (gprs or
+         memory) as well as VRs, we do not use the partial bytes mechanism;
+         instead, rs6000_function_arg will return a PARALLEL including a memory
+         element as necessary.  Library support functions for IEEE 128-bit are
+         assumed to not need the value passed both in GPRs and in vector
+         registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	return 0;
 
       /* Otherwise, we pass in VRs only.  Check for partial copies.  */
@@ -14431,8 +14460,6 @@ rs6000_init_builtins (void)
   tree tdecl;
   tree ftype;
   machine_mode mode;
-  machine_mode ieee128_mode;
-  machine_mode ibm128_mode;
 
   if (TARGET_DEBUG_BUILTIN)
     fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n",
@@ -14505,26 +14532,24 @@ rs6000_init_builtins (void)
      TFmode will be either IEEE 128-bit floating point or the IBM double-double
      format that uses a pair of doubles, depending on the switches and
      defaults.  */
-  if (TARGET_IEEEQUAD)
-    {
-      ieee128_mode = TFmode;
-      ibm128_mode = IFmode;
-    }
-  else
+  if (TARGET_FLOAT128)
     {
-      ieee128_mode = KFmode;
-      ibm128_mode = TFmode;
-    }
+      ibm128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ibm128_float_type_node) = 128;
+      layout_type (ibm128_float_type_node);
+      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+
+      ieee128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ieee128_float_type_node) = 128;
+      layout_type (ieee128_float_type_node);
+      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
 
-  ieee128_float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (ieee128_float_type_node) = 128;
-  layout_type (ieee128_float_type_node);
-  SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode);
+      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+					      "__float128");
 
-  ibm128_float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (ibm128_float_type_node) = 128;
-  layout_type (ibm128_float_type_node);
-  SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode);
+      lang_hooks.types.register_builtin_type (ibm128_float_type_node,
+					      "__ibm128");
+    }
 
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
@@ -16030,75 +16055,184 @@ rs6000_common_init_builtins (void)
     }
 }
 
+/* Set up AIX/Darwin/64-bit Linux quad floating point routines.  */
 static void
-rs6000_init_libfuncs (void)
+init_float128_ibm (machine_mode mode)
 {
-  if (!TARGET_IEEEQUAD)
-      /* AIX/Darwin/64-bit Linux quad floating point routines.  */
-    if (!TARGET_XL_COMPAT)
-      {
-	set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
-	set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
-	set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
+  if (!TARGET_XL_COMPAT)
+    {
+      set_optab_libfunc (add_optab, mode, "__gcc_qadd");
+      set_optab_libfunc (sub_optab, mode, "__gcc_qsub");
+      set_optab_libfunc (smul_optab, mode, "__gcc_qmul");
+      set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv");
 
-	if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
-	  {
-	    set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
-	    set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
-	    set_optab_libfunc (ne_optab, TFmode, "__gcc_qne");
-	    set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt");
-	    set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
-	    set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
-	    set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
-
-	    set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
-	    set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
-	    set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos");
-	    set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod");
-	    set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi");
-	    set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou");
-	    set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
-	    set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
-	  }
+      if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
+	{
+	  set_optab_libfunc (neg_optab, mode, "__gcc_qneg");
+	  set_optab_libfunc (eq_optab, mode, "__gcc_qeq");
+	  set_optab_libfunc (ne_optab, mode, "__gcc_qne");
+	  set_optab_libfunc (gt_optab, mode, "__gcc_qgt");
+	  set_optab_libfunc (ge_optab, mode, "__gcc_qge");
+	  set_optab_libfunc (lt_optab, mode, "__gcc_qlt");
+	  set_optab_libfunc (le_optab, mode, "__gcc_qle");
 
-	if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
-	  set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
-      }
-    else
-      {
-	set_optab_libfunc (add_optab, TFmode, "_xlqadd");
-	set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
-	set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
-      }
+	  set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq");
+	  set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq");
+	  set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos");
+	  set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod");
+	  set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi");
+	  set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou");
+	  set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq");
+	  set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq");
+	}
+
+      if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
+	set_optab_libfunc (unord_optab, mode, "__gcc_qunord");
+    }
   else
     {
-      /* 32-bit SVR4 quad floating point routines.  */
+      set_optab_libfunc (add_optab, mode, "_xlqadd");
+      set_optab_libfunc (sub_optab, mode, "_xlqsub");
+      set_optab_libfunc (smul_optab, mode, "_xlqmul");
+      set_optab_libfunc (sdiv_optab, mode, "_xlqdiv");
+    }
+
+  /* Add various conversions for IFmode to use the traditional TFmode
+     names.  */
+  if (mode == IFmode)
+    {
+      set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdtf2");
+      set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddtf2");
+      set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunctftd2");
+      set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunctfsd2");
+      set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunctfdd2");
+      set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtdtf2");
 
-      set_optab_libfunc (add_optab, TFmode, "_q_add");
-      set_optab_libfunc (sub_optab, TFmode, "_q_sub");
-      set_optab_libfunc (neg_optab, TFmode, "_q_neg");
-      set_optab_libfunc (smul_optab, TFmode, "_q_mul");
-      set_optab_libfunc (sdiv_optab, TFmode, "_q_div");
+      if (TARGET_POWERPC64)
+	{
+	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixtfti");
+	  set_conv_libfunc (ufix_optab, TImode, mode, "__fixunstfti");
+	  set_conv_libfunc (sfloat_optab, mode, TImode, "__floattitf");
+	  set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntitf");
+	}
+    }
+}
+
+/* Set up IEEE 128-bit floating point routines.  Use different names if the
+   arguments can be passed in a vector register.  The historical PowerPC
+   implementation of IEEE 128-bit floating point used _q_<op> for the names, so
+   continue to use that if we aren't using vector registers to pass IEEE
+   128-bit floating point.  */
+
+static void
+init_float128_ieee (machine_mode mode)
+{
+  if (FLOAT128_VECTOR_P (mode))
+    {
+      set_optab_libfunc (add_optab, mode, "__addkf3");
+      set_optab_libfunc (sub_optab, mode, "__subkf3");
+      set_optab_libfunc (neg_optab, mode, "__negkf2");
+      set_optab_libfunc (smul_optab, mode, "__mulkf3");
+      set_optab_libfunc (sdiv_optab, mode, "__divkf3");
+      set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2");
+      set_optab_libfunc (abs_optab, mode, "__abstkf2");
+
+      set_optab_libfunc (eq_optab, mode, "__eqkf2");
+      set_optab_libfunc (ne_optab, mode, "__nekf2");
+      set_optab_libfunc (gt_optab, mode, "__gtkf2");
+      set_optab_libfunc (ge_optab, mode, "__gekf2");
+      set_optab_libfunc (lt_optab, mode, "__ltkf2");
+      set_optab_libfunc (le_optab, mode, "__lekf2");
+      set_optab_libfunc (unord_optab, mode, "__unordkf2");
+      set_optab_libfunc (cmp_optab, mode, "__cmpokf2");		/* fcmpo */
+      set_optab_libfunc (ucmp_optab, mode, "__cmpukf2");	/* fcmpu */
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2");
+      set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2");
+
+      set_conv_libfunc (sext_optab, mode, IFmode, "__extendtfkf2");
+      if (mode != TFmode && FLOAT128_IBM_P (TFmode))
+	set_conv_libfunc (sext_optab, mode, TFmode, "__extendtfkf2");
+
+      set_conv_libfunc (trunc_optab, IFmode, mode, "__trunckftf2");
+      if (mode != TFmode && FLOAT128_IBM_P (TFmode))
+	set_conv_libfunc (trunc_optab, TFmode, mode, "__trunckftf2");
+
+      set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdkf2");
+      set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddkf2");
+      set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunckftd2");
+      set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunckfsd2");
+      set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunckfdd2");
+      set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtdkf2");
+
+      set_conv_libfunc (sfix_optab, SImode, mode, "__fixkfsi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "__fixunskfsi");
+      set_conv_libfunc (sfix_optab, DImode, mode, "__fixkfdi");
+      set_conv_libfunc (ufix_optab, DImode, mode, "__fixunskfdi");
+
+      set_conv_libfunc (sfloat_optab, mode, SImode, "__floatsikf");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "__floatunsikf");
+      set_conv_libfunc (sfloat_optab, mode, DImode, "__floatdikf");
+      set_conv_libfunc (ufloat_optab, mode, DImode, "__floatundikf");
+
+      if (TARGET_POWERPC64)
+	{
+	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti");
+	  set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti");
+	  set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf");
+	  set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf");
+	}
+    }
+
+  else
+    {
+      set_optab_libfunc (add_optab, mode, "_q_add");
+      set_optab_libfunc (sub_optab, mode, "_q_sub");
+      set_optab_libfunc (neg_optab, mode, "_q_neg");
+      set_optab_libfunc (smul_optab, mode, "_q_mul");
+      set_optab_libfunc (sdiv_optab, mode, "_q_div");
       if (TARGET_PPC_GPOPT)
-	set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
+	set_optab_libfunc (sqrt_optab, mode, "_q_sqrt");
 
-      set_optab_libfunc (eq_optab, TFmode, "_q_feq");
-      set_optab_libfunc (ne_optab, TFmode, "_q_fne");
-      set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
-      set_optab_libfunc (ge_optab, TFmode, "_q_fge");
-      set_optab_libfunc (lt_optab, TFmode, "_q_flt");
-      set_optab_libfunc (le_optab, TFmode, "_q_fle");
-
-      set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
-      set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
-      set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
-      set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
-      set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
-      set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
-      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
-      set_conv_libfunc (ufloat_optab, TFmode, SImode, "_q_utoq");
+      set_optab_libfunc (eq_optab, mode, "_q_feq");
+      set_optab_libfunc (ne_optab, mode, "_q_fne");
+      set_optab_libfunc (gt_optab, mode, "_q_fgt");
+      set_optab_libfunc (ge_optab, mode, "_q_fge");
+      set_optab_libfunc (lt_optab, mode, "_q_flt");
+      set_optab_libfunc (le_optab, mode, "_q_fle");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "_q_stoq");
+      set_conv_libfunc (sext_optab, mode, DFmode, "_q_dtoq");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "_q_qtos");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "_q_qtod");
+      set_conv_libfunc (sfix_optab, SImode, mode, "_q_qtoi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "_q_qtou");
+      set_conv_libfunc (sfloat_optab, mode, SImode, "_q_itoq");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "_q_utoq");
+    }
+}
+
+static void
+rs6000_init_libfuncs (void)
+{
+  /* __float128 support.  */
+  if (TARGET_FLOAT128)
+    {
+      init_float128_ibm (IFmode);
+      init_float128_ieee (KFmode);
+    }
+
+  /* AIX/Darwin/64-bit Linux quad floating point routines.  */
+  if (TARGET_LONG_DOUBLE_128)
+    {
+      if (!TARGET_IEEEQUAD)
+	init_float128_ibm (TFmode);
+
+      /* IEEE 128-bit including 32-bit SVR4 quad floating point routines.  */
+      else
+	init_float128_ieee (TFmode);
     }
 }
 
@@ -19983,17 +20117,18 @@ rs6000_generate_compare (rtx cmp, machin
       emit_insn (cmp);
     }
 
-  /* IEEE 128-bit support in VSX registers.  The comparison function (__cmpkf2)
-     returns 0..15 that is laid out the same way as the PowerPC CR register
-     would for a normal floating point comparison.  */
+  /* IEEE 128-bit support in VSX registers.  The comparison functions
+     (__cmpokf2 and __cmpukf2) returns 0..15 that is laid out the same way as
+     the PowerPC CR register would for a normal floating point comparison from
+     the fcmpo and fcmpu instructions.  */
   else if (FLOAT128_IEEE_P (mode))
     {
       rtx and_reg = gen_reg_rtx (SImode);
       rtx dest = gen_reg_rtx (SImode);
-      rtx libfunc = optab_libfunc (cmp_optab, mode);
+      rtx libfunc = optab_libfunc (ucmp_optab, mode);
       HOST_WIDE_INT mask_value = 0;
 
-      /* Values that __cmpkf2 returns.  */
+      /* Values that __cmpokf2/__cmpukf2 returns.  */
 #define PPC_CMP_UNORDERED	0x1		/* isnan (a) || isnan (b).  */
 #define PPC_CMP_EQUAL		0x2		/* a == b.  */
 #define PPC_CMP_GREATER_THEN	0x4		/* a > b.  */
@@ -20164,7 +20299,7 @@ rs6000_generate_compare (rtx cmp, machin
   return gen_rtx_fmt_ee (code, VOIDmode, compare_result, const0_rtx);
 }
 
-
+\f
 /* Expand floating point conversion to/from __float128 and __ibm128.  */
 
 void
@@ -20173,60 +20308,121 @@ rs6000_expand_float128_convert (rtx dest
   machine_mode dest_mode = GET_MODE (dest);
   machine_mode src_mode = GET_MODE (src);
   convert_optab cvt = unknown_optab;
+  bool do_move = false;
   rtx libfunc = NULL_RTX;
   rtx dest2;
 
   if (dest_mode == src_mode)
     gcc_unreachable ();
 
+  /* Eliminate memory operations.  */
+  if (MEM_P (src))
+    src = force_reg (src_mode, src);
+
+  if (MEM_P (dest))
+    {
+      rtx tmp = gen_reg_rtx (dest_mode);
+      rs6000_expand_float128_convert (tmp, src, unsigned_p);
+      rs6000_emit_move (dest, tmp, dest_mode);
+      return;
+    }
+
+  /* Convert to IEEE 128-bit floating point.  */
   if (FLOAT128_IEEE_P (dest_mode))
     {
-      if (src_mode == SFmode
-	  || src_mode == DFmode
-	  || FLOAT128_IBM_P (src_mode))
-	cvt = sext_optab;
+      switch (src_mode)
+	{
+	case DFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (src_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	case SFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (FLOAT128_IEEE_P (src_mode))
-	emit_move_insn (dest, gen_lowpart (dest_mode, src));
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (src_mode))
+	    cvt = sext_optab;
+	  else
+	    do_move = true;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Convert from IEEE 128-bit floating point.  */
   else if (FLOAT128_IEEE_P (src_mode))
     {
-      if (dest_mode == SFmode
-	  || dest_mode == DFmode
-	  || FLOAT128_IBM_P (dest_mode))
-	cvt = trunc_optab;
+      switch (dest_mode)
+	{
+	case DFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (dest_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	case SFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (dest_mode))
+	    cvt = trunc_optab;
+	  else
+	    do_move = true;
+	  break;
+
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Both IBM format.  */
+  else if (FLOAT128_IBM_P (dest_mode) && FLOAT128_IBM_P (src_mode))
+    do_move = true;
+
   else
     gcc_unreachable ();
 
-  gcc_assert (cvt != unknown_optab);
-  libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
-  gcc_assert (libfunc != NULL_RTX);
-
-  dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
-				   src_mode);
-
-  gcc_assert (dest != NULL_RTX);
-  if (!rtx_equal_p (dest, dest2))
-    emit_move_insn (dest, dest2);
+  /* Handle conversion between TFmode/KFmode.  */
+  if (do_move)
+    emit_move_insn (dest, gen_lowpart (dest_mode, src));
+
+  /* Call an external function to do the conversion.  */
+  else if (cvt != unknown_optab)
+    {
+      libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
+      gcc_assert (libfunc != NULL_RTX);
+
+      dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
+				       src_mode);
+
+      gcc_assert (dest2 != NULL_RTX);
+      if (!rtx_equal_p (dest, dest2))
+	emit_move_insn (dest, dest2);
+    }
+
+  else
+    gcc_unreachable ();
 
   return;
 }
 
+\f
 /* Emit the RTL for an sISEL pattern.  */
 
 void
@@ -29831,6 +30027,21 @@ rs6000_mangle_type (const_tree type)
   if (type == bool_int_type_node) return "U6__booli";
   if (type == bool_long_type_node) return "U6__booll";
 
+  /* Use a unique name for __float128 rather than trying to use "e" or "g". Use
+     "g" for IBM extended double, no matter whether it is long double (using
+     -mabi=ibmlongdouble) or the distinct __ibm128 type.  */
+  if (TARGET_FLOAT128)
+    {
+      if (type == ieee128_float_type_node)
+	return "U10__float128";
+
+      if (type == ibm128_float_type_node)
+	return "g";
+
+      if (type == long_double_type_node && TARGET_LONG_DOUBLE_128)
+	return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
+    }
+
   /* Mangle IBM extended float long double as `g' (__float128) on
      powerpc*-linux where long-double-64 previously was the default.  */
   if (TYPE_MAIN_VARIANT (type) == long_double_type_node
@@ -33116,8 +33327,8 @@ rs6000_scalar_mode_supported_p (machine_
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
-  else if (mode == KFmode)
-    return TARGET_FLOAT128;
+  else if (TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+    return true;
   else
     return default_scalar_mode_supported_p (mode);
 }
@@ -33143,6 +33354,26 @@ rs6000_vector_mode_supported_p (machine_
     return false;
 }
 
+/* Target hook for c_mode_for_suffix.  */
+static machine_mode
+rs6000_c_mode_for_suffix (char suffix)
+{
+  if (TARGET_FLOAT128)
+    {
+      if (suffix == 'q' || suffix == 'Q')
+	return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+
+      /* At the moment, we are not defining a suffix for IBM extended double.
+	 If/when the default for -mabi=ieeelongdouble is changed, and we want
+	 to support __ibm128 constants in legacy library code, we may need to
+	 re-evalaute this decision.  Currently, c-lex.c only supports 'w' and
+	 'q' as machine dependent suffixes.  The x86_64 port uses 'w' for
+	 __float80 constants.  */
+    }
+
+  return VOIDmode;
+}
+
 /* Target hook for invalid_arg_for_unprototyped_fn. */
 static const char *
 invalid_arg_for_unprototyped_fn (const_tree typelist, const_tree funcdecl, const_tree val)
@@ -33228,6 +33459,7 @@ static struct rs6000_opt_mask const rs60
   { "dlmzb",			OPTION_MASK_DLMZB,		false, true  },
   { "efficient-unaligned-vsx",	OPTION_MASK_EFFICIENT_UNALIGNED_VSX,
 								false, true  },
+  { "float128",			OPTION_MASK_FLOAT128,		false, true  },
   { "fprnd",			OPTION_MASK_FPRND,		false, true  },
   { "hard-dfp",			OPTION_MASK_DFP,		false, true  },
   { "htm",			OPTION_MASK_HTM,		false, true  },
@@ -33306,7 +33538,7 @@ static struct rs6000_opt_mask const rs60
 struct rs6000_opt_var {
   const char *name;		/* option name */
   size_t global_offset;		/* offset of the option in global_options.  */
-  size_t target_offset;		/* offset of the option in target optiosn.  */
+  size_t target_offset;		/* offset of the option in target options.  */
 };
 
 static struct rs6000_opt_var const rs6000_opt_vars[] =
@@ -35611,7 +35843,7 @@ chain_contains_only_swaps (swap_web_entr
 
   for (; link; link = link->next)
     {
-      if (!VECTOR_MODE_P (GET_MODE (DF_REF_REG (link->ref))))
+      if (!ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (DF_REF_REG (link->ref))))
 	continue;
 
       if (DF_REF_IS_ARTIFICIAL (link->ref))
@@ -35710,7 +35942,7 @@ mark_swaps_for_removal (swap_web_entry *
 	{
 	  /* Ignore uses for addressability.  */
 	  machine_mode mode = GET_MODE (DF_REF_REG (use));
-	  if (!VECTOR_MODE_P (mode))
+	  if (!ALTIVEC_OR_VSX_VECTOR_MODE (mode))
 	    continue;
 
 	  struct df_link *link = DF_REF_CHAIN (use);
@@ -36224,10 +36456,11 @@ rs6000_analyze_swaps (function *fun)
 		    mode = V4SImode;
 		}
 
-	      if (VECTOR_MODE_P (mode) || mode == TImode)
+	      if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
 		{
 		  insn_entry[uid].is_relevant = 1;
-		  if (mode == TImode || mode == V1TImode)
+		  if (mode == TImode || mode == V1TImode
+		      || FLOAT128_VECTOR_P (mode))
 		    insn_entry[uid].is_128_int = 1;
 		  if (DF_REF_INSN_INFO (mention))
 		    insn_entry[uid].contains_subreg
@@ -36248,13 +36481,14 @@ rs6000_analyze_swaps (function *fun)
 		 isn't sufficient to ensure we union the call into the
 		 web with the parameter setup code.  */
 	      if (mode == DImode && GET_CODE (insn) == SET
-		  && VECTOR_MODE_P (GET_MODE (SET_DEST (insn))))
+		  && ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (SET_DEST (insn))))
 		mode = GET_MODE (SET_DEST (insn));
 
-	      if (VECTOR_MODE_P (mode) || mode == TImode)
+	      if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
 		{
 		  insn_entry[uid].is_relevant = 1;
-		  if (mode == TImode || mode == V1TImode)
+		  if (mode == TImode || mode == V1TImode
+		      || FLOAT128_VECTOR_P (mode))
 		    insn_entry[uid].is_128_int = 1;
 		  if (DF_REF_INSN_INFO (mention))
 		    insn_entry[uid].contains_subreg
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 228506)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1217,11 +1217,16 @@ enum data_align { align_abi, align_opt, 
 	 ((MODE) == V4SFmode		\
 	  || (MODE) == V2DFmode)	\
 
-#define ALTIVEC_VECTOR_MODE(MODE)	\
-	 ((MODE) == V16QImode		\
-	  || (MODE) == V8HImode		\
-	  || (MODE) == V4SFmode		\
-	  || (MODE) == V4SImode)
+/* Note KFmode and possibly TFmode (i.e. IEEE 128-bit floating point) are not
+   really a vector, but we want to treat it as a vector for moves, and
+   such.  */
+
+#define ALTIVEC_VECTOR_MODE(MODE)					\
+  ((MODE) == V16QImode							\
+   || (MODE) == V8HImode						\
+   || (MODE) == V4SFmode						\
+   || (MODE) == V4SImode						\
+   || FLOAT128_VECTOR_P (MODE))
 
 #define ALTIVEC_OR_VSX_VECTOR_MODE(MODE)				\
   (ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)			\
@@ -1248,12 +1253,19 @@ enum data_align { align_abi, align_opt, 
 
    PTImode cannot tie with other modes because PTImode is restricted to even
    GPR registers, and TImode can go in any GPR as well as VSX registers (PR
-   57744).  */
+   57744).
+
+   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
+   128-bit floating point on VSX systems ties with other vectors.  */
 #define MODES_TIEABLE_P(MODE1, MODE2)		\
   ((MODE1) == PTImode				\
    ? (MODE2) == PTImode				\
    : (MODE2) == PTImode				\
    ? 0						\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
+   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   ? 0						\
    : SCALAR_FLOAT_MODE_P (MODE1)		\
    ? SCALAR_FLOAT_MODE_P (MODE2)		\
    : SCALAR_FLOAT_MODE_P (MODE2)		\
@@ -1266,10 +1278,6 @@ enum data_align { align_abi, align_opt, 
    ? SPE_VECTOR_MODE (MODE2)			\
    : SPE_VECTOR_MODE (MODE2)			\
    ? 0						\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
-   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   ? 0						\
    : 1)
 
 /* Post-reload, we can't use any new AltiVec registers, as we already
@@ -1801,6 +1809,7 @@ typedef struct rs6000_args
 				   GPR space (darwin64) */
   int named;			/* false for varargs params */
   int escapes;			/* if function visible outside tu */
+  int libcall;			/* If this is a compiler generated call.  */
 } CUMULATIVE_ARGS;
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 228511)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -347,8 +347,7 @@ (define_mode_iterator FP [
    && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_E500_SINGLE)")
   (DF "TARGET_HARD_FLOAT 
    && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)")
-  (TF "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
+  (TF "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
   (IF "TARGET_FLOAT128")
@@ -448,24 +447,18 @@ (define_mode_iterator RECIPF [SF DF V4SF
 ; Iterator for just SF/DF
 (define_mode_iterator SFDF [SF DF])
 
-; Iterator for float128 floating conversions
-(define_mode_iterator FLOAT128_SFDFTF [
-    (SF "TARGET_FLOAT128")
-    (DF "TARGET_FLOAT128")
-    (TF "FLOAT128_IBM_P (TFmode)")
-    (IF "TARGET_FLOAT128")])
-
-; Iterator for special 128-bit floating point.  This is for non-default
-; conversions, so TFmode is not used here.
-(define_mode_iterator IFKF [IF KF])
-
 ; Iterator for 128-bit floating point that uses the IBM double-double format
-(define_mode_iterator IBM128 [IF TF])
+(define_mode_iterator IBM128 [(IF "FLOAT128_IBM_P (IFmode)")
+			      (TF "FLOAT128_IBM_P (TFmode)")])
+
+; Iterator for 128-bit floating point that uses IEEE 128-bit float
+(define_mode_iterator IEEE128 [(KF "FLOAT128_IEEE_P (KFmode)")
+			       (TF "FLOAT128_IEEE_P (TFmode)")])
 
 ; Iterator for 128-bit floating point
-(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128")
-			      (IF "TARGET_FLOAT128")
-			      (TF "TARGET_LONG_DOUBLE_128")])
+(define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128")
+				(IF "TARGET_FLOAT128")
+				(TF "TARGET_LONG_DOUBLE_128")])
 
 ; SF/DF suffix for traditional floating instructions
 (define_mode_attr Ftrad		[(SF "s") (DF "")])
@@ -4248,8 +4241,7 @@ (define_expand "signbit<mode>2"
    	(match_dup 5))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
   	(match_dup 6))]
-  "FLOAT128_IBM_P (<MODE>mode)
-   && TARGET_HARD_FLOAT
+  "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)"
 {
   operands[2] = gen_reg_rtx (DFmode);
@@ -6476,34 +6468,51 @@ (define_insn_and_split "*mov<mode>_softf
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
   [(set_attr "length" "20,20,16")])
 
-(define_expand "extenddftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(float_extend:TF (match_operand:DF 1 "gpc_reg_operand" "")))]
+(define_expand "extenddf<mode>2"
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
   else if (TARGET_E500_DOUBLE)
-    emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
+    {
+      gcc_assert (<MODE>mode == TFmode);
+      emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
+    }
   else if (TARGET_VSX)
-    emit_insn (gen_extenddftf2_vsx (operands[0], operands[1]));
-  else
+    {
+      if (<MODE>mode == TFmode)
+	emit_insn (gen_extenddftf2_vsx (operands[0], operands[1]));
+      else if (<MODE>mode == IFmode)
+	emit_insn (gen_extenddfif2_vsx (operands[0], operands[1]));
+      else
+	gcc_unreachable ();
+    }
+   else
     {
       rtx zero = gen_reg_rtx (DFmode);
       rs6000_emit_move (zero, CONST0_RTX (DFmode), DFmode);
-      emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero));
+
+      if (<MODE>mode == TFmode)
+	emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero));
+      else if (<MODE>mode == IFmode)
+	emit_insn (gen_extenddfif2_fprs (operands[0], operands[1], zero));
+      else
+	gcc_unreachable ();
     }
   DONE;
 })
 
 ;; Allow memory operands for the source to be created by the combiner.
-(define_insn_and_split "extenddftf2_fprs"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=d,d,&d")
-	(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "d,m,d")))
+(define_insn_and_split "extenddf<mode>2_fprs"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d,&d")
+	(float_extend:IBM128
+	 (match_operand:DF 1 "nonimmediate_operand" "d,m,d")))
    (use (match_operand:DF 2 "nonimmediate_operand" "m,m,d"))]
   "!TARGET_VSX && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
-   && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD"
+   && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 3) (match_dup 1))
@@ -6512,14 +6521,15 @@ (define_insn_and_split "extenddftf2_fprs
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
 
-  operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
-  operands[4] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+  operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
+  operands[4] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
 })
 
-(define_insn_and_split "extenddftf2_vsx"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=d,d")
-	(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "ws,m")))]
-  "TARGET_LONG_DOUBLE_128 && TARGET_VSX && !TARGET_IEEEQUAD"
+(define_insn_and_split "extenddf<mode>2_vsx"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d")
+	(float_extend:IBM128
+	 (match_operand:DF 1 "nonimmediate_operand" "ws,m")))]
+  "TARGET_LONG_DOUBLE_128 && TARGET_VSX && FLOAT128_IBM_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (match_dup 1))
@@ -6528,47 +6538,48 @@ (define_insn_and_split "extenddftf2_vsx"
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
 
-  operands[2] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
-  operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+  operands[2] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
+  operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
   operands[4] = CONST0_RTX (DFmode);
 })
 
-(define_expand "extendsftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))]
+(define_expand "extendsf<mode>2"
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(float_extend:FLOAT128 (match_operand:SF 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
   else
     {
       rtx tmp = gen_reg_rtx (DFmode);
       emit_insn (gen_extendsfdf2 (tmp, operands[1]));
-      emit_insn (gen_extenddftf2 (operands[0], tmp));
+      emit_insn (gen_extenddf<mode>2 (operands[0], tmp));
     }
   DONE;
 })
 
-(define_expand "trunctfdf2"
+(define_expand "trunc<mode>df2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
+	(float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     {
       rs6000_expand_float128_convert (operands[0], operands[1], false);
       DONE;
     }
 })
 
-(define_insn_and_split "trunctfdf2_internal1"
+(define_insn_and_split "trunc<mode>df2_internal1"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d")
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,d")))]
-  "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
+	(float_truncate:DF
+	 (match_operand:IBM128 1 "gpc_reg_operand" "0,d")))]
+  "FLOAT128_IBM_P (<MODE>mode) && !TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "@
    #
@@ -6581,39 +6592,44 @@ (define_insn_and_split "trunctfdf2_inter
 }
   [(set_attr "type" "fp")])
 
-(define_insn "trunctfdf2_internal2"
+(define_insn "trunc<mode>df2_internal2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
-   && TARGET_LONG_DOUBLE_128"
+	(float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "d")))]
+  "FLOAT128_IBM_P (<MODE>mode) && TARGET_XL_COMPAT && TARGET_HARD_FLOAT
+   && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
   "fadd %0,%1,%L1"
   [(set_attr "type" "fp")
    (set_attr "fp_type" "fp_addsub_d")])
 
-(define_expand "trunctfsf2"
+(define_expand "trunc<mode>sf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
-	(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))]
+	(float_truncate:SF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
   else if (TARGET_E500_DOUBLE)
-    emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
-  else
+    {
+      gcc_assert (<MODE>mode == TFmode);
+      emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
+    }
+  else if (<MODE>mode == TFmode)
     emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1]));
+  else if (<MODE>mode == IFmode)
+    emit_insn (gen_truncifsf2_fprs (operands[0], operands[1]));
+  else
+    gcc_unreachable ();
   DONE;
 })
 
-(define_insn_and_split "trunctfsf2_fprs"
+(define_insn_and_split "trunc<mode>sf2_fprs"
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-	(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "d")))
+	(float_truncate:SF (match_operand:IBM128 1 "gpc_reg_operand" "d")))
    (clobber (match_scratch:DF 2 "=d"))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT 
-   && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT 
+   && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 2)
@@ -6622,56 +6638,69 @@ (define_insn_and_split "trunctfsf2_fprs"
 	(float_truncate:SF (match_dup 2)))]
   "")
 
-(define_expand "floatsitf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-        (float:TF (match_operand:SI 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
+(define_expand "floatsi<mode>2"
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+        (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  rtx tmp = gen_reg_rtx (DFmode);
-  expand_float (tmp, operands[1], false);
-  emit_insn (gen_extenddftf2 (operands[0], tmp));
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    rs6000_expand_float128_convert (operands[0], operands[1], false);
+  else
+    {
+      rtx tmp = gen_reg_rtx (DFmode);
+      expand_float (tmp, operands[1], false);
+      if (<MODE>mode == TFmode)
+	emit_insn (gen_extenddftf2 (operands[0], tmp));
+      else if (<MODE>mode == IFmode)
+	emit_insn (gen_extenddfif2 (operands[0], tmp));
+      else
+	gcc_unreachable ();
+    }
   DONE;
 })
 
 ; fadd, but rounding towards zero.
 ; This is probably not the optimal code sequence.
-(define_insn "fix_trunc_helper"
+(define_insn "fix_trunc_helper<mode>"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-	(unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "d")]
+	(unspec:DF [(match_operand:IBM128 1 "gpc_reg_operand" "d")]
 		   UNSPEC_FIX_TRUNC_TF))
    (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && FLOAT128_IBM_P (<MODE>mode)"
   "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2"
   [(set_attr "type" "fp")
    (set_attr "length" "20")])
 
-(define_expand "fix_trunctfsi2"
+(define_expand "fix_trunc<mode>si2"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
-	(fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))]
+	(fix:SI (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
-  else if (TARGET_E500_DOUBLE)
+  else if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
     emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1]));
-  else
+  else if (<MODE>mode == TFmode)
     emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1]));
+  else if (<MODE>mode == IFmode)
+    emit_insn (gen_fix_truncifsi2_fprs (operands[0], operands[1]));
+  else
+    gcc_unreachable ();
   DONE;
 })
 
-(define_expand "fix_trunctfsi2_fprs"
+(define_expand "fix_trunc<mode>si2_fprs"
   [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
-		   (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))
+		   (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "")))
 	      (clobber (match_dup 2))
 	      (clobber (match_dup 3))
 	      (clobber (match_dup 4))
 	      (clobber (match_dup 5))])]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
   operands[2] = gen_reg_rtx (DFmode);
   operands[3] = gen_reg_rtx (DFmode);
@@ -6679,21 +6708,21 @@ (define_expand "fix_trunctfsi2_fprs"
   operands[5] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode));
 })
 
-(define_insn_and_split "*fix_trunctfsi2_internal"
+(define_insn_and_split "*fix_trunc<mode>si2_internal"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (fix:SI (match_operand:TF 1 "gpc_reg_operand" "d")))
+        (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "d")))
    (clobber (match_operand:DF 2 "gpc_reg_operand" "=d"))
    (clobber (match_operand:DF 3 "gpc_reg_operand" "=&d"))
    (clobber (match_operand:DI 4 "gpc_reg_operand" "=d"))
    (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
   ""
   [(pc)]
 {
   rtx lowword;
-  emit_insn (gen_fix_trunc_helper (operands[2], operands[1], operands[3]));
+  emit_insn (gen_fix_trunc_helper<mode> (operands[2], operands[1],
+					 operands[3]));
 
   gcc_assert (MEM_P (operands[5]));
   lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
@@ -6704,45 +6733,45 @@ (define_insn_and_split "*fix_trunctfsi2_
   DONE;
 })
 
-(define_expand "fix_trunctfdi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
-	(fix:DI (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "fix_trunc<mode>di2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+	(fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "fixuns_trunctf<mode>2"
-  [(set (match_operand:SDI 0 "nonimmediate_operand" "")
-	(unsigned_fix:SDI (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+	(unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
 })
 
-(define_expand "floatditf2"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "")
-	(float:TF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "floatdi<mode>2"
+  [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
+	(float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "floatuns<mode>tf2"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "")
-	(unsigned_float:TF (match_operand:SDI 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "floatuns<SDI:mode><IEEE128:mode>2"
+  [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
+	(unsigned_float:IEEE128 (match_operand:SDI 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
 })
 
 (define_expand "neg<mode>2"
-  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
-	(neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(neg:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "FLOAT128_IEEE_P (<MODE>mode)
    || (FLOAT128_IBM_P (<MODE>mode)
        && TARGET_HARD_FLOAT
@@ -6752,7 +6781,14 @@ (define_expand "neg<mode>2"
   if (FLOAT128_IEEE_P (<MODE>mode))
     {
       if (TARGET_FLOAT128)
-	emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1]));
+	{
+	  if (<MODE>mode == TFmode)
+	    emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
+	  else if (<MODE>mode == KFmode)
+	    emit_insn (gen_ieee_128bit_vsx_negkf2 (operands[0], operands[1]));
+	  else
+	    gcc_unreachable ();
+	}
       else
 	{
 	  rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
@@ -6767,9 +6803,9 @@ (define_expand "neg<mode>2"
     }
 }")
 
-(define_insn "negtf2_internal"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=d")
-	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
+(define_insn "neg<mode>2_internal"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d")
+	(neg:IBM128 (match_operand:IBM128 1 "gpc_reg_operand" "d")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
   "*
 {
@@ -6782,8 +6818,8 @@ (define_insn "negtf2_internal"
    (set_attr "length" "8")])
 
 (define_expand "abs<mode>2"
-  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
-	(abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(abs:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "FLOAT128_IEEE_P (<MODE>mode)
    || (FLOAT128_IBM_P (<MODE>mode)
        && TARGET_HARD_FLOAT
@@ -6796,7 +6832,12 @@ (define_expand "abs<mode>2"
     {
       if (TARGET_FLOAT128)
 	{
-	  emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1]));
+	  if (<MODE>mode == TFmode)
+	    emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
+	  else if (<MODE>mode == KFmode)
+	    emit_insn (gen_ieee_128bit_vsx_abskf2 (operands[0], operands[1]));
+	  else
+	    FAIL;
 	  DONE;
 	}
       else
@@ -6804,22 +6845,26 @@ (define_expand "abs<mode>2"
     }
 
   label = gen_label_rtx ();
-  if (TARGET_E500_DOUBLE)
+  if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
     {
       if (flag_finite_math_only && !flag_trapping_math)
 	emit_insn (gen_spe_abstf2_tst (operands[0], operands[1], label));
       else
 	emit_insn (gen_spe_abstf2_cmp (operands[0], operands[1], label));
     }
-  else
+  else if (<MODE>mode == TFmode)
     emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
+  else if (<MODE>mode == TFmode)
+    emit_insn (gen_absif2_internal (operands[0], operands[1], label));
+  else
+    FAIL;
   emit_label (label);
   DONE;
 }")
 
-(define_expand "abstf2_internal"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(match_operand:TF 1 "gpc_reg_operand" ""))
+(define_expand "abs<mode>2_internal"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "")
+	(match_operand:IBM128 1 "gpc_reg_operand" ""))
    (set (match_dup 3) (match_dup 5))
    (set (match_dup 5) (abs:DF (match_dup 5)))
    (set (match_dup 4) (compare:CCFP (match_dup 3) (match_dup 5)))
@@ -6827,8 +6872,7 @@ (define_expand "abstf2_internal"
 			   (label_ref (match_operand 2 "" ""))
 			   (pc)))
    (set (match_dup 6) (neg:DF (match_dup 6)))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
    && TARGET_LONG_DOUBLE_128"
   "
 {
@@ -6836,8 +6880,8 @@ (define_expand "abstf2_internal"
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   operands[3] = gen_reg_rtx (DFmode);
   operands[4] = gen_reg_rtx (CCFPmode);
-  operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
-  operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+  operands[5] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
+  operands[6] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
 }")
 
 \f
@@ -6870,14 +6914,14 @@ (define_expand "ieee_128bit_negative_zer
 ;; neg/abs to create the constant just once.
 
 (define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (clobber (match_scratch:V16QI 2 "=v"))]
-  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "TARGET_FLOAT128"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
-		   (neg:TFIFKF (match_dup 1)))
+		   (neg:IEEE128 (match_dup 1)))
 	      (use (match_dup 2))])]
 {
   if (GET_CODE (operands[2]) == SCRATCH)
@@ -6890,8 +6934,8 @@ (define_insn_and_split "ieee_128bit_vsx_
    (set_attr "type" "vecsimple")])
 
 (define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (use (match_operand:V16QI 2 "register_operand" "=v"))]
   "TARGET_FLOAT128"
   "xxlxor %x0,%x1,%x2"
@@ -6899,14 +6943,14 @@ (define_insn "*ieee_128bit_vsx_neg<mode>
 
 ;; IEEE 128-bit absolute value
 (define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (clobber (match_scratch:V16QI 2 "=v"))]
   "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
-		   (abs:TFIFKF (match_dup 1)))
+		   (abs:IEEE128 (match_dup 1)))
 	      (use (match_dup 2))])]
 {
   if (GET_CODE (operands[2]) == SCRATCH)
@@ -6919,8 +6963,8 @@ (define_insn_and_split "ieee_128bit_vsx_
    (set_attr "type" "vecsimple")])
 
 (define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (use (match_operand:V16QI 2 "register_operand" "=v"))]
   "TARGET_FLOAT128"
   "xxlandc %x0,%x1,%x2"
@@ -6928,16 +6972,16 @@ (define_insn "*ieee_128bit_vsx_abs<mode>
 
 ;; IEEE 128-bit negative absolute value
 (define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF
-	 (abs:TFIFKF
-	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128
+	 (abs:IEEE128
+	  (match_operand:IEEE128 1 "register_operand" "wa"))))
    (clobber (match_scratch:V16QI 2 "=v"))]
   "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
-		   (abs:TFIFKF (match_dup 1)))
+		   (abs:IEEE128 (match_dup 1)))
 	      (use (match_dup 2))])]
 {
   if (GET_CODE (operands[2]) == SCRATCH)
@@ -6950,70 +6994,78 @@ (define_insn_and_split "*ieee_128bit_vsx
    (set_attr "type" "vecsimple")])
 
 (define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF
-	 (abs:TFIFKF
-	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128
+	 (abs:IEEE128
+	  (match_operand:IEEE128 1 "register_operand" "wa"))))
    (use (match_operand:V16QI 2 "register_operand" "=v"))]
   "TARGET_FLOAT128"
   "xxlor %x0,%x1,%x2"
   [(set_attr "type" "vecsimple")])
 
 ;; Float128 conversion functions.  These expand to library function calls.
+;; We use expand to convert from IBM double double to IEEE 128-bit
+;; and trunc for the opposite.
+(define_expand "extendiftf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+	(float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
+{
+  rs6000_expand_float128_convert (operands[0], operands[1], false);
+  DONE;
+})
 
-(define_expand "extend<FLOAT128_SFDFTF:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
-	(float_extend:IFKF
-	 (match_operand:FLOAT128_SFDFTF 1 "gpc_reg_operand" "")))]
+(define_expand "extendifkf2"
+  [(set (match_operand:KF 0 "gpc_reg_operand" "")
+	(float_extend:KF (match_operand:IF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2"
-  [(set (match_operand:FLOAT128_SFDFTF 0 "nonimmediate_operand" "")
-	(float_truncate:FLOAT128_SFDFTF
-	 (match_operand:IFKF 1 "gpc_reg_operand" "")))]
+(define_expand "extendtfkf2"
+  [(set (match_operand:KF 0 "gpc_reg_operand" "")
+	(float_extend:KF (match_operand:TF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "fix_trunc<IFKF:mode><SDI:mode>2"
-  [(set (match_operand:SDI 0 "nonimmediate_operand" "")
-	(fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))]
+(define_expand "trunciftf2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "")
+	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "fixuns_trunc<IFKF:mode><SDI:mode>2"
-  [(set (match_operand:SDI 0 "nonimmediate_operand" "")
-	(unsigned_fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))]
+(define_expand "truncifkf2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "")
+	(float_truncate:IF (match_operand:KF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], true);
+  rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "float<SDI:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
-	(float:KF (match_operand:SDI 1 "gpc_reg_operand" "")))]
+(define_expand "trunckftf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+	(float_truncate:TF (match_operand:KF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "floatuns<SDI:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
-	(unsigned_float:IFKF (match_operand:SDI 1 "gpc_reg_operand" "")))]
+(define_expand "trunctfif2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "")
+	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], true);
+  rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
@@ -10530,20 +10582,20 @@ (define_split
    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
 
 ;; Only need to compare second words if first words equal
-(define_insn "*cmptf_internal1"
+(define_insn "*cmp<mode>_internal1"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-	(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d")
-		      (match_operand:TF 2 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
+	(compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
+		      (match_operand:IBM128 2 "gpc_reg_operand" "d")))]
+  "!TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
   "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
   [(set_attr "type" "fpcompare")
    (set_attr "length" "12")])
 
-(define_insn_and_split "*cmptf_internal2"
+(define_insn_and_split "*cmp<mode>_internal2"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-	(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d")
-		      (match_operand:TF 2 "gpc_reg_operand" "d")))
+	(compare:CCFP (match_operand:IEEE128 1 "gpc_reg_operand" "d")
+		      (match_operand:IEEE128 2 "gpc_reg_operand" "d")))
     (clobber (match_scratch:DF 3 "=d"))
     (clobber (match_scratch:DF 4 "=d"))
     (clobber (match_scratch:DF 5 "=d"))
@@ -10553,7 +10605,7 @@ (define_insn_and_split "*cmptf_internal2
     (clobber (match_scratch:DF 9 "=d"))
     (clobber (match_scratch:DF 10 "=d"))
     (clobber (match_scratch:GPR 11 "=b"))]
-  "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
+  "TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
   "#"
   "&& reload_completed"
@@ -10577,10 +10629,10 @@ (define_insn_and_split "*cmptf_internal2
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
 
-  operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, hi_word);
-  operands[6] = simplify_gen_subreg (DFmode, operands[1], TFmode, lo_word);
-  operands[7] = simplify_gen_subreg (DFmode, operands[2], TFmode, hi_word);
-  operands[8] = simplify_gen_subreg (DFmode, operands[2], TFmode, lo_word);
+  operands[5] = simplify_gen_subreg (DFmode, operands[1], <MODE>mode, hi_word);
+  operands[6] = simplify_gen_subreg (DFmode, operands[1], <MODE>mode, lo_word);
+  operands[7] = simplify_gen_subreg (DFmode, operands[2], <MODE>mode, hi_word);
+  operands[8] = simplify_gen_subreg (DFmode, operands[2], <MODE>mode, lo_word);
   operands[12] = gen_label_rtx ();
   operands[13] = gen_label_rtx ();
   real_inf (&rv);
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(revision 228506)
+++ gcc/config/rs6000/rs6000-opts.h	(working copy)
@@ -80,14 +80,6 @@ enum fpu_type_t
 };
 
 
-/* Float128 support.  */
-enum float128_type_t
-{
-  FLOAT128_UNSET	= -1,	/* Initial value.  */
-  FLOAT128_NONE,		/* No __float128 support.  */
-  FLOAT128_SW			/* software __float128 support.  */
-};
-
 /* Types of costly dependences.  */
 enum rs6000_dependence_cost
 {
Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md	(revision 228545)
+++ gcc/config/rs6000/predicates.md	(working copy)
@@ -684,7 +684,7 @@ (define_predicate "indexed_or_indirect_o
 ;; Like indexed_or_indirect_operand, but also allow a GPR register if direct
 ;; moves are supported.
 (define_predicate "reg_or_indexed_operand"
-  (match_code "mem,reg")
+  (match_code "mem,reg,subreg")
 {
   if (MEM_P (op))
     return indexed_or_indirect_operand (op, mode);
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 228506)
+++ gcc/doc/extend.texi	(working copy)
@@ -929,6 +929,7 @@ examine and set these two fictitious var
 @cindex additional floating types
 @cindex @code{__float80} data type
 @cindex @code{__float128} data type
+@cindex @code{__ibm128} data type
 @cindex @code{w} floating point suffix
 @cindex @code{q} floating point suffix
 @cindex @code{W} floating point suffix
@@ -941,19 +942,39 @@ Support for additional types includes th
 add, subtract, multiply, divide; unary arithmetic operators;
 relational operators; equality operators; and conversions to and from
 integer and other floating types.  Use a suffix @samp{w} or @samp{W}
-in a literal constant of type @code{__float80} and @samp{q} or @samp{Q}
-for @code{_float128}.  You can declare complex types using the
-corresponding internal complex type, @code{XCmode} for @code{__float80}
-type and @code{TCmode} for @code{__float128} type:
+in a literal constant of type @code{__float80} or type
+@code{__ibm128}.  Use a suffix @samp{q} or @samp{Q} for @code{_float128}.
+
+On the i386, x86_64, IA-64, and HP-UX targets, you can declare complex
+types using the corresponding internal complex type, @code{XCmode} for
+@code{__float80} type and @code{TCmode} for @code{__float128} type:
 
 @smallexample
 typedef _Complex float __attribute__((mode(TC))) _Complex128;
 typedef _Complex float __attribute__((mode(XC))) _Complex80;
 @end smallexample
 
+On PowerPC Linux, Freebsd and Darwin systems, the default for
+@code{long double} is to use the IBM extended floating point format
+that uses a pair of @code{double} values to extend the precision.
+This means that the mode @code{TCmode} was already used by the
+traditional IBM long double format, and you would need to use the mode
+@code{KCmode}:
+
+@smallexample
+typedef _Complex float __attribute__((mode(KC))) _Complex128;
+@end smallexample
+
 Not all targets support additional floating-point types.  @code{__float80}
 and @code{__float128} types are supported on x86 and IA-64 targets.
-The @code{__float128} type is supported on hppa HP-UX targets.
+The @code{__float128} type is supported on hppa HP-UX.
+The @code{__float128} type is supported on PowerPC systems by default
+if the vector scalar instruction set (VSX) is enabled.
+
+On the PowerPC, @code{__ibm128} provides access to the IBM extended
+double format, and it is intended to be used by the library functions
+that handle conversions if/when long double is changed to be IEEE
+128-bit floating point.
 
 @node Half-Precision
 @section Half-Precision Floating Point
@@ -13329,6 +13350,8 @@ uint64_t __builtin_ppc_get_timebase ();
 unsigned long __builtin_ppc_mftb ();
 double __builtin_unpack_longdouble (long double, int);
 long double __builtin_pack_longdouble (double, double);
+double __builtin_unpack_ibm128 (long double, int);
+__ibm128 __builtin_pack_ibm128 (double, double);
 @end smallexample
 
 The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 228506)
+++ gcc/doc/invoke.texi	(working copy)
@@ -943,7 +943,8 @@ See RS/6000 and PowerPC Options.
 -mquad-memory-atomic -mno-quad-memory-atomic @gol
 -mcompat-align-parm -mno-compat-align-parm @gol
 -mupper-regs-df -mno-upper-regs-df -mupper-regs-sf -mno-upper-regs-sf @gol
--mupper-regs -mno-upper-regs}
+-mupper-regs -mno-upper-regs @gol
+-mfloat128 -mno-float128}
 
 @emph{RX Options}
 @gccoptlist{-m64bit-doubles  -m32bit-doubles  -fpu  -nofpu@gol
@@ -19466,6 +19467,17 @@ floating point register set, depending o
 If the @option{-mno-upper-regs} option is used, it turns off both
 @option{-mupper-regs-sf} and @option{-mupper-regs-df} options.
 
+@item -mfloat128
+@itemx -mno-float128
+@opindex mfloat128
+@opindex mno-float128
+Enable/disable the @var{__float128} keyword for IEEE 128-bit floating point
+and use software emulation for IEEE 128-bit floating point.
+
+The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7}, or
+@option{-mcpu=power8}) must be enabled to use the @option{-mfloat128}
+option.
+
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
 @opindex mfloat-gprs
Index: gcc/testsuite/gcc.target/powerpc/float128-call.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-call.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-call.c	(revision 0)
@@ -0,0 +1,27 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-O2 -mcpu=power7 -mfloat128 -mno-regnames" } */
+
+#ifndef __FLOAT128__
+#error "-mfloat128 is not supported."
+#endif
+
+#ifdef __LONG_DOUBLE_IEEE128__
+#define TYPE long double
+#define ONE  1.0L
+
+#else
+#define TYPE __float128
+#define ONE  1.0Q
+#endif
+
+/* Test to make sure vector registers are used for passing IEEE 128-bit
+   floating point values and returning them. Also make sure the 'q' suffix is
+   handled.  */
+TYPE one (void) { return ONE; }
+void store (TYPE a, TYPE *p) { *p = a; }
+
+/* { dg-final { scan-assembler "lxvd2x 34"  } } */
+/* { dg-final { scan-assembler "stxvd2x 34" } } */

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [Patch] PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-10-08 19:04   ` [Patch] PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
@ 2015-10-08 21:30     ` Joseph Myers
  2015-10-13 18:11       ` Michael Meissner
  0 siblings, 1 reply; 78+ messages in thread
From: Joseph Myers @ 2015-10-08 21:30 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

Question: what happens if you mix __float128 and __ibm128 in an arithmetic 
or conditional expression?

__float128 a;
__ibm128 b;
int x;
/* ... */
a + b;
x ? a : b;

(And likewise if one or both are the corresponding complex types.)  As I 
suggested in <https://gcc.gnu.org/ml/gcc/2014-06/msg00033.html> I think 
this would best be rejected for both C and C++ (with testcases).  That 
accords with TS 18661-3 (just published) making floating-point conversions 
undefined where neither type's set of values is a subset of the other's.

The invalid_binary_op target hook should be usable to cover the case where 
a binary operation would cause implicit conversions, but I don't see an 
existing hook that would deal with ? : expressions.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [Patch] PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-10-08 21:30     ` Joseph Myers
@ 2015-10-13 18:11       ` Michael Meissner
  2015-10-13 23:44         ` Joseph Myers
  0 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-13 18:11 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Thu, Oct 08, 2015 at 09:30:45PM +0000, Joseph Myers wrote:
> Question: what happens if you mix __float128 and __ibm128 in an arithmetic 
> or conditional expression?
> 
> __float128 a;
> __ibm128 b;
> int x;
> /* ... */
> a + b;
> x ? a : b;
> 
> (And likewise if one or both are the corresponding complex types.)  As I 
> suggested in <https://gcc.gnu.org/ml/gcc/2014-06/msg00033.html> I think 
> this would best be rejected for both C and C++ (with testcases).  That 
> accords with TS 18661-3 (just published) making floating-point conversions 
> undefined where neither type's set of values is a subset of the other's.
> 
> The invalid_binary_op target hook should be usable to cover the case where 
> a binary operation would cause implicit conversions, but I don't see an 
> existing hook that would deal with ? : expressions.

Good points. I hadn't delved into error conditions, but I will code up a target
hook not allowing inter-mixing different formats.

I believe every non-NaN value that IBM extended double supports is
representable in IEEE 754R 128-bit floating point, since IEEE has 112 bits of
mantissa plus the hidden bit, while IBM extended double has 106 bits (52 bits
of mantissa for each part plus 2 hidden bits). Even with all of the extra bits
that you can hand craft into silent/signalling NaNs, you should be able
represent those values in IEEE 128-bit floating point as similar NaNs.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [Patch] PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-10-13 18:11       ` Michael Meissner
@ 2015-10-13 23:44         ` Joseph Myers
  0 siblings, 0 replies; 78+ messages in thread
From: Joseph Myers @ 2015-10-13 23:44 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

On Tue, 13 Oct 2015, Michael Meissner wrote:

> I believe every non-NaN value that IBM extended double supports is
> representable in IEEE 754R 128-bit floating point, since IEEE has 112 bits of
> mantissa plus the hidden bit, while IBM extended double has 106 bits (52 bits
> of mantissa for each part plus 2 hidden bits). Even with all of the extra bits

No, because IBM long double can represent values with discontiguous 
mantissa bits (these are the values that 
libgcc/config/rs6000/ibm-ldouble-format describes as denormal but not 
subnormal).

> that you can hand craft into silent/signalling NaNs, you should be able
> represent those values in IEEE 128-bit floating point as similar NaNs.

The low part of a NaN in IBM long double is documented as don't-care (so 
all IBM long double NaNs are correctly converted to binary128 simply by 
converting the high part - as is also the case with zeroes).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-08-14 15:56 ` [PATCH], PowerPC IEEE 128-bit patch #7 Michael Meissner
  2015-08-14 16:24   ` Michael Meissner
@ 2015-10-23 17:24   ` Michael Meissner
  2015-10-23 17:30     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01 Michael Meissner
                       ` (19 more replies)
  1 sibling, 20 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:24 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

David asked me to try and break patch #7 into smaller bite sized chunks. I have
broken this into roughly 16 parts. These are the same patches that I submitted
for patch #7 (revised), just broken up.  There is one additional patch in this
selection, to restrict __float128 and IBM extended double from being combined
in an expression.

I have done bootstraps with no regressions on both a little endian power8
system and a big endian power7 system.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
@ 2015-10-23 17:30     ` Michael Meissner
  2015-10-29 14:28       ` David Edelsohn
  2015-10-23 17:31     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #02 Michael Meissner
                       ` (18 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:30 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 1046 bytes --]

This patch is the rs6000.h changes. It makes the IEEE 128-bit floating point
type that can go in vector registers a 'vector' type, so that the address code
in rs6000.c that determines whether to use VSX addressing works. In addition, I
made IEEE 128-bit floating point tie with vectors and not with other scalar
floats.

I have built the compiler with this patch applied, and run bootstrap and
regression tests with all of the patches installed.  Is it ok to install on the
trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Add IEEE 128-bit
	floating point modes that can go in vector registers.
	(MODES_TIEABLE_P): Move tests for vector modes before tests for
	scalar floating point, so that IEEE 128-bit floating point that
	can go in vector registers bind with vectors and not FP.
	(struct rs6000_args): Add libcall field.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07c --]
[-- Type: text/plain, Size: 2455 bytes --]

Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 229182)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1217,11 +1217,16 @@ enum data_align { align_abi, align_opt, 
 	 ((MODE) == V4SFmode		\
 	  || (MODE) == V2DFmode)	\
 
-#define ALTIVEC_VECTOR_MODE(MODE)	\
-	 ((MODE) == V16QImode		\
-	  || (MODE) == V8HImode		\
-	  || (MODE) == V4SFmode		\
-	  || (MODE) == V4SImode)
+/* Note KFmode and possibly TFmode (i.e. IEEE 128-bit floating point) are not
+   really a vector, but we want to treat it as a vector for moves, and
+   such.  */
+
+#define ALTIVEC_VECTOR_MODE(MODE)					\
+  ((MODE) == V16QImode							\
+   || (MODE) == V8HImode						\
+   || (MODE) == V4SFmode						\
+   || (MODE) == V4SImode						\
+   || FLOAT128_VECTOR_P (MODE))
 
 #define ALTIVEC_OR_VSX_VECTOR_MODE(MODE)				\
   (ALTIVEC_VECTOR_MODE (MODE) || VSX_VECTOR_MODE (MODE)			\
@@ -1248,12 +1253,19 @@ enum data_align { align_abi, align_opt, 
 
    PTImode cannot tie with other modes because PTImode is restricted to even
    GPR registers, and TImode can go in any GPR as well as VSX registers (PR
-   57744).  */
+   57744).
+
+   Altivec/VSX vector tests were moved ahead of scalar float mode, so that IEEE
+   128-bit floating point on VSX systems ties with other vectors.  */
 #define MODES_TIEABLE_P(MODE1, MODE2)		\
   ((MODE1) == PTImode				\
    ? (MODE2) == PTImode				\
    : (MODE2) == PTImode				\
    ? 0						\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
+   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
+   ? 0						\
    : SCALAR_FLOAT_MODE_P (MODE1)		\
    ? SCALAR_FLOAT_MODE_P (MODE2)		\
    : SCALAR_FLOAT_MODE_P (MODE2)		\
@@ -1266,10 +1278,6 @@ enum data_align { align_abi, align_opt, 
    ? SPE_VECTOR_MODE (MODE2)			\
    : SPE_VECTOR_MODE (MODE2)			\
    ? 0						\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE1)		\
-   ? ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   : ALTIVEC_OR_VSX_VECTOR_MODE (MODE2)		\
-   ? 0						\
    : 1)
 
 /* Post-reload, we can't use any new AltiVec registers, as we already
@@ -1801,6 +1809,7 @@ typedef struct rs6000_args
 				   GPR space (darwin64) */
   int named;			/* false for varargs params */
   int escapes;			/* if function visible outside tu */
+  int libcall;			/* If this is a compiler generated call.  */
 } CUMULATIVE_ARGS;
 
 /* Initialize a variable CUM of type CUMULATIVE_ARGS

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #02
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
  2015-10-23 17:30     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01 Michael Meissner
@ 2015-10-23 17:31     ` Michael Meissner
  2015-10-29 14:29       ` David Edelsohn
  2015-10-23 17:35     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #03 Michael Meissner
                       ` (17 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:31 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 2303 bytes --]

This patch changes the switch from -mfloat128-software and -mfloat128-none to
be a binary switch, -mfloat128 and -mno-float128.  It also provides some of the
basic setup for IEEE types.  It also removes code I had put in a previous patch
that doesn't allow IFmode/KFmode to go in any register if -mno-float128 (this
causes some reload problems).

I have built the compiler with this patch and subpatch #1 installed.  I have
built the compiler with all 16 subpatches and had no regressions.  Is this
patch ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.opt (-mfloat128-*): Delete -mfloat128-none
	and -mfloat128-software switches.  Replace them with a binary
	-mfloat128 switch.
	(-mfloat128): Likewise.

	* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow
	128-bit floating point types in GPRs, even if the appropriate
	option enabling the type was not used.
	(rs6000_debug_reg_global): Remove -mfloat128-{software,none}
	debugging.
	(rs6000_setup_reg_addr_masks): Do not allow pre-increment and
	pre-decrement on IEEE 128-bit floating point values.
	(rs6000_init_hard_regno_mode_ok): Change test for whether TFmode
	is IEEE 128-bit floating point.
	(rs6000_init_hard_regno_mode_ok): Add reload handlers for IEEE
	128-bit floating point types that can go in vector registers.
	(rs6000_option_override_internal): Change -mfloat128-none and
	-mfloat128-software to -mfloat128, and move code to be near other
	VSX option handling.
	(rs6000_option_override_internal): Disable -mfloat128 if we don't
	have the Altivec ABI.
	(rs6000_init_builtins): Don't make TFmode use either IFmode or
	KFmode floating point nodes. Instead, have three separate nodes.
	(rs6000_scalar_mode_supported_p): Add support for IFmode to allow
	eventually moving the long double default to IEEE 128-bit floating
	point.
	(rs6000_opt_masks): Add -mfloat128.
	(struct rs6000_opt_var): Fix typo in comment.

	* config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add -mfloat128 as
	an option that can be turned on via -mcpu=<xxx>.

	* config/rs6000/rs6000-opts.h (enum float128_type_t): Delete, no
	longer used.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07d --]
[-- Type: text/plain, Size: 12057 bytes --]

Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 229182)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -601,18 +601,6 @@ moptimize-swaps
 Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
 Analyze and remove doubleword swaps from VSX computations.
 
-mfloat128-
-Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save
--mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used.
-
-Enum
-Name(float128_type_t) Type(enum float128_type_t)
-
-EnumValue
-Enum(float128_type_t) String(none) Value(FLOAT128_NONE)
-
-EnumValue
-Enum(float128_type_t) String(software) Value(FLOAT128_SW)
-
-EnumValue
-Enum(float128_type_t) String(sw) Value(FLOAT128_SW)
+mfloat128
+Target Report Mask(FLOAT128) Var(rs6000_isa_flags)
+Enable/disable IEEE 128-bit floating point via the __float128 keyword.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229182)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1772,16 +1772,6 @@ rs6000_hard_regno_mode_ok (int regno, ma
 	    && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO)
 	    && ((regno & 1) == 0));
 
-  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
-     types from going in any registers.  Similarly if __float128 is not
-     supported, don't allow __float128/__ibm128 types.  */
-  if (!TARGET_LONG_DOUBLE_128
-      && (mode == TFmode || mode == KFmode || mode == IFmode))
-    return false;
-
-  if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
-    return false;
-
   /* VSX registers that overlap the FPR registers are larger than for non-VSX
      implementations.  Don't allow an item to be split between a FP register
      and an Altivec register.  Allow TImode in all VSX registers if the user
@@ -2055,7 +2045,6 @@ rs6000_debug_reg_global (void)
   const char *trace_str;
   const char *abi_str;
   const char *cmodel_str;
-  const char *float128_str;
   struct cl_target_option cl_opts;
 
   /* Modes we want tieable information on.  */
@@ -2421,15 +2410,6 @@ rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_S, "e500_double",
 	   (TARGET_E500_DOUBLE ? "true" : "false"));
 
-  switch (TARGET_FLOAT128)
-    {
-    case FLOAT128_NONE:	float128_str = "none";		break;
-    case FLOAT128_SW:	float128_str = "software";	break;
-    default:		float128_str = "unknown";	break;
-    }
-
-  fprintf (stderr, DEBUG_FMT_S, "float128", float128_str);
-
   if (TARGET_LINK_STACK)
     fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
 
@@ -2512,6 +2492,7 @@ rs6000_setup_reg_addr_masks (void)
 		  && (rc == RELOAD_REG_GPR || rc == RELOAD_REG_FPR)
 		  && GET_MODE_SIZE (m2) <= 8
 		  && !VECTOR_MODE_P (m2)
+		  && !FLOAT128_VECTOR_P (m2)
 		  && !COMPLEX_MODE_P (m2)
 		  && !indexed_only_p
 		  && !(TARGET_E500_DOUBLE && GET_MODE_SIZE (m2) == 8))
@@ -2657,6 +2638,20 @@ rs6000_init_hard_regno_mode_ok (bool glo
       align32 = 128;
     }
 
+  /* KF mode (IEEE 128-bit in VSX registers).  We do not have arithmetic, so
+     only set the memory modes.  Include TFmode if -mabi=ieeelongdouble.  */
+  if (TARGET_FLOAT128)
+    {
+      rs6000_vector_mem[KFmode] = VECTOR_VSX;
+      rs6000_vector_align[KFmode] = 128;
+
+      if (FLOAT128_IEEE_P (TFmode))
+	{
+	  rs6000_vector_mem[TFmode] = VECTOR_VSX;
+	  rs6000_vector_align[TFmode] = 128;
+	}
+    }
+
   /* V2DF mode, VSX only.  */
   if (TARGET_VSX)
     {
@@ -2850,7 +2845,7 @@ rs6000_init_hard_regno_mode_ok (bool glo
   if (TARGET_FLOAT128)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;	/* KFmode  */
-      if (rs6000_ieeequad)
+      if (FLOAT128_IEEE_P (TFmode))
 	rs6000_constraints[RS6000_CONSTRAINT_wp] = VSX_REGS;	/* TFmode  */
     }
 
@@ -2873,6 +2868,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_di_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_di_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_di_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_di_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_di_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_di_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_di_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_di_store;
@@ -2880,6 +2877,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_di_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_di_load;
 
+	  if (FLOAT128_IEEE_P (TFmode))
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_di_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_di_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -2933,6 +2936,8 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[V4SFmode].reload_load   = CODE_FOR_reload_v4sf_si_load;
 	  reg_addr[V2DFmode].reload_store  = CODE_FOR_reload_v2df_si_store;
 	  reg_addr[V2DFmode].reload_load   = CODE_FOR_reload_v2df_si_load;
+	  reg_addr[KFmode].reload_store    = CODE_FOR_reload_kf_si_store;
+	  reg_addr[KFmode].reload_load     = CODE_FOR_reload_kf_si_load;
 	  reg_addr[DFmode].reload_store    = CODE_FOR_reload_df_si_store;
 	  reg_addr[DFmode].reload_load     = CODE_FOR_reload_df_si_load;
 	  reg_addr[DDmode].reload_store    = CODE_FOR_reload_dd_si_store;
@@ -2940,6 +2945,12 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  reg_addr[SFmode].reload_store    = CODE_FOR_reload_sf_si_store;
 	  reg_addr[SFmode].reload_load     = CODE_FOR_reload_sf_si_load;
 
+	  if (FLOAT128_IEEE_P (TFmode))
+	    {
+	      reg_addr[TFmode].reload_store = CODE_FOR_reload_tf_si_store;
+	      reg_addr[TFmode].reload_load  = CODE_FOR_reload_tf_si_load;
+	    }
+
 	  /* Only provide a reload handler for SDmode if lfiwzx/stfiwx are
 	     available.  */
 	  if (TARGET_NO_SDMODE_STACK)
@@ -3695,13 +3706,6 @@ rs6000_option_override_internal (bool gl
       && optimize >= 3)
     rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN;
 
-  /* Set the appropriate IEEE 128-bit floating option.  Do not enable float128
-     support by default until the libgcc support is added.  */
-  if (TARGET_FLOAT128 == FLOAT128_UNSET)
-    TARGET_FLOAT128 = FLOAT128_NONE;
-  else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX)
-    error ("-mfloat128-software requires VSX support");
-
   /* Set -mallow-movmisalign to explicitly on if we have full ISA 2.07
      support. If we only have ISA 2.06 support, and the user did not specify
      the switch, leave it set to -1 so the movmisalign patterns are enabled,
@@ -3741,6 +3745,15 @@ rs6000_option_override_internal (bool gl
 	}
     }
 
+  /* __float128 requires VSX support.  */
+  if (TARGET_FLOAT128 && !TARGET_VSX)
+    {
+      if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) != 0)
+	error ("-mfloat128 requires VSX support");
+
+      rs6000_isa_flags &= ~OPTION_MASK_FLOAT128;
+    }
+
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
 
@@ -3821,7 +3834,8 @@ rs6000_option_override_internal (bool gl
      unless the altivec ABI was set.  This is set by default for 64-bit, but
      not for 32-bit.  */
   if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
-    rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC)
+    rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC
+			   | OPTION_MASK_FLOAT128)
 			  & ~rs6000_isa_flags_explicit);
 
   /* Enable Altivec ABI for AIX -maltivec.  */
@@ -14421,8 +14435,6 @@ rs6000_init_builtins (void)
   tree tdecl;
   tree ftype;
   machine_mode mode;
-  machine_mode ieee128_mode;
-  machine_mode ibm128_mode;
 
   if (TARGET_DEBUG_BUILTIN)
     fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n",
@@ -14495,26 +14507,24 @@ rs6000_init_builtins (void)
      TFmode will be either IEEE 128-bit floating point or the IBM double-double
      format that uses a pair of doubles, depending on the switches and
      defaults.  */
-  if (TARGET_IEEEQUAD)
-    {
-      ieee128_mode = TFmode;
-      ibm128_mode = IFmode;
-    }
-  else
+  if (TARGET_FLOAT128)
     {
-      ieee128_mode = KFmode;
-      ibm128_mode = TFmode;
-    }
+      ibm128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ibm128_float_type_node) = 128;
+      layout_type (ibm128_float_type_node);
+      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+
+      ieee128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ieee128_float_type_node) = 128;
+      layout_type (ieee128_float_type_node);
+      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
 
-  ieee128_float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (ieee128_float_type_node) = 128;
-  layout_type (ieee128_float_type_node);
-  SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode);
+      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+					      "__float128");
 
-  ibm128_float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (ibm128_float_type_node) = 128;
-  layout_type (ibm128_float_type_node);
-  SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode);
+      lang_hooks.types.register_builtin_type (ibm128_float_type_node,
+					      "__ibm128");
+    }
 
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
@@ -33093,8 +33103,8 @@ rs6000_scalar_mode_supported_p (machine_
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
-  else if (mode == KFmode)
-    return TARGET_FLOAT128;
+  else if (TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+    return true;
   else
     return default_scalar_mode_supported_p (mode);
 }
@@ -33205,6 +33215,7 @@ static struct rs6000_opt_mask const rs60
   { "dlmzb",			OPTION_MASK_DLMZB,		false, true  },
   { "efficient-unaligned-vsx",	OPTION_MASK_EFFICIENT_UNALIGNED_VSX,
 								false, true  },
+  { "float128",			OPTION_MASK_FLOAT128,		false, true  },
   { "fprnd",			OPTION_MASK_FPRND,		false, true  },
   { "hard-dfp",			OPTION_MASK_DFP,		false, true  },
   { "htm",			OPTION_MASK_HTM,		false, true  },
@@ -33283,7 +33294,7 @@ static struct rs6000_opt_mask const rs60
 struct rs6000_opt_var {
   const char *name;		/* option name */
   size_t global_offset;		/* offset of the option in global_options.  */
-  size_t target_offset;		/* offset of the option in target optiosn.  */
+  size_t target_offset;		/* offset of the option in target options.  */
 };
 
 static struct rs6000_opt_var const rs6000_opt_vars[] =
Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 229182)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -44,6 +44,7 @@
 #define ISA_2_6_MASKS_SERVER	(ISA_2_5_MASKS_SERVER			\
 				 | OPTION_MASK_POPCNTD			\
 				 | OPTION_MASK_ALTIVEC			\
+				 | OPTION_MASK_FLOAT128			\
 				 | OPTION_MASK_VSX			\
 				 | OPTION_MASK_UPPER_REGS_DF)
 
@@ -80,6 +81,7 @@
 				 | OPTION_MASK_DIRECT_MOVE		\
 				 | OPTION_MASK_DLMZB			\
 				 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX	\
+				 | OPTION_MASK_FLOAT128			\
 				 | OPTION_MASK_FPRND			\
 				 | OPTION_MASK_HTM			\
 				 | OPTION_MASK_ISEL			\
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(revision 229182)
+++ gcc/config/rs6000/rs6000-opts.h	(working copy)
@@ -80,14 +80,6 @@ enum fpu_type_t
 };
 
 
-/* Float128 support.  */
-enum float128_type_t
-{
-  FLOAT128_UNSET	= -1,	/* Initial value.  */
-  FLOAT128_NONE,		/* No __float128 support.  */
-  FLOAT128_SW			/* software __float128 support.  */
-};
-
 /* Types of costly dependences.  */
 enum rs6000_dependence_cost
 {

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #03
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
  2015-10-23 17:30     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01 Michael Meissner
  2015-10-23 17:31     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #02 Michael Meissner
@ 2015-10-23 17:35     ` Michael Meissner
  2015-10-29 14:29       ` David Edelsohn
  2015-10-23 17:38     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04 Michael Meissner
                       ` (16 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:35 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 817 bytes --]

This patch defines 3 macros to tell the user whether -mfloat128 is enabled or
not, and whether long double is IBM extended double or IEEE 128-bit floating
point.

I have built the compiler with this patch and the previous subpatches (1 and
2).  I have bootstrapped the compiler with all 16 subpatches installed, and
there were no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
	__FLOAT128__ if -mfloat128. Define __LONG_DOUBLE_IEEE128__ if long
	double is IEEE 128-bit. Define __LONG_DOUBLE_IBM128__ if long
	double is IBM extended double.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07e --]
[-- Type: text/plain, Size: 833 bytes --]

Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(revision 229182)
+++ gcc/config/rs6000/rs6000-c.c	(working copy)
@@ -408,6 +408,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
+  if (TARGET_FLOAT128)
+    builtin_define ("__FLOAT128__");
 
   if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM)
     {
@@ -481,6 +483,11 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
     {
       builtin_define ("__LONG_DOUBLE_128__");
       builtin_define ("__LONGDOUBLE128");
+
+      if (TARGET_IEEEQUAD)
+	builtin_define ("__LONG_DOUBLE_IEEE128__");
+      else
+	builtin_define ("__LONG_DOUBLE_IBM128__");
     }
 
   switch (TARGET_CMODEL)

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (2 preceding siblings ...)
  2015-10-23 17:35     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #03 Michael Meissner
@ 2015-10-23 17:38     ` Michael Meissner
  2015-10-23 20:24       ` Michael Meissner
  2015-10-29 14:29       ` David Edelsohn
  2015-10-23 17:39     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 Michael Meissner
                       ` (15 subsequent siblings)
  19 siblings, 2 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:38 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

This patch allows SUBREG's for the reg_or_indexed_operand, which is used when
you have an integral value in a float/vector register, and you want to move the
value (either via direct move on power8, or via store).

I have built the compiler with this patch and the previous subpatches (1-3).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/predicates.md (reg_or_indexed_operand): Allow
	SUBREGs.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (3 preceding siblings ...)
  2015-10-23 17:38     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04 Michael Meissner
@ 2015-10-23 17:39     ` Michael Meissner
  2015-10-23 18:08       ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 (patch included) Michael Meissner
  2015-10-29 14:33       ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 David Edelsohn
  2015-10-23 17:44     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06 Michael Meissner
                       ` (14 subsequent siblings)
  19 siblings, 2 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:39 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

This patch prevents the compiler from calling the IEEE 128-bit emulation
functions with the vector value in both GPRs and vector registers due to the
fact that the library function did not have a prototype.

I have built the compiler with this patch and the previous subpatches (1-4).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (init_cumulative_args): Initialize
	libcall field in CUMULATIVE_ARGS.
	(rs6000_function_arg): Treat library functions as if they had
	prototypes to prevent IEEE 128-bit support functions from passing
	arguments in both GPRs and vector registers.
	(rs6000_arg_partial_bytes): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (4 preceding siblings ...)
  2015-10-23 17:39     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 Michael Meissner
@ 2015-10-23 17:44     ` Michael Meissner
  2015-10-29 14:36       ` David Edelsohn
  2015-10-23 17:45     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07 Michael Meissner
                       ` (13 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:44 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 989 bytes --]

This patch sets up all of the emulation functions.

I have built the compiler with this patch and the previous subpatches (1-4).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (rs6000_init_libfuncs): Split libfunc
	setup into 3 functions: init_float128_ibm, init_float128_ieee, and
	rs6000_init_libfuncs. If -mfloat128, add IFmode functions for all
	of the traditional names that TFmode uses for handling IEEE
	extended double. If -mfloat128, add KFmode functions for all of
	the emulation functions. If -mabi=ieeelongdouble and -mfloat128,
	make TFmode use the same emulation functions as KFmode.
	(init_float128_ibm): Likewise.
	(init_float128_ieee): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07h --]
[-- Type: text/plain, Size: 10870 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229190)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -16036,75 +16036,184 @@ rs6000_common_init_builtins (void)
     }
 }
 
+/* Set up AIX/Darwin/64-bit Linux quad floating point routines.  */
 static void
-rs6000_init_libfuncs (void)
+init_float128_ibm (machine_mode mode)
 {
-  if (!TARGET_IEEEQUAD)
-      /* AIX/Darwin/64-bit Linux quad floating point routines.  */
-    if (!TARGET_XL_COMPAT)
-      {
-	set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
-	set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
-	set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
+  if (!TARGET_XL_COMPAT)
+    {
+      set_optab_libfunc (add_optab, mode, "__gcc_qadd");
+      set_optab_libfunc (sub_optab, mode, "__gcc_qsub");
+      set_optab_libfunc (smul_optab, mode, "__gcc_qmul");
+      set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv");
 
-	if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
-	  {
-	    set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
-	    set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
-	    set_optab_libfunc (ne_optab, TFmode, "__gcc_qne");
-	    set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt");
-	    set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
-	    set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
-	    set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
-
-	    set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
-	    set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
-	    set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos");
-	    set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod");
-	    set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi");
-	    set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou");
-	    set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
-	    set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
-	  }
+      if (!(TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)))
+	{
+	  set_optab_libfunc (neg_optab, mode, "__gcc_qneg");
+	  set_optab_libfunc (eq_optab, mode, "__gcc_qeq");
+	  set_optab_libfunc (ne_optab, mode, "__gcc_qne");
+	  set_optab_libfunc (gt_optab, mode, "__gcc_qgt");
+	  set_optab_libfunc (ge_optab, mode, "__gcc_qge");
+	  set_optab_libfunc (lt_optab, mode, "__gcc_qlt");
+	  set_optab_libfunc (le_optab, mode, "__gcc_qle");
 
-	if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
-	  set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
-      }
-    else
-      {
-	set_optab_libfunc (add_optab, TFmode, "_xlqadd");
-	set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
-	set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
-	set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
-      }
+	  set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq");
+	  set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq");
+	  set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos");
+	  set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod");
+	  set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi");
+	  set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou");
+	  set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq");
+	  set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq");
+	}
+
+      if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
+	set_optab_libfunc (unord_optab, mode, "__gcc_qunord");
+    }
   else
     {
-      /* 32-bit SVR4 quad floating point routines.  */
+      set_optab_libfunc (add_optab, mode, "_xlqadd");
+      set_optab_libfunc (sub_optab, mode, "_xlqsub");
+      set_optab_libfunc (smul_optab, mode, "_xlqmul");
+      set_optab_libfunc (sdiv_optab, mode, "_xlqdiv");
+    }
+
+  /* Add various conversions for IFmode to use the traditional TFmode
+     names.  */
+  if (mode == IFmode)
+    {
+      set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdtf2");
+      set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddtf2");
+      set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunctftd2");
+      set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunctfsd2");
+      set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunctfdd2");
+      set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtdtf2");
+
+      if (TARGET_POWERPC64)
+	{
+	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixtfti");
+	  set_conv_libfunc (ufix_optab, TImode, mode, "__fixunstfti");
+	  set_conv_libfunc (sfloat_optab, mode, TImode, "__floattitf");
+	  set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntitf");
+	}
+    }
+}
+
+/* Set up IEEE 128-bit floating point routines.  Use different names if the
+   arguments can be passed in a vector register.  The historical PowerPC
+   implementation of IEEE 128-bit floating point used _q_<op> for the names, so
+   continue to use that if we aren't using vector registers to pass IEEE
+   128-bit floating point.  */
+
+static void
+init_float128_ieee (machine_mode mode)
+{
+  if (FLOAT128_VECTOR_P (mode))
+    {
+      set_optab_libfunc (add_optab, mode, "__addkf3");
+      set_optab_libfunc (sub_optab, mode, "__subkf3");
+      set_optab_libfunc (neg_optab, mode, "__negkf2");
+      set_optab_libfunc (smul_optab, mode, "__mulkf3");
+      set_optab_libfunc (sdiv_optab, mode, "__divkf3");
+      set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2");
+      set_optab_libfunc (abs_optab, mode, "__abstkf2");
 
-      set_optab_libfunc (add_optab, TFmode, "_q_add");
-      set_optab_libfunc (sub_optab, TFmode, "_q_sub");
-      set_optab_libfunc (neg_optab, TFmode, "_q_neg");
-      set_optab_libfunc (smul_optab, TFmode, "_q_mul");
-      set_optab_libfunc (sdiv_optab, TFmode, "_q_div");
+      set_optab_libfunc (eq_optab, mode, "__eqkf2");
+      set_optab_libfunc (ne_optab, mode, "__nekf2");
+      set_optab_libfunc (gt_optab, mode, "__gtkf2");
+      set_optab_libfunc (ge_optab, mode, "__gekf2");
+      set_optab_libfunc (lt_optab, mode, "__ltkf2");
+      set_optab_libfunc (le_optab, mode, "__lekf2");
+      set_optab_libfunc (unord_optab, mode, "__unordkf2");
+      set_optab_libfunc (cmp_optab, mode, "__cmpokf2");		/* fcmpo */
+      set_optab_libfunc (ucmp_optab, mode, "__cmpukf2");	/* fcmpu */
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2");
+      set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2");
+
+      set_conv_libfunc (sext_optab, mode, IFmode, "__extendtfkf2");
+      if (mode != TFmode && FLOAT128_IBM_P (TFmode))
+	set_conv_libfunc (sext_optab, mode, TFmode, "__extendtfkf2");
+
+      set_conv_libfunc (trunc_optab, IFmode, mode, "__trunckftf2");
+      if (mode != TFmode && FLOAT128_IBM_P (TFmode))
+	set_conv_libfunc (trunc_optab, TFmode, mode, "__trunckftf2");
+
+      set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdkf2");
+      set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddkf2");
+      set_conv_libfunc (trunc_optab, mode, TDmode, "__dpd_trunckftd2");
+      set_conv_libfunc (trunc_optab, SDmode, mode, "__dpd_trunckfsd2");
+      set_conv_libfunc (trunc_optab, DDmode, mode, "__dpd_trunckfdd2");
+      set_conv_libfunc (sext_optab, TDmode, mode, "__dpd_extendtdkf2");
+
+      set_conv_libfunc (sfix_optab, SImode, mode, "__fixkfsi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "__fixunskfsi");
+      set_conv_libfunc (sfix_optab, DImode, mode, "__fixkfdi");
+      set_conv_libfunc (ufix_optab, DImode, mode, "__fixunskfdi");
+
+      set_conv_libfunc (sfloat_optab, mode, SImode, "__floatsikf");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "__floatunsikf");
+      set_conv_libfunc (sfloat_optab, mode, DImode, "__floatdikf");
+      set_conv_libfunc (ufloat_optab, mode, DImode, "__floatundikf");
+
+      if (TARGET_POWERPC64)
+	{
+	  set_conv_libfunc (sfix_optab, TImode, mode, "__fixkfti");
+	  set_conv_libfunc (ufix_optab, TImode, mode, "__fixunskfti");
+	  set_conv_libfunc (sfloat_optab, mode, TImode, "__floattikf");
+	  set_conv_libfunc (ufloat_optab, mode, TImode, "__floatuntikf");
+	}
+    }
+
+  else
+    {
+      set_optab_libfunc (add_optab, mode, "_q_add");
+      set_optab_libfunc (sub_optab, mode, "_q_sub");
+      set_optab_libfunc (neg_optab, mode, "_q_neg");
+      set_optab_libfunc (smul_optab, mode, "_q_mul");
+      set_optab_libfunc (sdiv_optab, mode, "_q_div");
       if (TARGET_PPC_GPOPT)
-	set_optab_libfunc (sqrt_optab, TFmode, "_q_sqrt");
+	set_optab_libfunc (sqrt_optab, mode, "_q_sqrt");
 
-      set_optab_libfunc (eq_optab, TFmode, "_q_feq");
-      set_optab_libfunc (ne_optab, TFmode, "_q_fne");
-      set_optab_libfunc (gt_optab, TFmode, "_q_fgt");
-      set_optab_libfunc (ge_optab, TFmode, "_q_fge");
-      set_optab_libfunc (lt_optab, TFmode, "_q_flt");
-      set_optab_libfunc (le_optab, TFmode, "_q_fle");
-
-      set_conv_libfunc (sext_optab, TFmode, SFmode, "_q_stoq");
-      set_conv_libfunc (sext_optab, TFmode, DFmode, "_q_dtoq");
-      set_conv_libfunc (trunc_optab, SFmode, TFmode, "_q_qtos");
-      set_conv_libfunc (trunc_optab, DFmode, TFmode, "_q_qtod");
-      set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
-      set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
-      set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
-      set_conv_libfunc (ufloat_optab, TFmode, SImode, "_q_utoq");
+      set_optab_libfunc (eq_optab, mode, "_q_feq");
+      set_optab_libfunc (ne_optab, mode, "_q_fne");
+      set_optab_libfunc (gt_optab, mode, "_q_fgt");
+      set_optab_libfunc (ge_optab, mode, "_q_fge");
+      set_optab_libfunc (lt_optab, mode, "_q_flt");
+      set_optab_libfunc (le_optab, mode, "_q_fle");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "_q_stoq");
+      set_conv_libfunc (sext_optab, mode, DFmode, "_q_dtoq");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "_q_qtos");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "_q_qtod");
+      set_conv_libfunc (sfix_optab, SImode, mode, "_q_qtoi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "_q_qtou");
+      set_conv_libfunc (sfloat_optab, mode, SImode, "_q_itoq");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "_q_utoq");
+    }
+}
+
+static void
+rs6000_init_libfuncs (void)
+{
+  /* __float128 support.  */
+  if (TARGET_FLOAT128)
+    {
+      init_float128_ibm (IFmode);
+      init_float128_ieee (KFmode);
+    }
+
+  /* AIX/Darwin/64-bit Linux quad floating point routines.  */
+  if (TARGET_LONG_DOUBLE_128)
+    {
+      if (!TARGET_IEEEQUAD)
+	init_float128_ibm (TFmode);
+
+      /* IEEE 128-bit including 32-bit SVR4 quad floating point routines.  */
+      else
+	init_float128_ieee (TFmode);
     }
 }
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (5 preceding siblings ...)
  2015-10-23 17:44     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06 Michael Meissner
@ 2015-10-23 17:45     ` Michael Meissner
  2015-10-29 14:36       ` David Edelsohn
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09 Michael Meissner
                       ` (12 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:45 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 1167 bytes --]

This patch updates to use the unordered comparison function for IEEE 128-bit
floating point to mimic the behaviour of SFmode/DFmode using the fcmpu
instruction.

It also restructures the code to allow a future change to drop in easier.

I have built the compiler with this patch and the previous subpatches (1-6).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (rs6000_generate_compare): For IEEE
	128-bit floating point comparisons, call the unordered comparison
	function instead of the ordered comparison function.
	(rs6000_expand_float128_convert): Deal with operands that are
	memory operands. Restructure the code to use a switch statement on
	the mode. Add support for TFmode defaulting to either IBM extended
	double or IEEE 128-bit floating point. If the underlying types are
	the same, use a move instead of a conversion function.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07i --]
[-- Type: text/plain, Size: 4902 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229191)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -20098,17 +20098,18 @@ rs6000_generate_compare (rtx cmp, machin
       emit_insn (cmp);
     }
 
-  /* IEEE 128-bit support in VSX registers.  The comparison function (__cmpkf2)
-     returns 0..15 that is laid out the same way as the PowerPC CR register
-     would for a normal floating point comparison.  */
+  /* IEEE 128-bit support in VSX registers.  The comparison functions
+     (__cmpokf2 and __cmpukf2) returns 0..15 that is laid out the same way as
+     the PowerPC CR register would for a normal floating point comparison from
+     the fcmpo and fcmpu instructions.  */
   else if (FLOAT128_IEEE_P (mode))
     {
       rtx and_reg = gen_reg_rtx (SImode);
       rtx dest = gen_reg_rtx (SImode);
-      rtx libfunc = optab_libfunc (cmp_optab, mode);
+      rtx libfunc = optab_libfunc (ucmp_optab, mode);
       HOST_WIDE_INT mask_value = 0;
 
-      /* Values that __cmpkf2 returns.  */
+      /* Values that __cmpokf2/__cmpukf2 returns.  */
 #define PPC_CMP_UNORDERED	0x1		/* isnan (a) || isnan (b).  */
 #define PPC_CMP_EQUAL		0x2		/* a == b.  */
 #define PPC_CMP_GREATER_THEN	0x4		/* a > b.  */
@@ -20280,6 +20281,7 @@ rs6000_generate_compare (rtx cmp, machin
 }
 
 
+\f
 /* Expand floating point conversion to/from __float128 and __ibm128.  */
 
 void
@@ -20288,60 +20290,121 @@ rs6000_expand_float128_convert (rtx dest
   machine_mode dest_mode = GET_MODE (dest);
   machine_mode src_mode = GET_MODE (src);
   convert_optab cvt = unknown_optab;
+  bool do_move = false;
   rtx libfunc = NULL_RTX;
   rtx dest2;
 
   if (dest_mode == src_mode)
     gcc_unreachable ();
 
+  /* Eliminate memory operations.  */
+  if (MEM_P (src))
+    src = force_reg (src_mode, src);
+
+  if (MEM_P (dest))
+    {
+      rtx tmp = gen_reg_rtx (dest_mode);
+      rs6000_expand_float128_convert (tmp, src, unsigned_p);
+      rs6000_emit_move (dest, tmp, dest_mode);
+      return;
+    }
+
+  /* Convert to IEEE 128-bit floating point.  */
   if (FLOAT128_IEEE_P (dest_mode))
     {
-      if (src_mode == SFmode
-	  || src_mode == DFmode
-	  || FLOAT128_IBM_P (src_mode))
-	cvt = sext_optab;
+      switch (src_mode)
+	{
+	case DFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (src_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	case SFmode:
+	  cvt = sext_optab;
+	  break;
 
-      else if (FLOAT128_IEEE_P (src_mode))
-	emit_move_insn (dest, gen_lowpart (dest_mode, src));
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (src_mode))
+	    cvt = sext_optab;
+	  else
+	    do_move = true;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufloat_optab : sfloat_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Convert from IEEE 128-bit floating point.  */
   else if (FLOAT128_IEEE_P (src_mode))
     {
-      if (dest_mode == SFmode
-	  || dest_mode == DFmode
-	  || FLOAT128_IBM_P (dest_mode))
-	cvt = trunc_optab;
+      switch (dest_mode)
+	{
+	case DFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else if (GET_MODE_CLASS (dest_mode) == MODE_INT)
-	cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	case SFmode:
+	  cvt = trunc_optab;
+	  break;
 
-      else
-	gcc_unreachable ();
+	case KFmode:
+	case IFmode:
+	case TFmode:
+	  if (FLOAT128_IBM_P (dest_mode))
+	    cvt = trunc_optab;
+	  else
+	    do_move = true;
+	  break;
+
+	case SImode:
+	case DImode:
+	  cvt = (unsigned_p) ? ufix_optab : sfix_optab;
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
     }
 
+  /* Both IBM format.  */
+  else if (FLOAT128_IBM_P (dest_mode) && FLOAT128_IBM_P (src_mode))
+    do_move = true;
+
   else
     gcc_unreachable ();
 
-  gcc_assert (cvt != unknown_optab);
-  libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
-  gcc_assert (libfunc != NULL_RTX);
-
-  dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
-				   src_mode);
-
-  gcc_assert (dest != NULL_RTX);
-  if (!rtx_equal_p (dest, dest2))
-    emit_move_insn (dest, dest2);
+  /* Handle conversion between TFmode/KFmode.  */
+  if (do_move)
+    emit_move_insn (dest, gen_lowpart (dest_mode, src));
+
+  /* Call an external function to do the conversion.  */
+  else if (cvt != unknown_optab)
+    {
+      libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode);
+      gcc_assert (libfunc != NULL_RTX);
+
+      dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src,
+				       src_mode);
+
+      gcc_assert (dest2 != NULL_RTX);
+      if (!rtx_equal_p (dest, dest2))
+	emit_move_insn (dest, dest2);
+    }
+
+  else
+    gcc_unreachable ();
 
   return;
 }
 
+\f
 /* Emit the RTL for an sISEL pattern.  */
 
 void

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (6 preceding siblings ...)
  2015-10-23 17:45     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07 Michael Meissner
@ 2015-10-23 17:47     ` Michael Meissner
  2015-10-23 20:17       ` Joseph Myers
  2015-10-29 14:39       ` David Edelsohn
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #08 Michael Meissner
                       ` (11 subsequent siblings)
  19 siblings, 2 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:47 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 851 bytes --]

This patch is the new patch from the last submission. It sets up a hook so that
the compiler will not allow IBM extended double and IEEE 128-bit floating point
to intermix in a binary expression without using an explicit conversion.

I have built the compiler with this patch and the previous subpatches (1-8).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (TARGET_INVALID_BINARY_OP): Do not allow
	inter-mixing of IEEE 128-bit floating point with IBM extended
	double floating point.
	(rs6000_invalid_binary_op): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07k --]
[-- Type: text/plain, Size: 2001 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229193)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1677,6 +1677,9 @@ static const struct attribute_spec rs600
 
 #undef TARGET_C_MODE_FOR_SUFFIX
 #define TARGET_C_MODE_FOR_SUFFIX rs6000_c_mode_for_suffix
+
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP rs6000_invalid_binary_op
 \f
 
 /* Processor table.  */
@@ -20283,6 +20286,47 @@ rs6000_generate_compare (rtx cmp, machin
   return gen_rtx_fmt_ee (code, VOIDmode, compare_result, const0_rtx);
 }
 
+\f
+/* Return the diagnostic message string if the binary operation OP is
+   not permitted on TYPE1 and TYPE2, NULL otherwise.  */
+
+static const char*
+rs6000_invalid_binary_op (int op ATTRIBUTE_UNUSED,
+			  const_tree type1,
+			  const_tree type2)
+{
+  enum machine_mode mode1 = TYPE_MODE (type1);
+  enum machine_mode mode2 = TYPE_MODE (type2);
+
+  /* For complex modes, use the inner type.  */
+  if (COMPLEX_MODE_P (mode1))
+    mode1 = GET_MODE_INNER (mode1);
+
+  if (COMPLEX_MODE_P (mode2))
+    mode2 = GET_MODE_INNER (mode2);
+
+  /* Don't allow IEEE 754R 128-bit binary floating point and IBM extended
+     double to intermix.  */
+  if (mode1 == mode2)
+    return NULL;
+
+  if ((mode1 == KFmode && mode2 == IFmode)
+      || (mode1 == IFmode && mode2 == KFmode))
+    return N_("__float128 and __ibm128 cannot be used in the same expression");
+
+  if (TARGET_IEEEQUAD
+      && ((mode1 == IFmode && mode2 == TFmode)
+	  || (mode1 == TFmode && mode2 == IFmode)))
+    return N_("__ibm128 and long double cannot be used in the same expression");
+
+  if (!TARGET_IEEEQUAD
+      && ((mode1 == KFmode && mode2 == TFmode)
+	  || (mode1 == TFmode && mode2 == KFmode)))
+    return N_("__float128 and long double cannot be used in the same "
+	      "expression");
+
+  return NULL;
+}
 
 \f
 /* Expand floating point conversion to/from __float128 and __ibm128.  */

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #08
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (7 preceding siblings ...)
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09 Michael Meissner
@ 2015-10-23 17:47     ` Michael Meissner
  2015-10-29 14:38       ` David Edelsohn
  2015-10-23 17:52     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #10 Michael Meissner
                       ` (10 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:47 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 791 bytes --]

This patch adds support for using 'q' or 'Q' as a suffix for __float128
constants, which is compatible with the existing x86_64 implmenetation of their
__float128 support.

I have built the compiler with this patch and the previous subpatches (1-7).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (TARGET_C_MODE_FOR_SUFFIX): Define 'q'
	and 'Q' as the suffix to use for IEEE 128-bit floating point
	constants with -mfloat128.
	(rs6000_c_mode_for_suffix): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07j --]
[-- Type: text/plain, Size: 1394 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229192)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1674,6 +1674,9 @@ static const struct attribute_spec rs600
 
 #undef TARGET_OFFLOAD_OPTIONS
 #define TARGET_OFFLOAD_OPTIONS rs6000_offload_options
+
+#undef TARGET_C_MODE_FOR_SUFFIX
+#define TARGET_C_MODE_FOR_SUFFIX rs6000_c_mode_for_suffix
 \f
 
 /* Processor table.  */
@@ -33308,6 +33311,26 @@ rs6000_vector_mode_supported_p (machine_
     return false;
 }
 
+/* Target hook for c_mode_for_suffix.  */
+static machine_mode
+rs6000_c_mode_for_suffix (char suffix)
+{
+  if (TARGET_FLOAT128)
+    {
+      if (suffix == 'q' || suffix == 'Q')
+	return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+
+      /* At the moment, we are not defining a suffix for IBM extended double.
+	 If/when the default for -mabi=ieeelongdouble is changed, and we want
+	 to support __ibm128 constants in legacy library code, we may need to
+	 re-evalaute this decision.  Currently, c-lex.c only supports 'w' and
+	 'q' as machine dependent suffixes.  The x86_64 port uses 'w' for
+	 __float80 constants.  */
+    }
+
+  return VOIDmode;
+}
+
 /* Target hook for invalid_arg_for_unprototyped_fn. */
 static const char *
 invalid_arg_for_unprototyped_fn (const_tree typelist, const_tree funcdecl, const_tree val)

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #10
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (8 preceding siblings ...)
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #08 Michael Meissner
@ 2015-10-23 17:52     ` Michael Meissner
  2015-10-29 14:40       ` David Edelsohn
  2015-10-23 17:57     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #11 Michael Meissner
                       ` (9 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:52 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 1027 bytes --]

This patch is part of the support needed to properly swap IEEE 128-bit floating
point on little endian systems.  Note, you will need the rs6000.md changes for
this to become effective.

I have built the compiler with this patch and the previous subpatches (1-9).  I
have bootstrapped the compiler with all 16 subpatches installed, and there were
no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (rs6000_gen_le_vsx_permute): On little
	endian systems generate a ROTATE insn instead of VEC_SELECT for
	IEEE 128-bit floating point types that can go in vector
	registers.
	(chain_contains_only_swaps): Properly swap IEEE 128-bit floating
	point types that can go in vector registers on little endian
	PowerPC systems.
	(mark_swaps_for_removal): Likewise.
	(rs6000_analyze_swaps): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07l --]
[-- Type: text/plain, Size: 2714 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229194)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -8467,8 +8467,14 @@ rs6000_const_vec (machine_mode mode)
 rtx
 rs6000_gen_le_vsx_permute (rtx source, machine_mode mode)
 {
-  rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
-  return gen_rtx_VEC_SELECT (mode, source, par);
+  /* Use ROTATE instead of VEC_SELECT on IEEE 128-bit floating point.  */
+  if (FLOAT128_VECTOR_P (mode))
+    return gen_rtx_ROTATE (mode, source, GEN_INT (64));
+  else
+    {
+      rtx par = gen_rtx_PARALLEL (VOIDmode, rs6000_const_vec (mode));
+      return gen_rtx_VEC_SELECT (mode, source, par);
+    }
 }
 
 /* Emit a little-endian load from vector memory location SOURCE to VSX
@@ -35844,7 +35850,7 @@ chain_contains_only_swaps (swap_web_entr
 
   for (; link; link = link->next)
     {
-      if (!VECTOR_MODE_P (GET_MODE (DF_REF_REG (link->ref))))
+      if (!ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (DF_REF_REG (link->ref))))
 	continue;
 
       if (DF_REF_IS_ARTIFICIAL (link->ref))
@@ -35943,7 +35949,7 @@ mark_swaps_for_removal (swap_web_entry *
 	{
 	  /* Ignore uses for addressability.  */
 	  machine_mode mode = GET_MODE (DF_REF_REG (use));
-	  if (!VECTOR_MODE_P (mode))
+	  if (!ALTIVEC_OR_VSX_VECTOR_MODE (mode))
 	    continue;
 
 	  struct df_link *link = DF_REF_CHAIN (use);
@@ -36457,10 +36463,11 @@ rs6000_analyze_swaps (function *fun)
 		    mode = V4SImode;
 		}
 
-	      if (VECTOR_MODE_P (mode) || mode == TImode)
+	      if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
 		{
 		  insn_entry[uid].is_relevant = 1;
-		  if (mode == TImode || mode == V1TImode)
+		  if (mode == TImode || mode == V1TImode
+		      || FLOAT128_VECTOR_P (mode))
 		    insn_entry[uid].is_128_int = 1;
 		  if (DF_REF_INSN_INFO (mention))
 		    insn_entry[uid].contains_subreg
@@ -36481,13 +36488,14 @@ rs6000_analyze_swaps (function *fun)
 		 isn't sufficient to ensure we union the call into the
 		 web with the parameter setup code.  */
 	      if (mode == DImode && GET_CODE (insn) == SET
-		  && VECTOR_MODE_P (GET_MODE (SET_DEST (insn))))
+		  && ALTIVEC_OR_VSX_VECTOR_MODE (GET_MODE (SET_DEST (insn))))
 		mode = GET_MODE (SET_DEST (insn));
 
-	      if (VECTOR_MODE_P (mode) || mode == TImode)
+	      if (ALTIVEC_OR_VSX_VECTOR_MODE (mode) || mode == TImode)
 		{
 		  insn_entry[uid].is_relevant = 1;
-		  if (mode == TImode || mode == V1TImode)
+		  if (mode == TImode || mode == V1TImode
+		      || FLOAT128_VECTOR_P (mode))
 		    insn_entry[uid].is_128_int = 1;
 		  if (DF_REF_INSN_INFO (mention))
 		    insn_entry[uid].contains_subreg

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #11
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (9 preceding siblings ...)
  2015-10-23 17:52     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #10 Michael Meissner
@ 2015-10-23 17:57     ` Michael Meissner
  2015-10-29 14:42       ` David Edelsohn
  2015-10-23 17:58     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #12 Michael Meissner
                       ` (8 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:57 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 777 bytes --]

This patch changes the mangling for __float128.  I came to the conclusion that
the current code is so tangled, that it would be better to use U10__float128
rather than "e".  However, if it is felt that we should go with "e", I can go
that way as well.

I have built the compiler with this patch and the previous subpatches (1-10).
I have bootstrapped the compiler with all 16 subpatches installed, and there
were no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (rs6000_mangle_type): Use U10__float128
	for IEEE 128-bit floating point.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07m --]
[-- Type: text/plain, Size: 1082 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229196)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -30052,6 +30052,21 @@ rs6000_mangle_type (const_tree type)
   if (type == bool_int_type_node) return "U6__booli";
   if (type == bool_long_type_node) return "U6__booll";
 
+  /* Use a unique name for __float128 rather than trying to use "e" or "g". Use
+     "g" for IBM extended double, no matter whether it is long double (using
+     -mabi=ibmlongdouble) or the distinct __ibm128 type.  */
+  if (TARGET_FLOAT128)
+    {
+      if (type == ieee128_float_type_node)
+	return "U10__float128";
+
+      if (type == ibm128_float_type_node)
+	return "g";
+
+      if (type == long_double_type_node && TARGET_LONG_DOUBLE_128)
+	return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
+    }
+
   /* Mangle IBM extended float long double as `g' (__float128) on
      powerpc*-linux where long-double-64 previously was the default.  */
   if (TYPE_MAIN_VARIANT (type) == long_double_type_node

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #12
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (10 preceding siblings ...)
  2015-10-23 17:57     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #11 Michael Meissner
@ 2015-10-23 17:58     ` Michael Meissner
  2015-10-29 14:44       ` David Edelsohn
  2015-10-23 18:00     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #13 Michael Meissner
                       ` (7 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 17:58 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 2617 bytes --]

This patch is the first of two rs6000.md patches to straighten out the IFmode,
KFmode, and TFmode support.  Part of the change is to change the iterator names
to be easier to understand, using IEEE128, IBM128, and FLOAT128 as the
iterators.  This change, and the next change go through and have parallel insns
for handling IFmode and TFmode (when -mabi=ibmlongdouble) for IBM extended
double, and for handling KFmode and TFmode (when -mabi=ieeelongdouble).  The
idea is to prepare the way in GCC 7.0 to change the default for long double.

I have built the compiler with this patch and the previous subpatches (1-11).
I have bootstrapped the compiler with all 16 subpatches installed, and there
were no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.md (FLOAT128_SFDFTF): Delete iterator,
	rework IEEE 128-bit floating point insns to deal with TFmode being
	either IBM extended double or IEEE 128-bit floating point.
	(IFKF): Likewise.
	(IBM128): Update iterator to add condition that the mode is IBM
	extended double.
	(IEEE128): New iterator for IEEE 128-bit floating point.
	(TFIFKF): Rename TFIFKF iterator to FLOAT128.
	(FLOAT128): Likewise.
	(signbit<mode>2): FLOAT128_IBM_P condition test moved into IBM128
	iterator.
	(neg<mode>2): Replace TFIFKF iterator with FLOAT128. Add support
	for TFmode being IEEE 128-bit floating point. Use IEEE128 iterator
	instead of hard coding TFmode or KFmode.
	(negtf2_internal): Likewise.
	(neg<mode>2_internal): Likewise.
	(abs<mode>2): Likewise.
	(abstf2_internal): Likewise.
	(abs<mode>2_internal): Likewise.
	(ieee_128bit_neg<mode>2): Likewise.
	(ieee_128bit_neg<mode>2_internal): Likewise.
	(ieee_128bit_abs<mode>2): Likewise.
	(ieee_128bit_abs<mode>2_internal): Likewise.
	(ieee_128bit_nabs<mode>2): Likewise.
	(ieee_128bit_nabs<mode>2_internal): Likewise.
	(extendiftf2): Add explicit conversions between 128-bit floating
	point types. Drop the old conversions that had become unwieldy.
	(extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
	(extendifkf2): Likewise.
	(trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
	(extendtfkf2): Likewise.
	(fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(trunciftf2): Likewise.
	(fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
	(truncifkf2): Likewise.
	(float<SDI:mode><IFKF:mode>2): Likewise.
	(trunckftf2): Likewise.
	(floatuns<SDI:mode><IFKF:mode>2): Likewise.
	(trunctfif2): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07n --]
[-- Type: text/plain, Size: 13001 bytes --]

Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 229182)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -448,24 +448,18 @@ (define_mode_iterator RECIPF [SF DF V4SF
 ; Iterator for just SF/DF
 (define_mode_iterator SFDF [SF DF])
 
-; Iterator for float128 floating conversions
-(define_mode_iterator FLOAT128_SFDFTF [
-    (SF "TARGET_FLOAT128")
-    (DF "TARGET_FLOAT128")
-    (TF "FLOAT128_IBM_P (TFmode)")
-    (IF "TARGET_FLOAT128")])
-
-; Iterator for special 128-bit floating point.  This is for non-default
-; conversions, so TFmode is not used here.
-(define_mode_iterator IFKF [IF KF])
-
 ; Iterator for 128-bit floating point that uses the IBM double-double format
-(define_mode_iterator IBM128 [IF TF])
+(define_mode_iterator IBM128 [(IF "FLOAT128_IBM_P (IFmode)")
+			      (TF "FLOAT128_IBM_P (TFmode)")])
+
+; Iterator for 128-bit floating point that uses IEEE 128-bit float
+(define_mode_iterator IEEE128 [(KF "FLOAT128_IEEE_P (KFmode)")
+			       (TF "FLOAT128_IEEE_P (TFmode)")])
 
 ; Iterator for 128-bit floating point
-(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128")
-			      (IF "TARGET_FLOAT128")
-			      (TF "TARGET_LONG_DOUBLE_128")])
+(define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128")
+				(IF "TARGET_FLOAT128")
+				(TF "TARGET_LONG_DOUBLE_128")])
 
 ; SF/DF suffix for traditional floating instructions
 (define_mode_attr Ftrad		[(SF "s") (DF "")])
@@ -4248,8 +4242,7 @@ (define_expand "signbit<mode>2"
    	(match_dup 5))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
   	(match_dup 6))]
-  "FLOAT128_IBM_P (<MODE>mode)
-   && TARGET_HARD_FLOAT
+  "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)"
 {
   operands[2] = gen_reg_rtx (DFmode);
@@ -6735,8 +6728,8 @@ (define_expand "floatuns<mode>tf2"
 })
 
 (define_expand "neg<mode>2"
-  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
-	(neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(neg:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "FLOAT128_IEEE_P (<MODE>mode)
    || (FLOAT128_IBM_P (<MODE>mode)
        && TARGET_HARD_FLOAT
@@ -6746,7 +6739,14 @@ (define_expand "neg<mode>2"
   if (FLOAT128_IEEE_P (<MODE>mode))
     {
       if (TARGET_FLOAT128)
-	emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1]));
+	{
+	  if (<MODE>mode == TFmode)
+	    emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
+	  else if (<MODE>mode == KFmode)
+	    emit_insn (gen_ieee_128bit_vsx_negkf2 (operands[0], operands[1]));
+	  else
+	    gcc_unreachable ();
+	}
       else
 	{
 	  rtx libfunc = optab_libfunc (neg_optab, <MODE>mode);
@@ -6761,9 +6761,9 @@ (define_expand "neg<mode>2"
     }
 }")
 
-(define_insn "negtf2_internal"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=d")
-	(neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))]
+(define_insn "neg<mode>2_internal"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d")
+	(neg:IBM128 (match_operand:IBM128 1 "gpc_reg_operand" "d")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)"
   "*
 {
@@ -6776,8 +6776,8 @@ (define_insn "negtf2_internal"
    (set_attr "length" "8")])
 
 (define_expand "abs<mode>2"
-  [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "")
-	(abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))]
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(abs:FLOAT128 (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "FLOAT128_IEEE_P (<MODE>mode)
    || (FLOAT128_IBM_P (<MODE>mode)
        && TARGET_HARD_FLOAT
@@ -6790,7 +6790,12 @@ (define_expand "abs<mode>2"
     {
       if (TARGET_FLOAT128)
 	{
-	  emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1]));
+	  if (<MODE>mode == TFmode)
+	    emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
+	  else if (<MODE>mode == KFmode)
+	    emit_insn (gen_ieee_128bit_vsx_abskf2 (operands[0], operands[1]));
+	  else
+	    FAIL;
 	  DONE;
 	}
       else
@@ -6798,22 +6803,26 @@ (define_expand "abs<mode>2"
     }
 
   label = gen_label_rtx ();
-  if (TARGET_E500_DOUBLE)
+  if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
     {
       if (flag_finite_math_only && !flag_trapping_math)
 	emit_insn (gen_spe_abstf2_tst (operands[0], operands[1], label));
       else
 	emit_insn (gen_spe_abstf2_cmp (operands[0], operands[1], label));
     }
-  else
+  else if (<MODE>mode == TFmode)
     emit_insn (gen_abstf2_internal (operands[0], operands[1], label));
+  else if (<MODE>mode == TFmode)
+    emit_insn (gen_absif2_internal (operands[0], operands[1], label));
+  else
+    FAIL;
   emit_label (label);
   DONE;
 }")
 
-(define_expand "abstf2_internal"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(match_operand:TF 1 "gpc_reg_operand" ""))
+(define_expand "abs<mode>2_internal"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "")
+	(match_operand:IBM128 1 "gpc_reg_operand" ""))
    (set (match_dup 3) (match_dup 5))
    (set (match_dup 5) (abs:DF (match_dup 5)))
    (set (match_dup 4) (compare:CCFP (match_dup 3) (match_dup 5)))
@@ -6821,8 +6830,7 @@ (define_expand "abstf2_internal"
 			   (label_ref (match_operand 2 "" ""))
 			   (pc)))
    (set (match_dup 6) (neg:DF (match_dup 6)))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
    && TARGET_LONG_DOUBLE_128"
   "
 {
@@ -6830,8 +6838,8 @@ (define_expand "abstf2_internal"
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   operands[3] = gen_reg_rtx (DFmode);
   operands[4] = gen_reg_rtx (CCFPmode);
-  operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
-  operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+  operands[5] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
+  operands[6] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
 }")
 
 \f
@@ -6864,14 +6872,14 @@ (define_expand "ieee_128bit_negative_zer
 ;; neg/abs to create the constant just once.
 
 (define_insn_and_split "ieee_128bit_vsx_neg<mode>2"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (clobber (match_scratch:V16QI 2 "=v"))]
-  "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
+  "TARGET_FLOAT128"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
-		   (neg:TFIFKF (match_dup 1)))
+		   (neg:IEEE128 (match_dup 1)))
 	      (use (match_dup 2))])]
 {
   if (GET_CODE (operands[2]) == SCRATCH)
@@ -6884,8 +6892,8 @@ (define_insn_and_split "ieee_128bit_vsx_
    (set_attr "type" "vecsimple")])
 
 (define_insn "*ieee_128bit_vsx_neg<mode>2_internal"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (use (match_operand:V16QI 2 "register_operand" "=v"))]
   "TARGET_FLOAT128"
   "xxlxor %x0,%x1,%x2"
@@ -6893,14 +6901,14 @@ (define_insn "*ieee_128bit_vsx_neg<mode>
 
 ;; IEEE 128-bit absolute value
 (define_insn_and_split "ieee_128bit_vsx_abs<mode>2"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (clobber (match_scratch:V16QI 2 "=v"))]
   "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
-		   (abs:TFIFKF (match_dup 1)))
+		   (abs:IEEE128 (match_dup 1)))
 	      (use (match_dup 2))])]
 {
   if (GET_CODE (operands[2]) == SCRATCH)
@@ -6913,8 +6921,8 @@ (define_insn_and_split "ieee_128bit_vsx_
    (set_attr "type" "vecsimple")])
 
 (define_insn "*ieee_128bit_vsx_abs<mode>2_internal"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa")))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (use (match_operand:V16QI 2 "register_operand" "=v"))]
   "TARGET_FLOAT128"
   "xxlandc %x0,%x1,%x2"
@@ -6922,16 +6930,16 @@ (define_insn "*ieee_128bit_vsx_abs<mode>
 
 ;; IEEE 128-bit negative absolute value
 (define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF
-	 (abs:TFIFKF
-	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128
+	 (abs:IEEE128
+	  (match_operand:IEEE128 1 "register_operand" "wa"))))
    (clobber (match_scratch:V16QI 2 "=v"))]
   "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
-		   (abs:TFIFKF (match_dup 1)))
+		   (abs:IEEE128 (match_dup 1)))
 	      (use (match_dup 2))])]
 {
   if (GET_CODE (operands[2]) == SCRATCH)
@@ -6944,70 +6952,78 @@ (define_insn_and_split "*ieee_128bit_vsx
    (set_attr "type" "vecsimple")])
 
 (define_insn "*ieee_128bit_vsx_nabs<mode>2_internal"
-  [(set (match_operand:TFIFKF 0 "register_operand" "=wa")
-	(neg:TFIFKF
-	 (abs:TFIFKF
-	  (match_operand:TFIFKF 1 "register_operand" "wa"))))
+  [(set (match_operand:IEEE128 0 "register_operand" "=wa")
+	(neg:IEEE128
+	 (abs:IEEE128
+	  (match_operand:IEEE128 1 "register_operand" "wa"))))
    (use (match_operand:V16QI 2 "register_operand" "=v"))]
   "TARGET_FLOAT128"
   "xxlor %x0,%x1,%x2"
   [(set_attr "type" "vecsimple")])
 
 ;; Float128 conversion functions.  These expand to library function calls.
+;; We use expand to convert from IBM double double to IEEE 128-bit
+;; and trunc for the opposite.
+(define_expand "extendiftf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+	(float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
+{
+  rs6000_expand_float128_convert (operands[0], operands[1], false);
+  DONE;
+})
 
-(define_expand "extend<FLOAT128_SFDFTF:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
-	(float_extend:IFKF
-	 (match_operand:FLOAT128_SFDFTF 1 "gpc_reg_operand" "")))]
+(define_expand "extendifkf2"
+  [(set (match_operand:KF 0 "gpc_reg_operand" "")
+	(float_extend:KF (match_operand:IF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2"
-  [(set (match_operand:FLOAT128_SFDFTF 0 "nonimmediate_operand" "")
-	(float_truncate:FLOAT128_SFDFTF
-	 (match_operand:IFKF 1 "gpc_reg_operand" "")))]
+(define_expand "extendtfkf2"
+  [(set (match_operand:KF 0 "gpc_reg_operand" "")
+	(float_extend:KF (match_operand:TF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "fix_trunc<IFKF:mode><SDI:mode>2"
-  [(set (match_operand:SDI 0 "nonimmediate_operand" "")
-	(fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))]
+(define_expand "trunciftf2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "")
+	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "fixuns_trunc<IFKF:mode><SDI:mode>2"
-  [(set (match_operand:SDI 0 "nonimmediate_operand" "")
-	(unsigned_fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))]
+(define_expand "truncifkf2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "")
+	(float_truncate:IF (match_operand:KF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], true);
+  rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "float<SDI:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
-	(float:KF (match_operand:SDI 1 "gpc_reg_operand" "")))]
+(define_expand "trunckftf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "")
+	(float_truncate:TF (match_operand:KF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "floatuns<SDI:mode><IFKF:mode>2"
-  [(set (match_operand:IFKF 0 "nonimmediate_operand" "")
-	(unsigned_float:IFKF (match_operand:SDI 1 "gpc_reg_operand" "")))]
+(define_expand "trunctfif2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "")
+	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
   "TARGET_FLOAT128"
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], true);
+  rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #13
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (11 preceding siblings ...)
  2015-10-23 17:58     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #12 Michael Meissner
@ 2015-10-23 18:00     ` Michael Meissner
  2015-10-29 14:46       ` David Edelsohn
  2015-10-23 18:01     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #14 Michael Meissner
                       ` (6 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 18:00 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 1961 bytes --]

This patch is the second part to allow TFmode to be IBM extended double or IEEE
128-bit floating point depending on switches.

I have built the compiler with this patch and the previous subpatches (1-12).
I have bootstrapped the compiler with all 16 subpatches installed, and there
were no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.md (FP iterator): Allow TFmode to be IEEE
	128-bit floating point.
	(extenddftf2): Rework 128-bit floating point conversions to
	properly handle -mabi=ieeelongdouble. Merge IFmode, TFmode, and
	KFmode expanders into one function.
	(extenddf<mode>2): Likewise.
	(extenddftf2_fprs): Likewise.
	(extenddf<mode>2_fprs): Likewise.
	(extenddftf2_vsx): Likewise.
	(extenddf<mode>2_vsx): Likewise.
	(extendsftf2): Likewise.
	(extendsf<mode>2): Likewise.
	(trunctfdf2): Likewise.
	(trunc<mode>df2): Likewise.
	(trunctfdf2_internal1): Likewise.
	(trunc<mode>df2_internal1): Likewise.
	(trunctfdf2_internal2): Likewise.
	(trunc<mode>df2_internal2): Likewise.
	(trunctfsf2): Likewise.
	(trunc<mode>sf2): Likewise.
	(trunctfsf2_fprs): Likewise.
	(trunc<mode>sf2_fprs): Likewise.
	(floatsit2f): Likewise.
	(floatsi<mode>2): Likewise.
	(fix_trunc_helper): Likewise.
	(fix_trunc_helper<mode>): Likewise.
	(fix_trunctfsi2): Likewise.
	(fix_trunc<mode>si2): Likewise.
	(fix_trunctfsi2_fprs): Likewise.
	(fix_trunc<mode>si2_fprs): Likewise.
	(fix_trunctfsi2_internal): Likewise.
	(fix_trunc<mode>si2_internal): Likewise.
	(fix_trunctfdi2): Likewise.
	(fix_trunc<mode>di2): Likewise.
	(fixuns_trunctf<mode>2): Likewise.
	(fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
	(floatditf2): Likewise.
	(floatdi<mode>2): Likewise.
	(floatuns<mode>tf2): Likewise.
	(floatuns<SDI:mode><IEEE128:mode>): Likewise.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07o --]
[-- Type: text/plain, Size: 15266 bytes --]

Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 229198)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -347,8 +347,7 @@ (define_mode_iterator FP [
    && ((TARGET_FPRS && TARGET_SINGLE_FLOAT) || TARGET_E500_SINGLE)")
   (DF "TARGET_HARD_FLOAT 
    && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)")
-  (TF "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
+  (TF "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
   (IF "TARGET_FLOAT128")
@@ -6463,34 +6462,51 @@ (define_insn_and_split "*mov<mode>_softf
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
   [(set_attr "length" "20,20,16")])
 
-(define_expand "extenddftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(float_extend:TF (match_operand:DF 1 "gpc_reg_operand" "")))]
+(define_expand "extenddf<mode>2"
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(float_extend:FLOAT128 (match_operand:DF 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
   else if (TARGET_E500_DOUBLE)
-    emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
+    {
+      gcc_assert (<MODE>mode == TFmode);
+      emit_insn (gen_spe_extenddftf2 (operands[0], operands[1]));
+    }
   else if (TARGET_VSX)
-    emit_insn (gen_extenddftf2_vsx (operands[0], operands[1]));
-  else
+    {
+      if (<MODE>mode == TFmode)
+	emit_insn (gen_extenddftf2_vsx (operands[0], operands[1]));
+      else if (<MODE>mode == IFmode)
+	emit_insn (gen_extenddfif2_vsx (operands[0], operands[1]));
+      else
+	gcc_unreachable ();
+    }
+   else
     {
       rtx zero = gen_reg_rtx (DFmode);
       rs6000_emit_move (zero, CONST0_RTX (DFmode), DFmode);
-      emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero));
+
+      if (<MODE>mode == TFmode)
+	emit_insn (gen_extenddftf2_fprs (operands[0], operands[1], zero));
+      else if (<MODE>mode == IFmode)
+	emit_insn (gen_extenddfif2_fprs (operands[0], operands[1], zero));
+      else
+	gcc_unreachable ();
     }
   DONE;
 })
 
 ;; Allow memory operands for the source to be created by the combiner.
-(define_insn_and_split "extenddftf2_fprs"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=d,d,&d")
-	(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "d,m,d")))
+(define_insn_and_split "extenddf<mode>2_fprs"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d,&d")
+	(float_extend:IBM128
+	 (match_operand:DF 1 "nonimmediate_operand" "d,m,d")))
    (use (match_operand:DF 2 "nonimmediate_operand" "m,m,d"))]
   "!TARGET_VSX && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
-   && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD"
+   && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 3) (match_dup 1))
@@ -6499,14 +6515,15 @@ (define_insn_and_split "extenddftf2_fprs
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
 
-  operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
-  operands[4] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+  operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
+  operands[4] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
 })
 
-(define_insn_and_split "extenddftf2_vsx"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=d,d")
-	(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "ws,m")))]
-  "TARGET_LONG_DOUBLE_128 && TARGET_VSX && !TARGET_IEEEQUAD"
+(define_insn_and_split "extenddf<mode>2_vsx"
+  [(set (match_operand:IBM128 0 "gpc_reg_operand" "=d,d")
+	(float_extend:IBM128
+	 (match_operand:DF 1 "nonimmediate_operand" "ws,m")))]
+  "TARGET_LONG_DOUBLE_128 && TARGET_VSX && FLOAT128_IBM_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 2) (match_dup 1))
@@ -6515,47 +6532,48 @@ (define_insn_and_split "extenddftf2_vsx"
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
 
-  operands[2] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
-  operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word);
+  operands[2] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, hi_word);
+  operands[3] = simplify_gen_subreg (DFmode, operands[0], <MODE>mode, lo_word);
   operands[4] = CONST0_RTX (DFmode);
 })
 
-(define_expand "extendsftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-	(float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))]
+(define_expand "extendsf<mode>2"
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+	(float_extend:FLOAT128 (match_operand:SF 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
   else
     {
       rtx tmp = gen_reg_rtx (DFmode);
       emit_insn (gen_extendsfdf2 (tmp, operands[1]));
-      emit_insn (gen_extenddftf2 (operands[0], tmp));
+      emit_insn (gen_extenddf<mode>2 (operands[0], tmp));
     }
   DONE;
 })
 
-(define_expand "trunctfdf2"
+(define_expand "trunc<mode>df2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
+	(float_truncate:DF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     {
       rs6000_expand_float128_convert (operands[0], operands[1], false);
       DONE;
     }
 })
 
-(define_insn_and_split "trunctfdf2_internal1"
+(define_insn_and_split "trunc<mode>df2_internal1"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d")
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,d")))]
-  "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
+	(float_truncate:DF
+	 (match_operand:IBM128 1 "gpc_reg_operand" "0,d")))]
+  "FLOAT128_IBM_P (<MODE>mode) && !TARGET_XL_COMPAT
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "@
    #
@@ -6568,39 +6586,44 @@ (define_insn_and_split "trunctfdf2_inter
 }
   [(set_attr "type" "fp")])
 
-(define_insn "trunctfdf2_internal2"
+(define_insn "trunc<mode>df2_internal2"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-	(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
-   && TARGET_LONG_DOUBLE_128"
+	(float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" "d")))]
+  "FLOAT128_IBM_P (<MODE>mode) && TARGET_XL_COMPAT && TARGET_HARD_FLOAT
+   && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
   "fadd %0,%1,%L1"
   [(set_attr "type" "fp")
    (set_attr "fp_type" "fp_addsub_d")])
 
-(define_expand "trunctfsf2"
+(define_expand "trunc<mode>sf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
-	(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))]
+	(float_truncate:SF (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
   else if (TARGET_E500_DOUBLE)
-    emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
-  else
+    {
+      gcc_assert (<MODE>mode == TFmode);
+      emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1]));
+    }
+  else if (<MODE>mode == TFmode)
     emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1]));
+  else if (<MODE>mode == IFmode)
+    emit_insn (gen_truncifsf2_fprs (operands[0], operands[1]));
+  else
+    gcc_unreachable ();
   DONE;
 })
 
-(define_insn_and_split "trunctfsf2_fprs"
+(define_insn_and_split "trunc<mode>sf2_fprs"
   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
-	(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "d")))
+	(float_truncate:SF (match_operand:IBM128 1 "gpc_reg_operand" "d")))
    (clobber (match_scratch:DF 2 "=d"))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT 
-   && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT 
+   && TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (<MODE>mode)"
   "#"
   "&& reload_completed"
   [(set (match_dup 2)
@@ -6609,56 +6632,69 @@ (define_insn_and_split "trunctfsf2_fprs"
 	(float_truncate:SF (match_dup 2)))]
   "")
 
-(define_expand "floatsitf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "")
-        (float:TF (match_operand:SI 1 "gpc_reg_operand" "")))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT
+(define_expand "floatsi<mode>2"
+  [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "")
+        (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand" "")))]
+  "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128"
 {
-  rtx tmp = gen_reg_rtx (DFmode);
-  expand_float (tmp, operands[1], false);
-  emit_insn (gen_extenddftf2 (operands[0], tmp));
+  if (FLOAT128_IEEE_P (<MODE>mode))
+    rs6000_expand_float128_convert (operands[0], operands[1], false);
+  else
+    {
+      rtx tmp = gen_reg_rtx (DFmode);
+      expand_float (tmp, operands[1], false);
+      if (<MODE>mode == TFmode)
+	emit_insn (gen_extenddftf2 (operands[0], tmp));
+      else if (<MODE>mode == IFmode)
+	emit_insn (gen_extenddfif2 (operands[0], tmp));
+      else
+	gcc_unreachable ();
+    }
   DONE;
 })
 
 ; fadd, but rounding towards zero.
 ; This is probably not the optimal code sequence.
-(define_insn "fix_trunc_helper"
+(define_insn "fix_trunc_helper<mode>"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d")
-	(unspec:DF [(match_operand:TF 1 "gpc_reg_operand" "d")]
+	(unspec:DF [(match_operand:IBM128 1 "gpc_reg_operand" "d")]
 		   UNSPEC_FIX_TRUNC_TF))
    (clobber (match_operand:DF 2 "gpc_reg_operand" "=&d"))]
-  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && FLOAT128_IBM_P (<MODE>mode)"
   "mffs %2\n\tmtfsb1 31\n\tmtfsb0 30\n\tfadd %0,%1,%L1\n\tmtfsf 1,%2"
   [(set_attr "type" "fp")
    (set_attr "length" "20")])
 
-(define_expand "fix_trunctfsi2"
+(define_expand "fix_trunc<mode>si2"
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
-	(fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))]
+	(fix:SI (match_operand:FLOAT128 1 "gpc_reg_operand" "")))]
   "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128"
 {
-  if (TARGET_IEEEQUAD)
+  if (FLOAT128_IEEE_P (<MODE>mode))
     rs6000_expand_float128_convert (operands[0], operands[1], false);
-  else if (TARGET_E500_DOUBLE)
+  else if (TARGET_E500_DOUBLE && <MODE>mode == TFmode)
     emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1]));
-  else
+  else if (<MODE>mode == TFmode)
     emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1]));
+  else if (<MODE>mode == IFmode)
+    emit_insn (gen_fix_truncifsi2_fprs (operands[0], operands[1]));
+  else
+    gcc_unreachable ();
   DONE;
 })
 
-(define_expand "fix_trunctfsi2_fprs"
+(define_expand "fix_trunc<mode>si2_fprs"
   [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
-		   (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))
+		   (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "")))
 	      (clobber (match_dup 2))
 	      (clobber (match_dup 3))
 	      (clobber (match_dup 4))
 	      (clobber (match_dup 5))])]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
 {
   operands[2] = gen_reg_rtx (DFmode);
   operands[3] = gen_reg_rtx (DFmode);
@@ -6666,21 +6702,21 @@ (define_expand "fix_trunctfsi2_fprs"
   operands[5] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode));
 })
 
-(define_insn_and_split "*fix_trunctfsi2_internal"
+(define_insn_and_split "*fix_trunc<mode>si2_internal"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (fix:SI (match_operand:TF 1 "gpc_reg_operand" "d")))
+        (fix:SI (match_operand:IBM128 1 "gpc_reg_operand" "d")))
    (clobber (match_operand:DF 2 "gpc_reg_operand" "=d"))
    (clobber (match_operand:DF 3 "gpc_reg_operand" "=&d"))
    (clobber (match_operand:DI 4 "gpc_reg_operand" "=d"))
    (clobber (match_operand:DI 5 "offsettable_mem_operand" "=o"))]
-  "!TARGET_IEEEQUAD
-   && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
   "#"
   ""
   [(pc)]
 {
   rtx lowword;
-  emit_insn (gen_fix_trunc_helper (operands[2], operands[1], operands[3]));
+  emit_insn (gen_fix_trunc_helper<mode> (operands[2], operands[1],
+					 operands[3]));
 
   gcc_assert (MEM_P (operands[5]));
   lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
@@ -6691,37 +6727,37 @@ (define_insn_and_split "*fix_trunctfsi2_
   DONE;
 })
 
-(define_expand "fix_trunctfdi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
-	(fix:DI (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "fix_trunc<mode>di2"
+  [(set (match_operand:DI 0 "gpc_reg_operand" "")
+	(fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "fixuns_trunctf<mode>2"
-  [(set (match_operand:SDI 0 "nonimmediate_operand" "")
-	(unsigned_fix:SDI (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2"
+  [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+	(unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
 })
 
-(define_expand "floatditf2"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "")
-	(float:TF (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "floatdi<mode>2"
+  [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
+	(float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 })
 
-(define_expand "floatuns<mode>tf2"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "")
-	(unsigned_float:TF (match_operand:SDI 1 "gpc_reg_operand" "")))]
-  "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
+(define_expand "floatuns<SDI:mode><IEEE128:mode>2"
+  [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
+	(unsigned_float:IEEE128 (match_operand:SDI 1 "gpc_reg_operand" "")))]
+  "TARGET_FLOAT128"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #14
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (12 preceding siblings ...)
  2015-10-23 18:00     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #13 Michael Meissner
@ 2015-10-23 18:01     ` Michael Meissner
  2015-10-29 14:46       ` David Edelsohn
  2015-10-23 18:03     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #15 Michael Meissner
                       ` (5 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 18:01 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 733 bytes --]

This patch makes TFmode be fully switchable for comparisons.

I have built the compiler with this patch and the previous subpatches (1-13).
I have bootstrapped the compiler with all 16 subpatches installed, and there
were no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.md (cmptf_internal1): Use a mode iterator
	to add support for both types (IFmode, TFmode) that support IBM
	extended double.
	(cmp<mode>_internal1): Likewise.
	(cmptf_internal2): Likewise.
	(cmp<mode>_internal2): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07p --]
[-- Type: text/plain, Size: 2881 bytes --]

Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 229200)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -10576,20 +10576,20 @@ (define_split
    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 4)))])
 
 ;; Only need to compare second words if first words equal
-(define_insn "*cmptf_internal1"
+(define_insn "*cmp<mode>_internal1"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-	(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d")
-		      (match_operand:TF 2 "gpc_reg_operand" "d")))]
-  "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
+	(compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
+		      (match_operand:IBM128 2 "gpc_reg_operand" "d")))]
+  "!TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
   "fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
   [(set_attr "type" "fpcompare")
    (set_attr "length" "12")])
 
-(define_insn_and_split "*cmptf_internal2"
+(define_insn_and_split "*cmp<mode>_internal2"
   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
-	(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "d")
-		      (match_operand:TF 2 "gpc_reg_operand" "d")))
+	(compare:CCFP (match_operand:IBM128 1 "gpc_reg_operand" "d")
+		      (match_operand:IBM128 2 "gpc_reg_operand" "d")))
     (clobber (match_scratch:DF 3 "=d"))
     (clobber (match_scratch:DF 4 "=d"))
     (clobber (match_scratch:DF 5 "=d"))
@@ -10599,7 +10599,7 @@ (define_insn_and_split "*cmptf_internal2
     (clobber (match_scratch:DF 9 "=d"))
     (clobber (match_scratch:DF 10 "=d"))
     (clobber (match_scratch:GPR 11 "=b"))]
-  "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
+  "TARGET_XL_COMPAT && FLOAT128_IBM_P (<MODE>mode)
    && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && TARGET_LONG_DOUBLE_128"
   "#"
   "&& reload_completed"
@@ -10623,10 +10623,10 @@ (define_insn_and_split "*cmptf_internal2
   const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
   const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
 
-  operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, hi_word);
-  operands[6] = simplify_gen_subreg (DFmode, operands[1], TFmode, lo_word);
-  operands[7] = simplify_gen_subreg (DFmode, operands[2], TFmode, hi_word);
-  operands[8] = simplify_gen_subreg (DFmode, operands[2], TFmode, lo_word);
+  operands[5] = simplify_gen_subreg (DFmode, operands[1], <MODE>mode, hi_word);
+  operands[6] = simplify_gen_subreg (DFmode, operands[1], <MODE>mode, lo_word);
+  operands[7] = simplify_gen_subreg (DFmode, operands[2], <MODE>mode, hi_word);
+  operands[8] = simplify_gen_subreg (DFmode, operands[2], <MODE>mode, lo_word);
   operands[12] = gen_label_rtx ();
   operands[13] = gen_label_rtx ();
   real_inf (&rv);

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #15
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (13 preceding siblings ...)
  2015-10-23 18:01     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #14 Michael Meissner
@ 2015-10-23 18:03     ` Michael Meissner
  2015-10-29 14:50       ` David Edelsohn
  2015-10-23 18:04     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #16 Michael Meissner
                       ` (4 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 18:03 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 634 bytes --]

This patch adds the documentation.

I have built the compiler with this patch and the previous subpatches (1-14).
I have bootstrapped the compiler with all 16 subpatches installed, and there
were no regressions.  Is it ok to install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* doc/extend.texi (Floating Types): Document __ibm128 and
	__float128 on PowerPC.

	* doc/invoke.texi (RS/6000 and PowerPC Options): Document
	-mfloat128 and -mno-float128.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07q --]
[-- Type: text/plain, Size: 3924 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 229182)
+++ gcc/doc/extend.texi	(working copy)
@@ -929,6 +929,7 @@ examine and set these two fictitious var
 @cindex additional floating types
 @cindex @code{__float80} data type
 @cindex @code{__float128} data type
+@cindex @code{__ibm128} data type
 @cindex @code{w} floating point suffix
 @cindex @code{q} floating point suffix
 @cindex @code{W} floating point suffix
@@ -941,19 +942,39 @@ Support for additional types includes th
 add, subtract, multiply, divide; unary arithmetic operators;
 relational operators; equality operators; and conversions to and from
 integer and other floating types.  Use a suffix @samp{w} or @samp{W}
-in a literal constant of type @code{__float80} and @samp{q} or @samp{Q}
-for @code{_float128}.  You can declare complex types using the
-corresponding internal complex type, @code{XCmode} for @code{__float80}
-type and @code{TCmode} for @code{__float128} type:
+in a literal constant of type @code{__float80} or type
+@code{__ibm128}.  Use a suffix @samp{q} or @samp{Q} for @code{_float128}.
+
+On the i386, x86_64, IA-64, and HP-UX targets, you can declare complex
+types using the corresponding internal complex type, @code{XCmode} for
+@code{__float80} type and @code{TCmode} for @code{__float128} type:
 
 @smallexample
 typedef _Complex float __attribute__((mode(TC))) _Complex128;
 typedef _Complex float __attribute__((mode(XC))) _Complex80;
 @end smallexample
 
+On PowerPC Linux, Freebsd and Darwin systems, the default for
+@code{long double} is to use the IBM extended floating point format
+that uses a pair of @code{double} values to extend the precision.
+This means that the mode @code{TCmode} was already used by the
+traditional IBM long double format, and you would need to use the mode
+@code{KCmode}:
+
+@smallexample
+typedef _Complex float __attribute__((mode(KC))) _Complex128;
+@end smallexample
+
 Not all targets support additional floating-point types.  @code{__float80}
 and @code{__float128} types are supported on x86 and IA-64 targets.
-The @code{__float128} type is supported on hppa HP-UX targets.
+The @code{__float128} type is supported on hppa HP-UX.
+The @code{__float128} type is supported on PowerPC systems by default
+if the vector scalar instruction set (VSX) is enabled.
+
+On the PowerPC, @code{__ibm128} provides access to the IBM extended
+double format, and it is intended to be used by the library functions
+that handle conversions if/when long double is changed to be IEEE
+128-bit floating point.
 
 @node Half-Precision
 @section Half-Precision Floating Point
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 229182)
+++ gcc/doc/invoke.texi	(working copy)
@@ -946,7 +946,8 @@ See RS/6000 and PowerPC Options.
 -mquad-memory-atomic -mno-quad-memory-atomic @gol
 -mcompat-align-parm -mno-compat-align-parm @gol
 -mupper-regs-df -mno-upper-regs-df -mupper-regs-sf -mno-upper-regs-sf @gol
--mupper-regs -mno-upper-regs}
+-mupper-regs -mno-upper-regs @gol
+-mfloat128 -mno-float128}
 
 @emph{RX Options}
 @gccoptlist{-m64bit-doubles  -m32bit-doubles  -fpu  -nofpu@gol
@@ -19519,6 +19520,17 @@ floating point register set, depending o
 If the @option{-mno-upper-regs} option is used, it turns off both
 @option{-mupper-regs-sf} and @option{-mupper-regs-df} options.
 
+@item -mfloat128
+@itemx -mno-float128
+@opindex mfloat128
+@opindex mno-float128
+Enable/disable the @var{__float128} keyword for IEEE 128-bit floating point
+and use software emulation for IEEE 128-bit floating point.
+
+The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7}, or
+@option{-mcpu=power8}) must be enabled to use the @option{-mfloat128}
+option.
+
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
 @opindex mfloat-gprs

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #16
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (14 preceding siblings ...)
  2015-10-23 18:03     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #15 Michael Meissner
@ 2015-10-23 18:04     ` Michael Meissner
  2015-10-29 15:02       ` David Edelsohn
  2015-10-23 20:06     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Segher Boessenkool
                       ` (3 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 18:04 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 591 bytes --]

This patch adds a test to make sure __float128 are passed and returned like
vector objects, and not as IBM extended double did.

This is the last subpatch of patch #7.  I have bootstrapped the compiler with
all 16 subpatches installed, and there were no regressions.  Is it ok to
install in the trunk?

2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/float128-call.c: New test for -mfloat128 on
	PowerPC.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07r --]
[-- Type: text/plain, Size: 1173 bytes --]

Index: gcc/testsuite/gcc.target/powerpc/float128-call.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-call.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-call.c	(revision 0)
@@ -0,0 +1,27 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-O2 -mcpu=power7 -mfloat128 -mno-regnames" } */
+
+#ifndef __FLOAT128__
+#error "-mfloat128 is not supported."
+#endif
+
+#ifdef __LONG_DOUBLE_IEEE128__
+#define TYPE long double
+#define ONE  1.0L
+
+#else
+#define TYPE __float128
+#define ONE  1.0Q
+#endif
+
+/* Test to make sure vector registers are used for passing IEEE 128-bit
+   floating point values and returning them. Also make sure the 'q' suffix is
+   handled.  */
+TYPE one (void) { return ONE; }
+void store (TYPE a, TYPE *p) { *p = a; }
+
+/* { dg-final { scan-assembler "lxvd2x 34"  } } */
+/* { dg-final { scan-assembler "stxvd2x 34" } } */

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 (patch included)
  2015-10-23 17:39     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 Michael Meissner
@ 2015-10-23 18:08       ` Michael Meissner
  2015-10-29 14:33       ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 David Edelsohn
  1 sibling, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 18:08 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 1072 bytes --]

On Fri, Oct 23, 2015 at 01:39:36PM -0400, Michael Meissner wrote:
> This patch prevents the compiler from calling the IEEE 128-bit emulation
> functions with the vector value in both GPRs and vector registers due to the
> fact that the library function did not have a prototype.
> 
> I have built the compiler with this patch and the previous subpatches (1-4).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
> 
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
> 
> 	* config/rs6000/rs6000.c (init_cumulative_args): Initialize
> 	libcall field in CUMULATIVE_ARGS.
> 	(rs6000_function_arg): Treat library functions as if they had
> 	prototypes to prevent IEEE 128-bit support functions from passing
> 	arguments in both GPRs and vector registers.
> 	(rs6000_arg_partial_bytes): Likewise.

I forgot to attach the patch.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07g --]
[-- Type: text/plain, Size: 2166 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 229187)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -9441,6 +9441,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      ? CALL_LIBCALL : CALL_NORMAL);
   cum->sysv_gregno = GP_ARG_MIN_REG;
   cum->stdarg = stdarg_p (fntype);
+  cum->libcall = libcall;
 
   cum->nargs_prototype = 0;
   if (incoming || cum->prototype)
@@ -10613,9 +10614,11 @@ rs6000_function_arg (cumulative_args_t c
       rtx r, off;
       int i, k = 0;
 
-      /* Do we also need to pass this argument in the parameter
-	 save area?  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* Do we also need to pass this argument in the parameter save area?
+	 Library support functions for IEEE 128-bit are assumed to not need the
+	 value passed both in GPRs and in vector registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	{
 	  int align_words = ROUND_UP (cum->words, 2);
 	  k = rs6000_psave_function_arg (mode, type, align_words, rvec);
@@ -10846,11 +10849,14 @@ rs6000_arg_partial_bytes (cumulative_arg
 
   if (USE_ALTIVEC_FOR_ARG_P (cum, elt_mode, named))
     {
-      /* If we are passing this arg in the fixed parameter save area
-         (gprs or memory) as well as VRs, we do not use the partial
-	 bytes mechanism; instead, rs6000_function_arg will return a
-	 PARALLEL including a memory element as necessary.  */
-      if (TARGET_64BIT && ! cum->prototype)
+      /* If we are passing this arg in the fixed parameter save area (gprs or
+         memory) as well as VRs, we do not use the partial bytes mechanism;
+         instead, rs6000_function_arg will return a PARALLEL including a memory
+         element as necessary.  Library support functions for IEEE 128-bit are
+         assumed to not need the value passed both in GPRs and in vector
+         registers.  */
+      if (TARGET_64BIT && !cum->prototype
+	  && (!cum->libcall || !FLOAT128_VECTOR_P (elt_mode)))
 	return 0;
 
       /* Otherwise, we pass in VRs only.  Check for partial copies.  */

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (15 preceding siblings ...)
  2015-10-23 18:04     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #16 Michael Meissner
@ 2015-10-23 20:06     ` Segher Boessenkool
  2015-10-23 20:25       ` Michael Meissner
  2015-10-27 19:48     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #17 Michael Meissner
                       ` (2 subsequent siblings)
  19 siblings, 1 reply; 78+ messages in thread
From: Segher Boessenkool @ 2015-10-23 20:06 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

On Fri, Oct 23, 2015 at 01:22:11PM -0400, Michael Meissner wrote:
> David asked me to try and break patch #7 into smaller bite sized chunks. I have
> broken this into roughly 16 parts. These are the same patches that I submitted
> for patch #7 (revised), just broken up.  There is one additional patch in this
> selection, to restrict __float128 and IBM extended double from being combined
> in an expression.

#04, #05 are missing the patch.


Segher

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09 Michael Meissner
@ 2015-10-23 20:17       ` Joseph Myers
  2015-10-23 20:23         ` Michael Meissner
  2015-10-29 14:39       ` David Edelsohn
  1 sibling, 1 reply; 78+ messages in thread
From: Joseph Myers @ 2015-10-23 20:17 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

On Fri, 23 Oct 2015, Michael Meissner wrote:

> This patch is the new patch from the last submission. It sets up a hook so that
> the compiler will not allow IBM extended double and IEEE 128-bit floating point
> to intermix in a binary expression without using an explicit conversion.

I don't see a testcase that this mixing is rejected.  And I'd have 
expected you to need a C/C++ front-end patch to cause rejection in 
conditional expressions, which don't seem currently to have such a hook, 
but didn't see that in this series - is it intended for a patch after #7?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09
  2015-10-23 20:17       ` Joseph Myers
@ 2015-10-23 20:23         ` Michael Meissner
  0 siblings, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 20:23 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Fri, Oct 23, 2015 at 08:05:58PM +0000, Joseph Myers wrote:
> On Fri, 23 Oct 2015, Michael Meissner wrote:
> 
> > This patch is the new patch from the last submission. It sets up a hook so that
> > the compiler will not allow IBM extended double and IEEE 128-bit floating point
> > to intermix in a binary expression without using an explicit conversion.
> 
> I don't see a testcase that this mixing is rejected.  And I'd have 
> expected you to need a C/C++ front-end patch to cause rejection in 
> conditional expressions, which don't seem currently to have such a hook, 
> but didn't see that in this series - is it intended for a patch after #7?

I am planning on writing the test cases, but I couldn't write them until all
of the sub-patches for patch #7 are in place.

I am planning on looking at a new hook for ?: next week.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04
  2015-10-23 17:38     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04 Michael Meissner
@ 2015-10-23 20:24       ` Michael Meissner
  2015-10-29 14:29       ` David Edelsohn
  1 sibling, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 20:24 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 833 bytes --]

On Fri, Oct 23, 2015 at 01:36:25PM -0400, Michael Meissner wrote:
> This patch allows SUBREG's for the reg_or_indexed_operand, which is used when
> you have an integral value in a float/vector register, and you want to move the
> value (either via direct move on power8, or via store).
> 
> I have built the compiler with this patch and the previous subpatches (1-3).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
> 
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
> 
> 	* config/rs6000/predicates.md (reg_or_indexed_operand): Allow
> 	SUBREGs.

I forgot to attach the patch.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07f --]
[-- Type: text/plain, Size: 564 bytes --]

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md     (revision 229188)
+++ gcc/config/rs6000/predicates.md     (revision 229189)
@@ -684,7 +684,7 @@ (define_predicate "indexed_or_indirect_o
 ;; Like indexed_or_indirect_operand, but also allow a GPR register if direct
 ;; moves are supported.
 (define_predicate "reg_or_indexed_operand"
-  (match_code "mem,reg")
+  (match_code "mem,reg,subreg")
 {
   if (MEM_P (op))
     return indexed_or_indirect_operand (op, mode);

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2)
  2015-10-23 20:06     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Segher Boessenkool
@ 2015-10-23 20:25       ` Michael Meissner
  0 siblings, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-23 20:25 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Fri, Oct 23, 2015 at 02:47:16PM -0500, Segher Boessenkool wrote:
> On Fri, Oct 23, 2015 at 01:22:11PM -0400, Michael Meissner wrote:
> > David asked me to try and break patch #7 into smaller bite sized chunks. I have
> > broken this into roughly 16 parts. These are the same patches that I submitted
> > for patch #7 (revised), just broken up.  There is one additional patch in this
> > selection, to restrict __float128 and IBM extended double from being combined
> > in an expression.
> 
> #04, #05 are missing the patch.

I had caught #05 was missing a patch, but I missed #04. I have re-submitted
subpatches #4 and #5.  Thanks.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #17
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (16 preceding siblings ...)
  2015-10-23 20:06     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Segher Boessenkool
@ 2015-10-27 19:48     ` Michael Meissner
  2015-11-04 15:47       ` David Edelsohn
  2015-10-27 22:27     ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Michael Meissner
  2015-10-27 22:35     ` [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems) Michael Meissner
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-27 19:48 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 574 bytes --]

This patch adds a test to make sure __float128 and __ibm128 are not allowed to
be combined in binary operations.  I re-ran the test suite on power8 little
endian, and this test passed. Once the preceeding 16 patches are applied to the
tree, is this patch ok to commit into trunk?

2015-10-27  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/float128-mix.c: New test for IEEE 128-bit
	floating point.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch07s --]
[-- Type: text/plain, Size: 981 bytes --]

Index: gcc/testsuite/gcc.target/powerpc/float128-mix.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-mix.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-mix.c	(revision 0)
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
+/* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
+
+
+/* Test to make sure that __float128 and __ibm128 cannot be combined together.  */
+__float128 add (__float128 a, __ibm128 b)
+{
+  return a+b;	/* { dg-error "__float128 and __ibm128 cannot be used in the same expression" "" } */
+}
+
+__ibm128 sub (__ibm128 a, __float128 b)
+{
+  return a-b;	/* { dg-error "__float128 and __ibm128 cannot be used in the same expression" "" } */
+}

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits)
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (17 preceding siblings ...)
  2015-10-27 19:48     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #17 Michael Meissner
@ 2015-10-27 22:27     ` Michael Meissner
  2015-10-27 23:39       ` Joseph Myers
  2015-10-27 22:35     ` [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems) Michael Meissner
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-27 22:27 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 2231 bytes --]

Assuming the 17 sub-patches within patch #7 are approved, this patch adds the
necessary bits to libgcc to build the __float128 emulation functions.

Originally, it was thought that since it uses the TFmode emulation functions
from the libgcc/soft-fp directory, that we would need to submit the patches
through glibc where the master source lives.

However, since we don't do any modification of the soft-fp sources, but do it
all through support in the libgcc/config/rs6000 directory, I'm submitting this
patch to libgcc.

This patch passes bootstrap and regression testing on a little endian power8
system (previous versions of the patch also were tested on a big endian power7
system).  Once the patch #7 sub-patches are checked in, is this patch
appropriate to be checked in?

2015-10-27  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* Makefile.in (EXTRA_CLEAN): New variable of additional files to
	clean.
	(FLAGS_TO_PASS): Add EXTRA_CLEAN.
	(clean): Delete EXTRA_CLEAN files.

	* configure.ac (powerpc*-*-linux*): If the compiler is capable of
	generating __float128 code, build the __float128 emulation
	libraries.
	* configure: Regenerate.

	* config/rs6000/extendkftf2.c: New files for IEEE 128-bit floating
	point support.
	* config/rs6000/cmpukf2.c: Likewise.
	* config/rs6000/trunctfk2.c: Likewise.
	* config/rs6000/quad-float128.h: Likewise.
	* config/rs6000/t-float128: Likewise.
	* config/rs6000/float128-sed: Likewise.

	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Update
	defintiions to use 64-bit types for 64-bit systems or 32-bit VSX
	systems with IEEE 128-bit floating point support.
	(_FP_W_TYPE): Likewise.
	(_FP_WS_TYPE): Likewise.
	(_FP_I_TYPE): Likewise.
	(TItype): Add defintions for IEEE 128-bit floating point support.
	(UTItype): Likewise.
	(TI_BITS): Likewise.
	(_FP_MUL_MEAT_Q): Use 64-bit types on 64-bit systems and for
	32-bit VSX systems with IEEE 128-bit floating point.
	(_FP_DIV_MEAT_Q): Likewise.
	(_FP_NANFRAC_Q): Likewise.

	* config/rs6000/libgcc-glibc.ver: Add requires for GCC 6.0 adding
	IEEE 128-bit floating point support.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch08b --]
[-- Type: text/plain, Size: 23038 bytes --]

Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 229390)
+++ libgcc/config.host	(working copy)
@@ -1058,6 +1058,11 @@ powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
 	extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	md_unwind_header=rs6000/linux-unwind.h
 	;;
Index: libgcc/Makefile.in
===================================================================
--- libgcc/Makefile.in	(revision 229390)
+++ libgcc/Makefile.in	(working copy)
@@ -70,6 +70,8 @@ INSTALL_DATA = @INSTALL_DATA@
 mkinstalldirs = $(SHELL) $(libgcc_topdir)/mkinstalldirs
 INSTALL_PARTS = $(EXTRA_PARTS)
 
+EXTRA_CLEAN =
+
 objext = .o
 
 AR = @AR@
@@ -90,6 +92,7 @@ FLAGS_TO_PASS = \
 	"CFLAGS=$(CFLAGS)" \
 	"DESTDIR=$(DESTDIR)" \
 	"EXTRA_OFILES=$(EXTRA_OFILES)" \
+	"EXTRA_CLEAN=$(EXTRA_CLEAN)" \
 	"HDEFINES=$(HDEFINES)" \
 	"INSTALL=$(INSTALL)" \
 	"INSTALL_DATA=$(INSTALL_DATA)" \
@@ -128,7 +131,7 @@ installcheck:
 clean:
 	-rm -f libgcc_tm.h libgcc.map
 	-rm -f libgcc_tm.stamp stmp-ldirs
-	-rm -f *$(objext)
+	-rm -f *$(objext) $(EXTRA_CLEAN)
 	-rm -f *.dep
 	-rm -f *.a
 	-rm -f libunwind$(SHLIB_EXT)
Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(revision 229390)
+++ libgcc/configure.ac	(working copy)
@@ -373,6 +373,17 @@ esac
 ;;
 esac
 
+case ${host} in
+powerpc*-*-linux*)
+  AC_CACHE_CHECK([whether the PowerPC compiler can do __float128],
+		 [libgcc_cv_powerpc_float128],
+		 [AC_COMPILE_IFELSE(
+    [#pragma GCC target ("vsx,float128")
+     __float128 add (__float128 *a) { return *a + *(a+1); }],
+    [libgcc_cv_powerpc_float128=yes],
+    [libgcc_cv_powerpc_float128=no])])
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
Index: libgcc/config/rs6000/extendkftf2.c
===================================================================
--- libgcc/config/rs6000/extendkftf2.c	(revision 0)
+++ libgcc/config/rs6000/extendkftf2.c	(revision 0)
@@ -0,0 +1,59 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Convert IEEE 128-bit floating point to IBM long double.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+extern __ibm128 __extendkftf2 (__float128);
+
+__ibm128
+__extendkftf2 (__float128 value)
+{
+  double high, low;
+
+  high = (double) value;
+  if (__builtin_isnan (high) || __builtin_isinf (high))
+    low = high;
+
+  else
+    {
+      low = (double) (value - (__float128)high);
+
+      /* Use copysign to propigate the sign bit so that -0.0Q becomes -0.0L.  */
+      low = __builtin_copysign (low, high);
+    }
+
+  return __builtin_pack_longdouble (high, low);
+}
Index: libgcc/config/rs6000/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(revision 229390)
+++ libgcc/config/rs6000/sfp-machine.h	(working copy)
@@ -1,7 +1,26 @@
+/* Decide whether to use 64 or 32-bit types to do the emulation.  If we are
+   doing IEEE-128 with VSX, use 64-bit emulation even if we are compiling for a
+   32-bit target.  */
+
+#if defined(_ARCH_PPC64) || defined(__VSX__) || defined(__FLOAT128__)
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long long
+#define _FP_WS_TYPE		signed long long
+#define _FP_I_TYPE		long long
+
+#ifdef _ARCH_PPC64
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+
+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
+#endif
+
+#else	/* 32-bits  */
 #define _FP_W_TYPE_SIZE		32
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
+#define _FP_W_TYPE		unsigned int
+#define _FP_WS_TYPE		signed int
+#define _FP_I_TYPE		int
+#endif	/* 32-bits  */
 
 /* The type of the result of a floating point comparison.  This must
    match `__libgcc_cmp_return__' in GCC for the target.  */
@@ -12,16 +31,34 @@ typedef int __gcc_CMPtype __attribute__ 
   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_D(R,X,Y)				\
   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_MUL_MEAT_Q(R,X,Y)				\
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#else
 #define _FP_MUL_MEAT_Q(R,X,Y)				\
   _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+#endif
 
 #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_loop(S,R,X,Y)
 #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_DIV_MEAT_Q(R,X,Y)   _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+#else
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+#endif
 
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
 #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+#else
 #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#endif
+
 #define _FP_NANSIGN_S		0
 #define _FP_NANSIGN_D		0
 #define _FP_NANSIGN_Q		0
Index: libgcc/config/rs6000/cmpukf2.c
===================================================================
--- libgcc/config/rs6000/cmpukf2.c	(revision 0)
+++ libgcc/config/rs6000/cmpukf2.c	(revision 0)
@@ -0,0 +1,87 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+#include "quad-float128.h"
+
+/* PowerPC condition register bits.  */
+#define PPC_UNORDERED		0x1		/* isnan (a) || isnan (b).  */
+#define PPC_EQUAL		0x2		/* a == b.  */
+#define PPC_GREATER_THEN	0x4		/* a > b.  */
+#define PPC_LESS_THEN		0x8		/* a < b.  */
+
+/* Map FP_CMP_Q output to PowerPC condition register bits.  */
+#define CMP_UNORDERED		(-2)		/* isnan (a) || isnan (b).  */
+#define CMP_LESS_THEN		(-1)		/* a < b.  */
+#define CMP_EQUAL		0		/* a == b.  */
+#define CMP_GREATER_THEN	1		/* a < b.  */
+#define CMP_INVALID		2		/* raise invalid exception.  */
+
+#define CMP_LOW			CMP_UNORDERED	/* comparison low value.  */
+#define CMP_HIGH		CMP_INVALID	/* comparison high value.  */
+
+static const unsigned char ppc_cr_map[] = {
+  PPC_UNORDERED,				/* -2: unordered.  */
+  PPC_LESS_THEN,				/* -1: a < b.  */
+  PPC_EQUAL,					/*  0: a == b.  */
+  PPC_GREATER_THEN,				/*  1: a > b.  */
+  PPC_UNORDERED,				/*  2: invalid.  */
+};
+
+/* Compare two IEEE 128-bit floating point values and return the status.  We
+   return the status as a 4-bit value that can be copied into an appropriate
+   PowerPC conditon code register.  */
+
+CMPtype
+__cmpukf2 (TFtype a, TFtype b)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_Q (B);
+  CMPtype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_UNPACK_RAW_Q (B, b);
+  FP_CMP_Q (r, A, B, 2, 2);
+  if (r == CMP_INVALID)
+    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_HANDLE_EXCEPTIONS;
+
+  return (r < CMP_LOW || r > CMP_HIGH) ? PPC_UNORDERED : ppc_cr_map[r-CMP_LOW];
+}
Index: libgcc/config/rs6000/trunctfk2.c
===================================================================
--- libgcc/config/rs6000/trunctfk2.c	(revision 0)
+++ libgcc/config/rs6000/trunctfk2.c	(revision 0)
@@ -0,0 +1,65 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Convert IBM long double to IEEE 128-bit floating point.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+extern __float128 __trunctfkf2 (__ibm128);
+
+#ifdef __LITTLE_ENDIAN__
+#define HIGH_WORD	1
+#define LOW_WORD	0
+#else
+#define HIGH_WORD	0
+#define LOW_WORD	1
+#endif
+
+__float128
+__trunctfkf2 (__ibm128 value)
+{
+  double high = __builtin_unpack_longdouble (value, HIGH_WORD);
+  double low = __builtin_unpack_longdouble (value, LOW_WORD);
+
+  /* Handle the special cases of NAN and inifinity.  */
+  if (__builtin_isnan (high) || __builtin_isinf (high))
+    return (__float128) high;
+
+  /* If low is 0.0, there no need to do the add.  In addition, avoiding the add
+     produces the correct sign if high is -0.0.  */
+  if (low == 0.0)
+    return (__float128) high;
+
+  return ((__float128)high) + ((__float128)low);
+}
Index: libgcc/config/rs6000/quad-float128.h
===================================================================
--- libgcc/config/rs6000/quad-float128.h	(revision 0)
+++ libgcc/config/rs6000/quad-float128.h	(revision 0)
@@ -0,0 +1,72 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Quad Precision on the PowerPC.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* quad.h defines the TFtype type by:
+   typedef float TFtype __attribute__ ((mode (TF)));
+
+   This define forces it to use KFmode (aka, ieee 128-bit floating point).  */
+#define TF KF
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+#include <quad.h>
+
+/* Add prototypes of the library functions created.  In case the appropriate
+   int/long types are not declared in scope by the time quad.h is included,
+   provide our own version.  */
+typedef int	 SItype_ppc  __attribute__ ((__mode__ (__SI__)));
+typedef int	 DItype_ppc  __attribute__ ((__mode__ (__DI__)));
+typedef unsigned USItype_ppc __attribute__ ((__mode__ (__SI__)));
+typedef unsigned UDItype_ppc __attribute__ ((__mode__ (__DI__)));
+
+TFtype __addkf3 (TFtype, TFtype);
+TFtype __subkf3 (TFtype, TFtype);
+TFtype __mulkf3 (TFtype, TFtype);
+TFtype __divkf3 (TFtype, TFtype);
+TFtype __negkf2 (TFtype);
+CMPtype __cmpukf2 (TFtype, TFtype);
+CMPtype __eqkf2 (TFtype, TFtype);
+CMPtype __gekf2 (TFtype, TFtype);
+CMPtype __lekf2 (TFtype, TFtype);
+CMPtype __unordkf2 (TFtype, TFtype);
+TFtype __extendsfkf2 (float);
+TFtype __extenddfkf2 (double);
+float __trunckfsf2 (TFtype);
+double __trunckfdf2 (TFtype);
+SItype_ppc __fixkfsi (TFtype);
+DItype_ppc __fixkfdi (TFtype);
+USItype_ppc __fixunskfsi (TFtype);
+UDItype_ppc __fixunskfdi (TFtype);
+TFtype __floatsikf (SItype_ppc);
+TFtype __floatdikf (DItype_ppc);
+TFtype __floatunsikf (USItype_ppc);
+TFtype __floatundikf (UDItype_ppc);
Index: libgcc/config/rs6000/libgcc-glibc.ver
===================================================================
--- libgcc/config/rs6000/libgcc-glibc.ver	(revision 229390)
+++ libgcc/config/rs6000/libgcc-glibc.ver	(working copy)
@@ -71,3 +71,81 @@ GCC_4.2.0 {
   __gcc_qunord
 %endif
 }
+
+
+# IEEE 128-bit support (__float128) was introduced with GCC 6.0.
+
+%exclude {
+  __addkf3
+  __cmpukf2
+  __divkf3
+  __eqkf2
+  __extenddfkf2
+  __extendkftf2
+  __extendsfkf2
+  __fixkfdi
+  __fixkfsi
+  __fixkfti
+  __fixunskfdi
+  __fixunskfsi
+  __fixunskfti
+  __floattikf
+  __floatuntikf
+  __gekf2
+  __gtkf2
+  __lekf2
+  __ltkf2
+  __mulkf3
+  __negkf3
+  __nekf2
+  __orderedkf2
+  __sqrtkf3
+  __subkf3
+  __trunckfdf2
+  __trunckfsf2
+  __trunctfkf2
+  __uneqkf2
+  __ungekf2
+  __ungtkf2
+  __unlekf2
+  __unltkf2
+  __unordkf2
+}
+
+GCC_6.0.0 {
+  __addkf3
+  __cmpukf2
+  __divkf3
+  __eqkf2
+  __extenddfkf2
+  __extendkftf2
+  __extendsfkf2
+  __fixkfdi
+  __fixkfsi
+  __fixkfti
+  __fixunskfdi
+  __fixunskfsi
+  __fixunskfti
+  __floattikf
+  __floatuntikf
+  __gekf2
+  __gtkf2
+  __lekf2
+  __ltkf2
+  __mulkf3
+  __negkf3
+  __nekf2
+  __orderedkf2
+  __sqrtkf3
+  __subkf3
+  __trunckfdf2
+  __trunckfsf2
+  __trunctfkf2
+  __uneqkf2
+  __ungekf2
+  __ungtkf2
+  __unlekf2
+  __unltkf2
+  __unordkf2
+}
+
Index: libgcc/config/rs6000/t-float128
===================================================================
--- libgcc/config/rs6000/t-float128	(revision 0)
+++ libgcc/config/rs6000/t-float128	(revision 0)
@@ -0,0 +1,77 @@
+# Support for adding __float128 to the powerpc.
+
+# The standard 128-bit floating point support functions are TFmode.  Most
+# PowerPC targets use a long double format that has a pair of doubles to give
+# you more precision, but no extra expoenent range.  This long double format is
+# mostly compatible with the format used by the IBM XL compilers.  Some of the
+# names used by the IBM double-double format use TF in them, so we rename
+# all of the functions provided for the new IEEE 128-bit support.
+#
+# We use the TF functions in soft-fp for 128-bit floating point support, using
+# sed to transform the names in the files from TF names to KF names.
+
+# Emulator functions from the soft-fp directory
+fp128_softfp_funcs	= addkf3 subkf3 mulkf3 divkf3 \
+			  negkf2 eqkf2 gekf2 lekf2 unordkf2 \
+			  extendsfkf2 extenddfkf2 trunckfsf2 trunckfdf2 \
+			  fixkfsi fixkfdi fixunskfsi fixunskfdi \
+			  floatsikf floatdikf floatunsikf floatundikf
+
+fp128_softfp_src	= $(addsuffix .c,$(fp128_softfp_funcs))
+fp128_softfp_static_obj	= $(addsuffix $(objext),$(fp128_softfp_funcs))
+fp128_softfp_shared_obj	= $(addsuffix _s$(objext),$(fp128_softfp_funcs))
+fp128_softfp_obj	= $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj)
+
+# New functions
+fp128_ppc_funcs		= cmpukf2 extendkftf2 trunctfk2
+fp128_ppc_src		= $(addprefix $(srcdir)/config/rs6000/,$(addsuffix .c,$(fp128_ppc_funcs)))
+fp128_ppc_static_obj	= $(addsuffix $(objext),$(fp128_ppc_funcs))
+fp128_ppc_shared_obj	= $(addsuffix _s$(objext),$(fp128_ppc_funcs))
+fp128_ppc_obj		= $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj)
+
+# All functions
+fp128_funcs		= $(fp128_softfp_funcs) $(fp128_ppc_funcs)
+fp128_src		= $(fp128_softfp_src) $(fp128_ppc_src)
+fp128_obj		= $(fp128_softfp_obj) $(fp128_ppc_obj)
+fp128_sed		= $(srcdir)/config/rs6000/float128-sed
+fp128_dep		= $(fp128_sed) $(srcdir)/config/rs6000/t-float128
+
+fp128_includes		= $(srcdir)/soft-fp/double.h \
+			  $(srcdir)/soft-fp/op-1.h \
+			  $(srcdir)/soft-fp/op-4.h \
+			  $(srcdir)/soft-fp/op-common.h \
+			  $(srcdir)/soft-fp/single.h \
+			  $(srcdir)/soft-fp/extended.h \
+			  $(srcdir)/soft-fp/op-2.h \
+			  $(srcdir)/soft-fp/op-8.h \
+			  $(srcdir)/soft-fp/quad.h \
+			  $(srcdir)/soft-fp/soft-fp.h
+
+EXTRA_CLEAN		+= $(fp128_softfp_src)
+
+FP128_CFLAGS		 = -Wno-type-limits -mvsx -mfloat128 \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000
+
+$(fp128_obj)		 : INTERNAL_CFLAGS += $(FP128_CFLAGS)
+$(fp128_obj)		 : $(fp128_includes)
+$(fp128_obj)		 : $(srcdir)/config/rs6000/quad-float128.h
+
+$(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst kf,tf,$@) $(fp128_dep)
+	@src="$(srcdir)/soft-fp/$(subst kf,tf,$@)"; \
+	echo "Create $@"; \
+	(echo "/* file created from $$src */"; \
+	 echo; \
+	 sed -f $(fp128_sed) < $$src) > $@
+
+test:
+	@echo "fp128_src:"; \
+	for x in $(fp128_src); do echo "    $$x"; done; \
+	echo; \
+	echo "fp128_obj:"; \
+	for x in $(fp128_obj); do echo "    $$x"; done;
+
+# For now, only put it in the static library
+# LIB2ADD += $(fp128_src)
+
+LIB2ADD_ST += $(fp128_src)
Index: libgcc/config/rs6000/float128-sed
===================================================================
--- libgcc/config/rs6000/float128-sed	(revision 0)
+++ libgcc/config/rs6000/float128-sed	(revision 0)
@@ -0,0 +1,25 @@
+s/__addtf3/__addkf3/g
+s/__divtf3/__divkf3/g
+s/__eqtf2/__eqkf2/g
+s/__extenddftf2/__extenddfkf2/g
+s/__extendsftf2/__extendsfkf2/g
+s/__fixtfdi/__fixkfdi/g
+s/__fixtfsi/__fixkfsi/g
+s/__fixunstfdi/__fixunskfdi/g
+s/__fixunstfsi/__fixunskfsi/g
+s/__floatditf/__floatdikf/g
+s/__floatsitf/__floatsikf/g
+s/__floatunditf/__floatundikf/g
+s/__floatunsitf/__floatunsikf/g
+s/__getf2/__gekf2/g
+s/__gttf2/__gtkf2/g
+s/__letf2/__lekf2/g
+s/__lttf2/__ltkf2/g
+s/__multf3/__mulkf3/g
+s/__negtf2/__negkf2/g
+s/__netf2/__nekf2/g
+s/quad[.]h/quad-float128.h/g
+s/__subtf3/__subkf3/g
+s/__trunctfdf2/__trunckfdf2/g
+s/__trunctfsf2/__trunckfsf2/g
+s/__unordtf2/__unordkf2/g
Index: libgcc/configure
===================================================================
--- libgcc/configure	(revision 229390)
+++ libgcc/configure	(working copy)
@@ -4766,6 +4766,29 @@ esac
 ;;
 esac
 
+case ${host} in
+powerpc*-*-linux*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do __float128" >&5
+$as_echo_n "checking whether the PowerPC compiler can do __float128... " >&6; }
+if test "${libgcc_cv_powerpc_float128+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#pragma GCC target ("vsx,float128")
+     __float128 add (__float128 *a) { return *a + *(a+1); }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_powerpc_float128=yes
+else
+  libgcc_cv_powerpc_float128=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128" >&5
+$as_echo "$libgcc_cv_powerpc_float128" >&6; }
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems)
  2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
                       ` (18 preceding siblings ...)
  2015-10-27 22:27     ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Michael Meissner
@ 2015-10-27 22:35     ` Michael Meissner
  2015-10-29 14:08       ` Segher Boessenkool
  19 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-10-27 22:35 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

[-- Attachment #1: Type: text/plain, Size: 867 bytes --]

This is the final patch that enables __float128 by default on systems that
support the VSX instruction set (power7, power8).  In addition, I added two
runtime tests to verify that __float128 runs, and gives more precision than
double.

Once all of the sub-patches for patch #7 for gcc and patch #8 for libgcc are
installed, is this patch ok to check into trunk?

[gcc]
2015-10-27  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-cpus.def (ISA_2_6_MASKS_SERVER): Add
	-mfloat128.

[gcc/testsuite]
2015-10-27  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/float128-1.c: New test for IEEE 128-bit
	floating point support.
	* gcc.target/powerpc/float128-2.c: Likewise.


-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch09b --]
[-- Type: text/plain, Size: 8882 bytes --]

Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(revision 229203)
+++ gcc/config/rs6000/rs6000-cpus.def	(working copy)
@@ -46,6 +46,7 @@
 				 | OPTION_MASK_ALTIVEC			\
 				 | OPTION_MASK_FLOAT128			\
 				 | OPTION_MASK_VSX			\
+				 | OPTION_MASK_FLOAT128			\
 				 | OPTION_MASK_UPPER_REGS_DF)
 
 /* For now, don't provide an embedded version of ISA 2.07.  */
Index: gcc/testsuite/gcc.target/powerpc/float128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
@@ -0,0 +1,149 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+#ifdef DEBUG
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+
+#if !defined(__FLOAT128__) || !defined(_ARCH_PPC)
+static __float128
+pass_through (__float128 x)
+{
+  return x;
+}
+
+__float128 (*no_optimize) (__float128) = pass_through;
+#endif
+
+#ifdef DEBUG
+__attribute__((__noinline__))
+static void
+print_f128 (__float128 x)
+{
+  unsigned sign;
+  unsigned exponent;
+  uint64_t mantissa1;
+  uint64_t mantissa2;
+  uint64_t upper;
+  uint64_t lower;
+
+#if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__)
+  struct ieee128 {
+    uint64_t upper;
+    uint64_t lower;
+  };
+
+#elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__)
+  struct ieee128 {
+    uint64_t lower;
+    uint64_t upper;
+  };
+
+#else
+#error "Unknown system"
+#endif
+
+  union {
+    __float128 f128;
+    struct ieee128 s128;
+  } u;
+
+  u.f128 = x;
+  upper  = u.s128.upper;
+  lower  = u.s128.lower;
+
+  sign      = (unsigned)((upper >> 63) & 1);
+  exponent  = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1));
+  mantissa1 = (upper & ((((uint64_t)1) << 48) - 1));
+  mantissa2 = lower;
+
+  printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64,
+	  sign ? '-' : '+',
+	  exponent,
+	  mantissa1,
+	  mantissa2);
+}
+#endif
+
+__attribute__((__noinline__))
+static void
+do_test (__float128 expected, __float128 got, const char *name)
+{
+  int equal_p = (expected == got);
+
+#ifdef DEBUG
+  printf ("Test %s, expected: ", name);
+  print_f128 (expected);
+  printf (" %5g, got: ", (double) expected);
+  print_f128 (got);
+  printf (" %5g, result %s\n",
+	  (double) got,
+	  (equal_p) ? "equal" : "not equal");
+#endif
+
+  if (!equal_p)
+    __builtin_abort ();
+}
+
+
+int
+main (void)
+{
+  __float128 one	= 1.0q;
+  __float128 two	= 2.0q;
+  __float128 three	= 3.0q;
+  __float128 four	= 4.0q;
+  __float128 five	= 5.0q;
+  __float128 add_result = (1.0q + 2.0q);
+  __float128 mul_result = ((1.0q + 2.0q) * 3.0q);
+  __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q);
+  __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q);
+  __float128 neg_result = - sub_result;
+  __float128 add_xresult;
+  __float128 mul_xresult;
+  __float128 div_xresult;
+  __float128 sub_xresult;
+  __float128 neg_xresult;
+
+#if defined(__FLOAT128__) && defined(_ARCH_PPC)
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (one));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (two));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (three));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (four));
+  __asm__ (" #prevent constant folding, %x0" : "+wa" (five));
+
+#else
+  one   = no_optimize (one);
+  two   = no_optimize (two);
+  three = no_optimize (three);
+  four  = no_optimize (four);
+  five  = no_optimize (five);
+#endif
+
+  add_xresult = (one + two);
+  do_test (add_result, add_xresult, "add");
+
+  mul_xresult = add_xresult * three;
+  do_test (mul_result, mul_xresult, "mul");
+
+  div_xresult = mul_xresult / four;
+  do_test (div_result, div_xresult, "div");
+
+  sub_xresult = div_xresult - five;
+  do_test (sub_result, sub_xresult, "sub");
+
+  neg_xresult = - sub_xresult;
+  do_test (neg_result, neg_xresult, "neg");
+
+#ifdef DEBUG
+  printf ("Passed\n");
+#endif
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/float128-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-2.c	(revision 0)
@@ -0,0 +1,228 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+/*
+ * Test program to make sure we are getting more precision than the 53 bits we
+ * get with IEEE double.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+#ifndef NO_INLINE
+#define NO_INLINE __attribute__((__noinline__))
+#endif
+
+static TYPE power_of_two (ssize_t) NO_INLINE;
+static TYPE calc1 (TYPE) NO_INLINE;
+static TYPE calc2 (TYPE) NO_INLINE;
+static TYPE calc3 (TYPE) NO_INLINE;
+
+#ifndef POWER2
+#define POWER2 60
+#endif
+
+\f
+/*
+ * Print TYPE in hex.
+ */
+
+
+#if defined(DEBUG) || defined(DEBUG2)
+static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE;
+
+#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__)
+#define ENDIAN_REVERSE(N, MAX)        ((MAX) - 1 - (N))
+
+#else
+#define ENDIAN_REVERSE(N, MAX)        (N)
+#endif
+
+static void
+print_hex (const char *prefix, TYPE value, const char *suffix)
+{
+  union {
+    TYPE f128;
+    unsigned char uc[sizeof (TYPE)];
+  } u;
+
+  size_t i;
+
+  u.f128 = value;
+  printf ("%s0x", prefix);
+  for (i = 0; i < sizeof (TYPE); i++)
+    printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]);
+
+  printf (", %24.2Lf%s", (long double)value, suffix);
+}
+#endif
+
+\f
+/*
+ * Return a power of two.
+ */
+
+static TYPE
+power_of_two (ssize_t num)
+{
+  TYPE ret = (TYPE) 1.0;
+  ssize_t i;
+
+  if (num >= 0)
+    {
+      for (i = 0; i < num; i++)
+	ret *= (TYPE) 2.0;
+    }
+  else
+    {
+      ssize_t num2 = -num;
+      for (i = 0; i < num2; i++)
+	ret /= (TYPE) 2.0;
+    }
+
+#ifdef DEBUG
+  printf ("power_of_two (%2ld)   = ", (long) num);
+  print_hex ("", ret, "\n");
+#endif
+
+  return ret;
+}
+
+\f
+#ifdef ADDSUB
+static TYPE add (TYPE a, TYPE b) NO_INLINE;
+static TYPE sub (TYPE a, TYPE b) NO_INLINE;
+
+static TYPE
+add (TYPE a, TYPE b)
+{
+  TYPE c;
+#ifdef DEBUG
+  print_hex ("add, arg1           = ", a, "\n");
+  print_hex ("add, arg2           = ", b, "\n");
+#endif
+  c = a + b;
+#ifdef DEBUG
+  print_hex ("add, result         = ", c, "\n");
+#endif
+  return c;
+}
+
+static TYPE
+sub (TYPE a, TYPE b)
+{
+  TYPE c;
+#ifdef DEBUG
+  print_hex ("sub, arg1           = ", a, "\n");
+  print_hex ("sub, arg2           = ", b, "\n");
+#endif
+  c = a - b;
+#ifdef DEBUG
+  print_hex ("sub, result         = ", c, "\n");
+#endif
+  return c;
+}
+
+#else
+#define add(x, y) ((x) + (y))
+#define sub(x, y) ((x) - (y))
+#endif
+
+/*
+ * Various calculations.  Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should
+ * get the original value.
+ */
+
+static TYPE
+calc1 (TYPE num)
+{
+  TYPE num2 = add (power_of_two (POWER2), num);
+  TYPE ret;
+
+#ifdef DEBUG
+  print_hex ("calc1 (before call) = ", num2, "\n");
+#endif
+
+  ret = calc2 (num2);
+
+#ifdef DEBUG
+  print_hex ("calc1 (after call)  = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+static TYPE
+calc2 (TYPE num)
+{
+  TYPE num2 = sub (num, power_of_two (POWER2-1));
+  TYPE ret;
+
+#ifdef DEBUG
+  print_hex ("calc2 (before call) = ", num2, "\n");
+#endif
+
+  ret = calc3 (num2);
+
+#ifdef DEBUG
+  print_hex ("calc2 (after call)  = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+static TYPE
+calc3 (TYPE num)
+{
+  TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2)));
+
+#ifdef DEBUG
+  print_hex ("calc3               = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+\f
+int
+main (void)
+{
+  TYPE input, output;
+
+#ifdef DEBUG
+  printf ("Testing, %ld bytes\n", (long) sizeof (TYPE));
+#endif
+
+  input = power_of_two (-1);
+  if ((double)input != 0.5)
+    {
+#if defined(DEBUG) || defined(DEBUG2)
+      print_hex ("Input should be 0.5:  ", output, "\n");
+      return 1;
+#else
+      __builtin_abort ();
+#endif
+    }
+
+  output = calc1 (input);
+  if ((double)output != 0.5)
+    {
+#if defined(DEBUG) || defined(DEBUG2)
+      print_hex ("Output should be 0.5: ", output, "\n");
+      return 1;
+#else
+      __builtin_abort ();
+#endif
+    }
+
+  return 0;
+}

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits)
  2015-10-27 22:27     ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Michael Meissner
@ 2015-10-27 23:39       ` Joseph Myers
  2015-11-03 22:17         ` Michael Meissner
  0 siblings, 1 reply; 78+ messages in thread
From: Joseph Myers @ 2015-10-27 23:39 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

This patch does not take account of the issues with the powerpc-specific 
functions that I pointed out in 
<https://sourceware.org/ml/libc-alpha/2015-10/msg00921.html> when they 
were posted to libc-alpha.  (Testcases covering those issues would be a 
good idea to put in the testsuite.)

The patch is also missing the sfp-machine.h changes to integrate with 
hardware exceptions and rounding modes (see what x86 does to get that 
support for __float128, for example - while you need to read 
floating-point state to get the rounding mode, you don't need to write it 
explicitly to raise exceptions as you can do that with appropriate 
computations on double that raise the same exceptions) - as previously 
noted to be missing in 
<https://gcc.gnu.org/ml/gcc-patches/2014-05/msg00105.html> and 
<https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01768.html>.  Roughly, you 
need to define _FP_DECL_EX FP_INIT_ROUNDMODE FP_RND_* (if the defaults 
aren't right for powerpc) FP_EX_* FP_HANDLE_EXCEPTIONS 
FP_TRAPPING_EXCEPTIONS FP_ROUNDMODE.

I don't think you need the %exclude in libgcc-glibc.ver, because the 
existing .ver files won't have any mention of KFmode functions; %exclude 
should only be relevant if a mode with an old standard name is newly 
supported.

You're listing conversions between KFmode and TImode in libgcc-glibc.ver.  
Those should indeed be in libgcc (when building 64-bit code, since TImode 
isn't supported for 32-bit code).  But I don't see anything in t-float128 
that would actually cause such functions to be built - do they actually 
end up in your library?  (I'd expect you to need conditional code to add 
them.)

Are you doing all comparisons with __cmpukf2 and __cmpokf2, or with a load 
of other functions as well?  Right now you're building in eqkf2 gekf2 
lekf2 unordkf2, and list yet more such functions e.g. __orderedkf2 
__ungtkf2 in libgcc-glibc.ver.

I'd expect libgcc-glibc.ver to need conversions from all of SImode, DImode 
and TImode (signed and unsigned) to KFmode, not just the TImode 
conversions currently listed there.

I think you should enable existing __float128 testcases for powerpc 
targets supporting float128, where they don't have anything x86-specific.  
This might help show up any missing or broken libgcc functions.  
Especially the fp-int-convert-float128-* tests.  I suppose you need to 
change e.g.

/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */

to

/* { dg-do run { target { float128 } } } */
/* { dg-add-options float128 } */

where float128 is a new effective-target, and a new dg-add-options case to 
add -mvsx in the powerpc case.  (Well, you need more than that, so that in 
the powerpc case without VSX runtime support you compile but not execute, 
but you get the idea.)

(Some of the existing tests may be under gcc.dg, some under gcc.target.  
A few may actually be architecture-specific, e.g. 
float128-truncdf-underflow.c is not applicable to powerpc because powerpc 
uses before-rounding tininess detection, and anything involving __float80 
/ x86 long double likewise, but most should be applicable to powerpc.  
Some, e.g. float128-exact-underflow.c, may apply to powerpc but require a 
glibc target for trapping exceptions, so they need to have an appropriate 
target constraint in addition to the above.)

Testcase enablement can reasonably be a separate patch from libgcc 
support, but I think it's an important part of actually having much 
confidence that the feature is working properly.

Will there be a separate patch to cause __mulkc3 and __divkc3 (complex 
arithmetic, using existing libgcc2.c code for a new mode) to be built?  
There's also the matter of __powikf2 (I'm not sure if calls to that can be 
generated right now without new built-in functions, or not).

Are conversions between KFmode and decimal floating point being deferred 
for now (which seems reasonable, as I said in 
<https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01894.html> - those in 
dfp-bit.c rely on strtod / sprintf, which of course won't work as an 
approach for KFmode)?

x86 has a minimal set of built-in functions for __float128, __builtin_infq 
__builtin_huge_valq __builtin_fabsq __builtin_copysignq.  Unless I've 
missed it, you don't seem to have these for powerpc.  (They are needed for 
the libgcc2.c complex arithmetic functions.)

Another thing that would help find missing libgcc functions is enabling 
libquadmath for powerpc (building with -mvsx) - though there isn't a 
libquadmath testsuite - missing functions would mean it fails to link 
(though this wouldn't find more obscure missing functions such as TImode 
conversions).

Enabling libquadmath has another advantage: it's reasonably 
straightforward, meaning users can get those functions through libquadmath 
with GCC 6 in the near future.  While getting *f128 functions in glibc is 
the desired long-term goal, (a) it also involves a long and fiddly process 
of design, consensus building and implementing many 
architecture-independent glibc patches to fully support additional 
floating-point types in accordance with a clean agreed design, and (b) 
adding such functions to glibc for powerpc (as opposed to adding them for 
x86 / x86_64 to work out design issues) requires consensus that building 
glibc for powerpc can require a GCC version with support for __float128, 
and even if __float128 support is backported to any past release branches, 
I expect it will be a while before the glibc community is willing to 
require such a recent version (we've only today moved to requiring a 
minimum of GCC 4.7 to build glibc, and even that was controversial).

(The libquadmath code is three years out of date with respect to glibc, 
which has had many relevant fixes in the past three years.  You could talk 
to the libquadmath maintainers about getting it updated, which shouldn't 
be hard and should be OK while trunk is in bug-fixing mode.)

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems)
  2015-10-27 22:35     ` [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems) Michael Meissner
@ 2015-10-29 14:08       ` Segher Boessenkool
  2015-10-29 19:02         ` Joseph Myers
  2015-10-29 21:09         ` Michael Meissner
  0 siblings, 2 replies; 78+ messages in thread
From: Segher Boessenkool @ 2015-10-29 14:08 UTC (permalink / raw)
  To: Michael Meissner, gcc-patches, dje.gcc

Hi!

On Tue, Oct 27, 2015 at 06:31:41PM -0400, Michael Meissner wrote:
> Index: gcc/testsuite/gcc.target/powerpc/float128-1.c
> ===================================================================
> --- gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
> +++ gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
> @@ -0,0 +1,149 @@
> +/* { dg-do run { target { powerpc*-*-linux* } } } */
> +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
> +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */

Some of this is redundant.  Should this really be linux-only?
The second line doesn't do anything then.  { "*" } { "" } isn't
needed either.

In general, please only add dg-skip-if if you know it is needed.

There probably should be an effective-target for float128.


Segher

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01
  2015-10-23 17:30     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01 Michael Meissner
@ 2015-10-29 14:28       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:28 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:26 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch is the rs6000.h changes. It makes the IEEE 128-bit floating point
> type that can go in vector registers a 'vector' type, so that the address code
> in rs6000.c that determines whether to use VSX addressing works. In addition, I
> made IEEE 128-bit floating point tie with vectors and not with other scalar
> floats.
>
> I have built the compiler with this patch applied, and run bootstrap and
> regression tests with all of the patches installed.  Is it ok to install on the
> trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.h (ALTIVEC_VECTOR_MODE): Add IEEE 128-bit
>         floating point modes that can go in vector registers.
>         (MODES_TIEABLE_P): Move tests for vector modes before tests for
>         scalar floating point, so that IEEE 128-bit floating point that
>         can go in vector registers bind with vectors and not FP.
>         (struct rs6000_args): Add libcall field.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #03
  2015-10-23 17:35     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #03 Michael Meissner
@ 2015-10-29 14:29       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:29 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:33 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch defines 3 macros to tell the user whether -mfloat128 is enabled or
> not, and whether long double is IBM extended double or IEEE 128-bit floating
> point.
>
> I have built the compiler with this patch and the previous subpatches (1 and
> 2).  I have bootstrapped the compiler with all 16 subpatches installed, and
> there were no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
>         __FLOAT128__ if -mfloat128. Define __LONG_DOUBLE_IEEE128__ if long
>         double is IEEE 128-bit. Define __LONG_DOUBLE_IBM128__ if long
>         double is IBM extended double.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #02
  2015-10-23 17:31     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #02 Michael Meissner
@ 2015-10-29 14:29       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:29 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:30 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch changes the switch from -mfloat128-software and -mfloat128-none to
> be a binary switch, -mfloat128 and -mno-float128.  It also provides some of the
> basic setup for IEEE types.  It also removes code I had put in a previous patch
> that doesn't allow IFmode/KFmode to go in any register if -mno-float128 (this
> causes some reload problems).
>
> I have built the compiler with this patch and subpatch #1 installed.  I have
> built the compiler with all 16 subpatches and had no regressions.  Is this
> patch ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.opt (-mfloat128-*): Delete -mfloat128-none
>         and -mfloat128-software switches.  Replace them with a binary
>         -mfloat128 switch.
>         (-mfloat128): Likewise.
>
>         * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow
>         128-bit floating point types in GPRs, even if the appropriate
>         option enabling the type was not used.
>         (rs6000_debug_reg_global): Remove -mfloat128-{software,none}
>         debugging.
>         (rs6000_setup_reg_addr_masks): Do not allow pre-increment and
>         pre-decrement on IEEE 128-bit floating point values.
>         (rs6000_init_hard_regno_mode_ok): Change test for whether TFmode
>         is IEEE 128-bit floating point.
>         (rs6000_init_hard_regno_mode_ok): Add reload handlers for IEEE
>         128-bit floating point types that can go in vector registers.
>         (rs6000_option_override_internal): Change -mfloat128-none and
>         -mfloat128-software to -mfloat128, and move code to be near other
>         VSX option handling.
>         (rs6000_option_override_internal): Disable -mfloat128 if we don't
>         have the Altivec ABI.
>         (rs6000_init_builtins): Don't make TFmode use either IFmode or
>         KFmode floating point nodes. Instead, have three separate nodes.
>         (rs6000_scalar_mode_supported_p): Add support for IFmode to allow
>         eventually moving the long double default to IEEE 128-bit floating
>         point.
>         (rs6000_opt_masks): Add -mfloat128.
>         (struct rs6000_opt_var): Fix typo in comment.
>
>         * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add -mfloat128 as
>         an option that can be turned on via -mcpu=<xxx>.
>
>         * config/rs6000/rs6000-opts.h (enum float128_type_t): Delete, no
>         longer used.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04
  2015-10-23 17:38     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04 Michael Meissner
  2015-10-23 20:24       ` Michael Meissner
@ 2015-10-29 14:29       ` David Edelsohn
  1 sibling, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:29 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:36 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch allows SUBREG's for the reg_or_indexed_operand, which is used when
> you have an integral value in a float/vector register, and you want to move the
> value (either via direct move on power8, or via store).
>
> I have built the compiler with this patch and the previous subpatches (1-3).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/predicates.md (reg_or_indexed_operand): Allow
>         SUBREGs.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05
  2015-10-23 17:39     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 Michael Meissner
  2015-10-23 18:08       ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 (patch included) Michael Meissner
@ 2015-10-29 14:33       ` David Edelsohn
  1 sibling, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:33 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:39 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch prevents the compiler from calling the IEEE 128-bit emulation
> functions with the vector value in both GPRs and vector registers due to the
> fact that the library function did not have a prototype.
>
> I have built the compiler with this patch and the previous subpatches (1-4).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (init_cumulative_args): Initialize
>         libcall field in CUMULATIVE_ARGS.
>         (rs6000_function_arg): Treat library functions as if they had
>         prototypes to prevent IEEE 128-bit support functions from passing
>         arguments in both GPRs and vector registers.
>         (rs6000_arg_partial_bytes): Likewise.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06
  2015-10-23 17:44     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06 Michael Meissner
@ 2015-10-29 14:36       ` David Edelsohn
  2015-10-29 17:56         ` Michael Meissner
  0 siblings, 1 reply; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:36 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches, David Edelsohn

On Fri, Oct 23, 2015 at 1:40 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch sets up all of the emulation functions.
>
> I have built the compiler with this patch and the previous subpatches (1-4).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (rs6000_init_libfuncs): Split libfunc
>         setup into 3 functions: init_float128_ibm, init_float128_ieee, and
>         rs6000_init_libfuncs. If -mfloat128, add IFmode functions for all
>         of the traditional names that TFmode uses for handling IEEE
>         extended double. If -mfloat128, add KFmode functions for all of
>         the emulation functions. If -mabi=ieeelongdouble and -mfloat128,
>         make TFmode use the same emulation functions as KFmode.
>         (init_float128_ibm): Likewise.
>         (init_float128_ieee): Likewise.

This seems to change the logic for initializing Darwin and AIX
libfuncs.  It may not be wrong, but I am a little concerned.  I
believe that they were defined unconditionally before and now they
only are defined if TARGET_LONG_DOUBLE_128.

Am I misunderstanding something?

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07
  2015-10-23 17:45     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07 Michael Meissner
@ 2015-10-29 14:36       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:36 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:43 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch updates to use the unordered comparison function for IEEE 128-bit
> floating point to mimic the behaviour of SFmode/DFmode using the fcmpu
> instruction.
>
> It also restructures the code to allow a future change to drop in easier.
>
> I have built the compiler with this patch and the previous subpatches (1-6).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (rs6000_generate_compare): For IEEE
>         128-bit floating point comparisons, call the unordered comparison
>         function instead of the ordered comparison function.
>         (rs6000_expand_float128_convert): Deal with operands that are
>         memory operands. Restructure the code to use a switch statement on
>         the mode. Add support for TFmode defaulting to either IBM extended
>         double or IEEE 128-bit floating point. If the underlying types are
>         the same, use a move instead of a conversion function.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #08
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #08 Michael Meissner
@ 2015-10-29 14:38       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:38 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:45 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch adds support for using 'q' or 'Q' as a suffix for __float128
> constants, which is compatible with the existing x86_64 implmenetation of their
> __float128 support.
>
> I have built the compiler with this patch and the previous subpatches (1-7).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (TARGET_C_MODE_FOR_SUFFIX): Define 'q'
>         and 'Q' as the suffix to use for IEEE 128-bit floating point
>         constants with -mfloat128.
>         (rs6000_c_mode_for_suffix): Likewise.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09
  2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09 Michael Meissner
  2015-10-23 20:17       ` Joseph Myers
@ 2015-10-29 14:39       ` David Edelsohn
  1 sibling, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:39 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:47 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch is the new patch from the last submission. It sets up a hook so that
> the compiler will not allow IBM extended double and IEEE 128-bit floating point
> to intermix in a binary expression without using an explicit conversion.
>
> I have built the compiler with this patch and the previous subpatches (1-8).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (TARGET_INVALID_BINARY_OP): Do not allow
>         inter-mixing of IEEE 128-bit floating point with IBM extended
>         double floating point.
>         (rs6000_invalid_binary_op): Likewise.

Okay.  Assuming that Joseph's concerns are addressed in subsequent patches.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #10
  2015-10-23 17:52     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #10 Michael Meissner
@ 2015-10-29 14:40       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:40 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:49 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch is part of the support needed to properly swap IEEE 128-bit floating
> point on little endian systems.  Note, you will need the rs6000.md changes for
> this to become effective.
>
> I have built the compiler with this patch and the previous subpatches (1-9).  I
> have bootstrapped the compiler with all 16 subpatches installed, and there were
> no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (rs6000_gen_le_vsx_permute): On little
>         endian systems generate a ROTATE insn instead of VEC_SELECT for
>         IEEE 128-bit floating point types that can go in vector
>         registers.
>         (chain_contains_only_swaps): Properly swap IEEE 128-bit floating
>         point types that can go in vector registers on little endian
>         PowerPC systems.
>         (mark_swaps_for_removal): Likewise.
>         (rs6000_analyze_swaps): Likewise.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #11
  2015-10-23 17:57     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #11 Michael Meissner
@ 2015-10-29 14:42       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:42 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:52 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch changes the mangling for __float128.  I came to the conclusion that
> the current code is so tangled, that it would be better to use U10__float128
> rather than "e".  However, if it is felt that we should go with "e", I can go
> that way as well.
>
> I have built the compiler with this patch and the previous subpatches (1-10).
> I have bootstrapped the compiler with all 16 subpatches installed, and there
> were no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.c (rs6000_mangle_type): Use U10__float128
>         for IEEE 128-bit floating point.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #12
  2015-10-23 17:58     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #12 Michael Meissner
@ 2015-10-29 14:44       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:44 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:57 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch is the first of two rs6000.md patches to straighten out the IFmode,
> KFmode, and TFmode support.  Part of the change is to change the iterator names
> to be easier to understand, using IEEE128, IBM128, and FLOAT128 as the
> iterators.  This change, and the next change go through and have parallel insns
> for handling IFmode and TFmode (when -mabi=ibmlongdouble) for IBM extended
> double, and for handling KFmode and TFmode (when -mabi=ieeelongdouble).  The
> idea is to prepare the way in GCC 7.0 to change the default for long double.
>
> I have built the compiler with this patch and the previous subpatches (1-11).
> I have bootstrapped the compiler with all 16 subpatches installed, and there
> were no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.md (FLOAT128_SFDFTF): Delete iterator,
>         rework IEEE 128-bit floating point insns to deal with TFmode being
>         either IBM extended double or IEEE 128-bit floating point.
>         (IFKF): Likewise.
>         (IBM128): Update iterator to add condition that the mode is IBM
>         extended double.
>         (IEEE128): New iterator for IEEE 128-bit floating point.
>         (TFIFKF): Rename TFIFKF iterator to FLOAT128.
>         (FLOAT128): Likewise.
>         (signbit<mode>2): FLOAT128_IBM_P condition test moved into IBM128
>         iterator.
>         (neg<mode>2): Replace TFIFKF iterator with FLOAT128. Add support
>         for TFmode being IEEE 128-bit floating point. Use IEEE128 iterator
>         instead of hard coding TFmode or KFmode.
>         (negtf2_internal): Likewise.
>         (neg<mode>2_internal): Likewise.
>         (abs<mode>2): Likewise.
>         (abstf2_internal): Likewise.
>         (abs<mode>2_internal): Likewise.
>         (ieee_128bit_neg<mode>2): Likewise.
>         (ieee_128bit_neg<mode>2_internal): Likewise.
>         (ieee_128bit_abs<mode>2): Likewise.
>         (ieee_128bit_abs<mode>2_internal): Likewise.
>         (ieee_128bit_nabs<mode>2): Likewise.
>         (ieee_128bit_nabs<mode>2_internal): Likewise.
>         (extendiftf2): Add explicit conversions between 128-bit floating
>         point types. Drop the old conversions that had become unwieldy.
>         (extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise.
>         (extendifkf2): Likewise.
>         (trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise.
>         (extendtfkf2): Likewise.
>         (fix_trunc<IFKF:mode><SDI:mode>2): Likewise.
>         (trunciftf2): Likewise.
>         (fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise.
>         (truncifkf2): Likewise.
>         (float<SDI:mode><IFKF:mode>2): Likewise.
>         (trunckftf2): Likewise.
>         (floatuns<SDI:mode><IFKF:mode>2): Likewise.
>         (trunctfif2): Likewise.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #13
  2015-10-23 18:00     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #13 Michael Meissner
@ 2015-10-29 14:46       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:46 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 1:58 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch is the second part to allow TFmode to be IBM extended double or IEEE
> 128-bit floating point depending on switches.
>
> I have built the compiler with this patch and the previous subpatches (1-12).
> I have bootstrapped the compiler with all 16 subpatches installed, and there
> were no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.md (FP iterator): Allow TFmode to be IEEE
>         128-bit floating point.
>         (extenddftf2): Rework 128-bit floating point conversions to
>         properly handle -mabi=ieeelongdouble. Merge IFmode, TFmode, and
>         KFmode expanders into one function.
>         (extenddf<mode>2): Likewise.
>         (extenddftf2_fprs): Likewise.
>         (extenddf<mode>2_fprs): Likewise.
>         (extenddftf2_vsx): Likewise.
>         (extenddf<mode>2_vsx): Likewise.
>         (extendsftf2): Likewise.
>         (extendsf<mode>2): Likewise.
>         (trunctfdf2): Likewise.
>         (trunc<mode>df2): Likewise.
>         (trunctfdf2_internal1): Likewise.
>         (trunc<mode>df2_internal1): Likewise.
>         (trunctfdf2_internal2): Likewise.
>         (trunc<mode>df2_internal2): Likewise.
>         (trunctfsf2): Likewise.
>         (trunc<mode>sf2): Likewise.
>         (trunctfsf2_fprs): Likewise.
>         (trunc<mode>sf2_fprs): Likewise.
>         (floatsit2f): Likewise.
>         (floatsi<mode>2): Likewise.
>         (fix_trunc_helper): Likewise.
>         (fix_trunc_helper<mode>): Likewise.
>         (fix_trunctfsi2): Likewise.
>         (fix_trunc<mode>si2): Likewise.
>         (fix_trunctfsi2_fprs): Likewise.
>         (fix_trunc<mode>si2_fprs): Likewise.
>         (fix_trunctfsi2_internal): Likewise.
>         (fix_trunc<mode>si2_internal): Likewise.
>         (fix_trunctfdi2): Likewise.
>         (fix_trunc<mode>di2): Likewise.
>         (fixuns_trunctf<mode>2): Likewise.
>         (fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
>         (floatditf2): Likewise.
>         (floatdi<mode>2): Likewise.
>         (floatuns<mode>tf2): Likewise.
>         (floatuns<SDI:mode><IEEE128:mode>): Likewise.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #14
  2015-10-23 18:01     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #14 Michael Meissner
@ 2015-10-29 14:46       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:46 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 2:00 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch makes TFmode be fully switchable for comparisons.
>
> I have built the compiler with this patch and the previous subpatches (1-13).
> I have bootstrapped the compiler with all 16 subpatches installed, and there
> were no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000.md (cmptf_internal1): Use a mode iterator
>         to add support for both types (IFmode, TFmode) that support IBM
>         extended double.
>         (cmp<mode>_internal1): Likewise.
>         (cmptf_internal2): Likewise.
>         (cmp<mode>_internal2): Likewise.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #15
  2015-10-23 18:03     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #15 Michael Meissner
@ 2015-10-29 14:50       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 14:50 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 2:01 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch adds the documentation.
>
> I have built the compiler with this patch and the previous subpatches (1-14).
> I have bootstrapped the compiler with all 16 subpatches installed, and there
> were no regressions.  Is it ok to install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * doc/extend.texi (Floating Types): Document __ibm128 and
>         __float128 on PowerPC.
>
>         * doc/invoke.texi (RS/6000 and PowerPC Options): Document
>         -mfloat128 and -mno-float128.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #16
  2015-10-23 18:04     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #16 Michael Meissner
@ 2015-10-29 15:02       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-10-29 15:02 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Fri, Oct 23, 2015 at 2:03 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch adds a test to make sure __float128 are passed and returned like
> vector objects, and not as IBM extended double did.
>
> This is the last subpatch of patch #7.  I have bootstrapped the compiler with
> all 16 subpatches installed, and there were no regressions.  Is it ok to
> install in the trunk?
>
> 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * gcc.target/powerpc/float128-call.c: New test for -mfloat128 on
>         PowerPC.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06
  2015-10-29 14:36       ` David Edelsohn
@ 2015-10-29 17:56         ` Michael Meissner
  0 siblings, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-29 17:56 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Michael Meissner, GCC Patches

On Thu, Oct 29, 2015 at 10:33:48AM -0400, David Edelsohn wrote:
> On Fri, Oct 23, 2015 at 1:40 PM, Michael Meissner
> <meissner@linux.vnet.ibm.com> wrote:
> > This patch sets up all of the emulation functions.
> >
> > I have built the compiler with this patch and the previous subpatches (1-4).  I
> > have bootstrapped the compiler with all 16 subpatches installed, and there were
> > no regressions.  Is it ok to install in the trunk?
> >
> > 2015-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
> >
> >         * config/rs6000/rs6000.c (rs6000_init_libfuncs): Split libfunc
> >         setup into 3 functions: init_float128_ibm, init_float128_ieee, and
> >         rs6000_init_libfuncs. If -mfloat128, add IFmode functions for all
> >         of the traditional names that TFmode uses for handling IEEE
> >         extended double. If -mfloat128, add KFmode functions for all of
> >         the emulation functions. If -mabi=ieeelongdouble and -mfloat128,
> >         make TFmode use the same emulation functions as KFmode.
> >         (init_float128_ibm): Likewise.
> >         (init_float128_ieee): Likewise.
> 
> This seems to change the logic for initializing Darwin and AIX
> libfuncs.  It may not be wrong, but I am a little concerned.  I
> believe that they were defined unconditionally before and now they
> only are defined if TARGET_LONG_DOUBLE_128.
> 
> Am I misunderstanding something?

No really, I just assumed if -mlong-double-64 you wouldn't be using TFmode.  I
can remove the test if you prefer.  BTW, Darwin has 128-bit long double (using
IBM extended double).

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems)
  2015-10-29 14:08       ` Segher Boessenkool
@ 2015-10-29 19:02         ` Joseph Myers
  2015-10-29 21:09         ` Michael Meissner
  1 sibling, 0 replies; 78+ messages in thread
From: Joseph Myers @ 2015-10-29 19:02 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Thu, 29 Oct 2015, Segher Boessenkool wrote:

> There probably should be an effective-target for float128.

Yes, as I said in 
<https://gcc.gnu.org/ml/gcc-patches/2015-10/msg02991.html> there needs to 
be standard test boilerplate to: disable a test if __float128 isn't 
supported at all even with extra options added; add those options on 
targets that support it provided the right options are added; and turn a 
run test to a compile test if the options are supported but the hardware 
support (for VSX in this case) is missing.  Then the tests that run for 
x86 and possibly ia64 targets (some of which may be under gcc.target at 
present) need to have their target restrictions replaced, being moved out 
of gcc.target as needed.

The tests using feenableexcept would then *also* require some suitable 
effective-target (or restriction to *-*-*gnu*) to restrict them to glibc 
targets.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems)
  2015-10-29 14:08       ` Segher Boessenkool
  2015-10-29 19:02         ` Joseph Myers
@ 2015-10-29 21:09         ` Michael Meissner
  1 sibling, 0 replies; 78+ messages in thread
From: Michael Meissner @ 2015-10-29 21:09 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Michael Meissner, gcc-patches, dje.gcc

On Thu, Oct 29, 2015 at 09:02:22AM -0500, Segher Boessenkool wrote:
> Hi!
> 
> On Tue, Oct 27, 2015 at 06:31:41PM -0400, Michael Meissner wrote:
> > Index: gcc/testsuite/gcc.target/powerpc/float128-1.c
> > ===================================================================
> > --- gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
> > +++ gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
> > @@ -0,0 +1,149 @@
> > +/* { dg-do run { target { powerpc*-*-linux* } } } */
> > +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
> > +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
> 
> Some of this is redundant.  Should this really be linux-only?
> The second line doesn't do anything then.  { "*" } { "" } isn't
> needed either.
> 
> In general, please only add dg-skip-if if you know it is needed.
> 
> There probably should be an effective-target for float128.

Well the normal VSX target should work.

Back when I was doing power7 development, there were problems with Darwin
and/or SPE ignoring the -mcpu=<xxx> option, so I've just cloned the code on
these tests ever since.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits)
  2015-10-27 23:39       ` Joseph Myers
@ 2015-11-03 22:17         ` Michael Meissner
  2015-11-03 22:53           ` Michael Meissner
                             ` (2 more replies)
  0 siblings, 3 replies; 78+ messages in thread
From: Michael Meissner @ 2015-11-03 22:17 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc, marcotq, sjmunroe

On Tue, Oct 27, 2015 at 11:38:48PM +0000, Joseph Myers wrote:
> This patch does not take account of the issues with the powerpc-specific 
> functions that I pointed out in 
> <https://sourceware.org/ml/libc-alpha/2015-10/msg00921.html> when they 
> were posted to libc-alpha.  (Testcases covering those issues would be a 
> good idea to put in the testsuite.)
> 
> The patch is also missing the sfp-machine.h changes to integrate with 
> hardware exceptions and rounding modes (see what x86 does to get that 
> support for __float128, for example - while you need to read 
> floating-point state to get the rounding mode, you don't need to write it 
> explicitly to raise exceptions as you can do that with appropriate 
> computations on double that raise the same exceptions) - as previously 
> noted to be missing in 
> <https://gcc.gnu.org/ml/gcc-patches/2014-05/msg00105.html> and 
> <https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01768.html>.  Roughly, you 
> need to define _FP_DECL_EX FP_INIT_ROUNDMODE FP_RND_* (if the defaults 
> aren't right for powerpc) FP_EX_* FP_HANDLE_EXCEPTIONS 
> FP_TRAPPING_EXCEPTIONS FP_ROUNDMODE.

Just to update you.  Tulio and Steve have been working on patches to include
exception support.  I will be submitting revised patches once things settle
down.  Note, Tulio will be on vacation for the next 2 weeks.

We also will be eliminating the __cmp{o,u}kf2 functions, and go back to the
__eqkf2, etc. like the other software emulation patches.  It isn't as simple to
just eliminate the define insn for cbranch... for the KFmodes, as it will
convert KFmode to TFmode and do that comparison.  I will be working on that,
along with the other non-IEEE work for GCC 6.

> I don't think you need the %exclude in libgcc-glibc.ver, because the 
> existing .ver files won't have any mention of KFmode functions; %exclude 
> should only be relevant if a mode with an old standard name is newly 
> supported.

Ok.

> You're listing conversions between KFmode and TImode in libgcc-glibc.ver.  
> Those should indeed be in libgcc (when building 64-bit code, since TImode 
> isn't supported for 32-bit code).  But I don't see anything in t-float128 
> that would actually cause such functions to be built - do they actually 
> end up in your library?  (I'd expect you to need conditional code to add 
> them.)

That fell through the cracks.  Thanks.

> Are you doing all comparisons with __cmpukf2 and __cmpokf2, or with a load 
> of other functions as well?  Right now you're building in eqkf2 gekf2 
> lekf2 unordkf2, and list yet more such functions e.g. __orderedkf2 
> __ungtkf2 in libgcc-glibc.ver.

The intention was to keep those to allow other compilers (XL, LLVM) to use
these functions for developing their own IEEE 128-bit support.  However, since
I posted the patch, those groups feel they cannot use the libgcc support due to
GPL licensing issues.

Since we will be returning to use those functions, I will eliminate the cmp*
file.

> I'd expect libgcc-glibc.ver to need conversions from all of SImode, DImode 
> and TImode (signed and unsigned) to KFmode, not just the TImode 
> conversions currently listed there.

I thought I had listed them.  Thanks.

> I think you should enable existing __float128 testcases for powerpc 
> targets supporting float128, where they don't have anything x86-specific.  
> This might help show up any missing or broken libgcc functions.  
> Especially the fp-int-convert-float128-* tests.  I suppose you need to 
> change e.g.

Yes, I plan to do that once the basic support is in.

> /* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */
> 
> to
> 
> /* { dg-do run { target { float128 } } } */
> /* { dg-add-options float128 } */
> 
> where float128 is a new effective-target, and a new dg-add-options case to 
> add -mvsx in the powerpc case.  (Well, you need more than that, so that in 
> the powerpc case without VSX runtime support you compile but not execute, 
> but you get the idea.)
> 
> (Some of the existing tests may be under gcc.dg, some under gcc.target.  
> A few may actually be architecture-specific, e.g. 
> float128-truncdf-underflow.c is not applicable to powerpc because powerpc 
> uses before-rounding tininess detection, and anything involving __float80 
> / x86 long double likewise, but most should be applicable to powerpc.  
> Some, e.g. float128-exact-underflow.c, may apply to powerpc but require a 
> glibc target for trapping exceptions, so they need to have an appropriate 
> target constraint in addition to the above.)
> 
> Testcase enablement can reasonably be a separate patch from libgcc 
> support, but I think it's an important part of actually having much 
> confidence that the feature is working properly.
> 
> Will there be a separate patch to cause __mulkc3 and __divkc3 (complex 
> arithmetic, using existing libgcc2.c code for a new mode) to be built?  
> There's also the matter of __powikf2 (I'm not sure if calls to that can be 
> generated right now without new built-in functions, or not).
> 
> Are conversions between KFmode and decimal floating point being deferred 
> for now (which seems reasonable, as I said in 
> <https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01894.html> - those in 
> dfp-bit.c rely on strtod / sprintf, which of course won't work as an 
> approach for KFmode)?
> 
> x86 has a minimal set of built-in functions for __float128, __builtin_infq 
> __builtin_huge_valq __builtin_fabsq __builtin_copysignq.  Unless I've 
> missed it, you don't seem to have these for powerpc.  (They are needed for 
> the libgcc2.c complex arithmetic functions.)

I haven't gotten to the builtin functions yet.  Those are a reasonable start.

> Another thing that would help find missing libgcc functions is enabling 
> libquadmath for powerpc (building with -mvsx) - though there isn't a 
> libquadmath testsuite - missing functions would mean it fails to link 
> (though this wouldn't find more obscure missing functions such as TImode 
> conversions).

Once the basic support is in, I was planning on looking at what is needed with
libquadmath.

> Enabling libquadmath has another advantage: it's reasonably 
> straightforward, meaning users can get those functions through libquadmath 
> with GCC 6 in the near future.  While getting *f128 functions in glibc is 
> the desired long-term goal, (a) it also involves a long and fiddly process 
> of design, consensus building and implementing many 
> architecture-independent glibc patches to fully support additional 
> floating-point types in accordance with a clean agreed design, and (b) 
> adding such functions to glibc for powerpc (as opposed to adding them for 
> x86 / x86_64 to work out design issues) requires consensus that building 
> glibc for powerpc can require a GCC version with support for __float128, 
> and even if __float128 support is backported to any past release branches, 
> I expect it will be a while before the glibc community is willing to 
> require such a recent version (we've only today moved to requiring a 
> minimum of GCC 4.7 to build glibc, and even that was controversial).
> 
> (The libquadmath code is three years out of date with respect to glibc, 
> which has had many relevant fixes in the past three years.  You could talk 
> to the libquadmath maintainers about getting it updated, which shouldn't 
> be hard and should be OK while trunk is in bug-fixing mode.)

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits)
  2015-11-03 22:17         ` Michael Meissner
@ 2015-11-03 22:53           ` Michael Meissner
  2015-11-14  0:02             ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits, revised) Michael Meissner
  2015-11-03 22:55           ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Mike Stump
  2015-11-03 23:41           ` Joseph Myers
  2 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-11-03 22:53 UTC (permalink / raw)
  To: Michael Meissner, Joseph Myers, gcc-patches, dje.gcc, sjmunroe, tulioqm

I had the wrong email address for Tulio.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits)
  2015-11-03 22:17         ` Michael Meissner
  2015-11-03 22:53           ` Michael Meissner
@ 2015-11-03 22:55           ` Mike Stump
  2015-11-03 23:41           ` Joseph Myers
  2 siblings, 0 replies; 78+ messages in thread
From: Mike Stump @ 2015-11-03 22:55 UTC (permalink / raw)
  To: Michael Meissner
  Cc: Joseph Myers, gcc-patches, David Edelsohn, marcotq, sjmunroe

On Nov 3, 2015, at 2:17 PM, Michael Meissner <meissner@linux.vnet.ibm.com> wrote:
> The intention was to keep those to allow other compilers (XL, LLVM) to use
> these functions for developing their own IEEE 128-bit support.  However, since
> I posted the patch, those groups feel they cannot use the libgcc support due to
> GPL licensing issues.

A contributor is free to write code, and contribute it to libgcc under the gcc license and to contribute it to llvm under their license.  That creates a mess, as bug fixes from one can’t always flow to the other, but if the code is perfect, then this will never happen.  If you want, you can see about an exception to include a different license on the code for gcc.  llvm generally handles this case by merely reimplmenting documented routines and putting them into compilerrt with a more permissive license.

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits)
  2015-11-03 22:17         ` Michael Meissner
  2015-11-03 22:53           ` Michael Meissner
  2015-11-03 22:55           ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Mike Stump
@ 2015-11-03 23:41           ` Joseph Myers
  2 siblings, 0 replies; 78+ messages in thread
From: Joseph Myers @ 2015-11-03 23:41 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc, sjmunroe, tulioqm

On Tue, 3 Nov 2015, Michael Meissner wrote:

> > Another thing that would help find missing libgcc functions is enabling 
> > libquadmath for powerpc (building with -mvsx) - though there isn't a 
> > libquadmath testsuite - missing functions would mean it fails to link 
> > (though this wouldn't find more obscure missing functions such as TImode 
> > conversions).
> 
> Once the basic support is in, I was planning on looking at what is needed with
> libquadmath.

Thanks.  Given a large, complicated series of patches like this, it's hard 
to have confidence that the code (both in the back end and in libgcc) is 
working correctly (or that back-end changes don't break it) without 
building a substantial body of __float128 code (such as libquadmath) using 
it.

The libquadmath maintainers had a way of hacking up the glibc libm 
testsuite to use it for testing libquadmath 
<https://gcc.gnu.org/ml/gcc-patches/2012-10/msg02958.html>.  To use that 
you'd need to take a three-year-old version of the glibc libm tests (since 
they've been massively reworked since then, which would require major 
reworking of the hacks), and I suppose compare the results with the 
(not-clean) results for x86_64 reported in that thread, since those hacks 
were never close to having clean test results (whereas the current libm 
testsuite itself does produce clean results for ldbl-128 testing on 
architectures using binary128 long double, given an up-to-date 
libm-test-ulps file).  Enabling the libm testsuite to be used cleanly for 
other types would be several of the maybe 50 or more patches involved in 
getting _Float128 support into glibc (which might have the side-effect of 
facilitating libquadmath updates and testing).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #17
  2015-10-27 19:48     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #17 Michael Meissner
@ 2015-11-04 15:47       ` David Edelsohn
  0 siblings, 0 replies; 78+ messages in thread
From: David Edelsohn @ 2015-11-04 15:47 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches, David Edelsohn

On Tue, Oct 27, 2015 at 12:44 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch adds a test to make sure __float128 and __ibm128 are not allowed to
> be combined in binary operations.  I re-ran the test suite on power8 little
> endian, and this test passed. Once the preceeding 16 patches are applied to the
> tree, is this patch ok to commit into trunk?
>
> 2015-10-27  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * gcc.target/powerpc/float128-mix.c: New test for IEEE 128-bit
>         floating point.

Okay.

Thanks, David

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits, revised)
  2015-11-03 22:53           ` Michael Meissner
@ 2015-11-14  0:02             ` Michael Meissner
  2015-11-16 23:06               ` Joseph Myers
  0 siblings, 1 reply; 78+ messages in thread
From: Michael Meissner @ 2015-11-14  0:02 UTC (permalink / raw)
  To: Michael Meissner, Joseph Myers, gcc-patches, dje.gcc,
	Steve Munroe, Tulio Magno Quites Machado Filho

[-- Attachment #1: Type: text/plain, Size: 2792 bytes --]

This patch should address the following IEEE problems with the libgcc emulator
with exceptions, etc.  Steve is working on patches to libdfp for Decimal
conversions.

When the PowerPC support for __builtin_cpu_is ("...") and
__builtin_cpu_supports ("...") go in, we will add support using IFUNC to
automatically switch between the software emulation functions in this patch,
and functions that use the PowerPC ISA 3.0 instructions.

This passes the bootstrap and regression tests (including the 2 test cases
added as part of IEEE 128-bit patch #9).  Is it ok to check into the trunk?

[gcc]
2015-11-13  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (init_float128_ieee): Only initialize
	cmp_optab, not ucmp_optab.
	(rs6000_generate_compare): Use the standard comparison functions
	(eqkf2, gekf2, lekf2) for normal comparisons.  Call __cmpukf2 for
	IEEE comparisons where NaN is handled specially.

[libgcc]
2015-11-13  Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Steve Munro <sjmunroe@us.ibm.com>
	    Tulio Magno Quites Machado Filho <tulioqm@br.ibm.com>

	<patch ieee #8>
	* Makefile.in (EXTRA_CLEAN): New variable of additional files to
	clean.
	(FLAGS_TO_PASS): Add EXTRA_CLEAN.
	(clean): Delete EXTRA_CLEAN files.

	* configure.ac (powerpc*-*-linux*): If the compiler is capable of
	generating __float128 code, build the __float128 emulation
	libraries.
	* configure: Regenerate.

	* config/rs6000/sfp-exceptions.c: New files for IEEE 128-bit
	floating point support.
	* config/rs6000/floattikf.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/extendkftf2.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/trunctfkf2.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/fixunskfti.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/fixkfti.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/cmpukf2.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/floatuntikf.c: Likewise.
	* config/rs6000/libgcc/config/rs6000/quad-float128.h: Likewise.
	* config/rs6000/libgcc/config/rs6000/t-float128: Likewise.
	* config/rs6000/libgcc/config/rs6000/float128-sed: Likewise.

	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Update
	defintiions to use 64-bit types for 64-bit systems or 32-bit VSX
	systems with IEEE 128-bit floating point support.
	(_FP_W_TYPE): Likewise.
	(_FP_WS_TYPE): Likewise.
	(_FP_I_TYPE): Likewise.
	(TItype): Add defintions for IEEE 128-bit floating point support.
	(UTItype): Likewise.
	(TI_BITS): Likewise.
	(_FP_MUL_MEAT_Q): Use 64-bit types on 64-bit systems and for
	32-bit VSX systems with IEEE 128-bit floating point.
	(_FP_DIV_MEAT_Q): Likewise.
	(_FP_NANFRAC_Q): Likewise.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

[-- Attachment #2: ieee128-patch08e --]
[-- Type: text/plain, Size: 39093 bytes --]

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 230347)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -16560,8 +16560,7 @@ init_float128_ieee (machine_mode mode)
       set_optab_libfunc (lt_optab, mode, "__ltkf2");
       set_optab_libfunc (le_optab, mode, "__lekf2");
       set_optab_libfunc (unord_optab, mode, "__unordkf2");
-      set_optab_libfunc (cmp_optab, mode, "__cmpokf2");		/* fcmpo */
-      set_optab_libfunc (ucmp_optab, mode, "__cmpukf2");	/* fcmpu */
+      set_optab_libfunc (cmp_optab, mode, "__cmpukf2");
 
       set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2");
       set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2");
@@ -20569,12 +20568,11 @@ rs6000_generate_compare (rtx cmp, machin
      instructions.  */
   else if (!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode))
     {
-      rtx and_reg = gen_reg_rtx (SImode);
       rtx dest = gen_reg_rtx (SImode);
-      rtx libfunc = optab_libfunc (ucmp_optab, mode);
+      rtx libfunc = NULL_RTX;
       HOST_WIDE_INT mask_value = 0;
 
-      /* Values that __cmpokf2/__cmpukf2 returns.  */
+      /* Values that __cmpukf2 returns.  */
 #define PPC_CMP_UNORDERED	0x1		/* isnan (a) || isnan (b).  */
 #define PPC_CMP_EQUAL		0x2		/* a == b.  */
 #define PPC_CMP_GREATER_THEN	0x4		/* a > b.  */
@@ -20582,84 +20580,83 @@ rs6000_generate_compare (rtx cmp, machin
 
       switch (code)
 	{
+	/* Normal comparisons use __eqkf2, __gekf2, __lekf2.  */
 	case EQ:
-	  mask_value = PPC_CMP_EQUAL;
-	  code = NE;
-	  break;
-
 	case NE:
-	  mask_value = PPC_CMP_EQUAL;
-	  code = EQ;
+	  libfunc = optab_libfunc (eq_optab, mode);
 	  break;
 
 	case GT:
-	  mask_value = PPC_CMP_GREATER_THEN;
-	  code = NE;
-	  break;
-
 	case GE:
-	  mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
-	  code = NE;
+	  libfunc = optab_libfunc (ge_optab, mode);
 	  break;
 
 	case LT:
-	  mask_value = PPC_CMP_LESS_THEN;
-	  code = NE;
-	  break;
-
 	case LE:
-	  mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
-	  code = NE;
+	  libfunc = optab_libfunc (le_optab, mode);
 	  break;
 
 	case UNLE:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_GREATER_THEN;
 	  code = EQ;
 	  break;
 
+	  /* IEEE comparisons that do not trap on NaN, call __cmpukf2 and
+	     return 4 bits for LT, EQ, GT, and Unordered.  */
 	case UNLT:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
 	  code = EQ;
 	  break;
 
 	case UNGE:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_LESS_THEN;
 	  code = EQ;
 	  break;
 
 	case UNGT:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
 	  code = EQ;
 	  break;
 
 	case UNEQ:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
 	  code = NE;
 
 	case LTGT:
+	  libfunc = optab_libfunc (cmp_optab, mode);
 	  mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED;
 	  code = EQ;
 	  break;
 
 	case UNORDERED:
-	  mask_value = PPC_CMP_UNORDERED;
-	  code = NE;
-	  break;
-
 	case ORDERED:
-	  mask_value = PPC_CMP_UNORDERED;
-	  code = EQ;
+	  libfunc = optab_libfunc (unord_optab, mode);
+	  code = (code == UNORDERED) ? NE : EQ;
 	  break;
 
 	default:
 	  gcc_unreachable ();
 	}
 
-      gcc_assert (mask_value != 0);
-      and_reg = emit_library_call_value (libfunc, and_reg, LCT_CONST, SImode, 2,
-					 op0, mode, op1, mode);
+      gcc_assert (libfunc != NULL_RTX);
+      dest = emit_library_call_value (libfunc, dest, LCT_CONST, SImode, 2,
+				      op0, mode, op1, mode);
+
+      /* If this is an IEEE comparison, see if the particular bits that we are
+	 interested are set.  */
+      if (mask_value != 0)
+	{
+	  rtx dest2 = gen_reg_rtx (SImode);
+
+	  emit_insn (gen_andsi3 (dest2, dest, GEN_INT (mask_value)));
+	  dest = dest2;
+	}
 
-      emit_insn (gen_andsi3 (dest, and_reg, GEN_INT (mask_value)));
       compare_result = gen_reg_rtx (CCmode);
       comp_mode = CCmode;
 
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 230345)
+++ libgcc/config.host	(working copy)
@@ -1059,6 +1059,11 @@ powerpc*-*-linux*)
 		exit 1
 		;;
 	esac
+
+	if test $libgcc_cv_powerpc_float128 = yes; then
+		tmake_file="${tmake_file} rs6000/t-float128"
+	fi
+
 	extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
 	md_unwind_header=rs6000/linux-unwind.h
 	;;
Index: libgcc/Makefile.in
===================================================================
--- libgcc/Makefile.in	(revision 230345)
+++ libgcc/Makefile.in	(working copy)
@@ -70,6 +70,8 @@ INSTALL_DATA = @INSTALL_DATA@
 mkinstalldirs = $(SHELL) $(libgcc_topdir)/mkinstalldirs
 INSTALL_PARTS = $(EXTRA_PARTS)
 
+EXTRA_CLEAN =
+
 objext = .o
 
 AR = @AR@
@@ -90,6 +92,7 @@ FLAGS_TO_PASS = \
 	"CFLAGS=$(CFLAGS)" \
 	"DESTDIR=$(DESTDIR)" \
 	"EXTRA_OFILES=$(EXTRA_OFILES)" \
+	"EXTRA_CLEAN=$(EXTRA_CLEAN)" \
 	"HDEFINES=$(HDEFINES)" \
 	"INSTALL=$(INSTALL)" \
 	"INSTALL_DATA=$(INSTALL_DATA)" \
@@ -128,7 +131,7 @@ installcheck:
 clean:
 	-rm -f libgcc_tm.h libgcc.map
 	-rm -f libgcc_tm.stamp stmp-ldirs
-	-rm -f *$(objext)
+	-rm -f *$(objext) $(EXTRA_CLEAN)
 	-rm -f *.dep
 	-rm -f *.a
 	-rm -f libunwind$(SHLIB_EXT)
Index: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(revision 230345)
+++ libgcc/configure.ac	(working copy)
@@ -373,6 +373,17 @@ esac
 ;;
 esac
 
+case ${host} in
+powerpc*-*-linux*)
+  AC_CACHE_CHECK([whether the PowerPC compiler can do __float128],
+		 [libgcc_cv_powerpc_float128],
+		 [AC_COMPILE_IFELSE(
+    [#pragma GCC target ("vsx,float128")
+     __float128 add (__float128 *a) { return *a + *(a+1); }],
+    [libgcc_cv_powerpc_float128=yes],
+    [libgcc_cv_powerpc_float128=no])])
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 
Index: libgcc/config/rs6000/sfp-exceptions.c
===================================================================
--- libgcc/config/rs6000/sfp-exceptions.c	(revision 0)
+++ libgcc/config/rs6000/sfp-exceptions.c	(revision 0)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 Free Software Foundation, Inc.
+ *
+ * This file 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.
+ *
+ * This file 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.
+ *
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "sfp-machine.h"
+
+void
+__sfp_handle_exceptions (int _fex)
+{
+  const double fp_max = __DBL_MAX__;
+  const double fp_min = __DBL_MIN__;
+  const double fp_zero = (double) 0.0;
+  const double fp_one = 1.0;
+
+  if (_fex & FP_EX_INVALID)
+    {
+      __asm__ __volatile__ ("fdiv %0, %0, %0"
+			    :
+			    : "f" (fp_zero));
+    }
+  if (_fex & FP_EX_DIVZERO)
+    {
+      __asm__ __volatile__ ("fdiv %0, %0, %1"
+			    :
+			    : "f" (fp_one), "f" (fp_zero));
+    }
+  if (_fex & FP_EX_OVERFLOW)
+    {
+      __asm__ __volatile__ ("fadd %0, %0, %0"
+			    :
+			    : "f" (fp_max));
+    }
+  if (_fex & FP_EX_UNDERFLOW)
+    {
+      __asm__ __volatile__ ("fmul %0, %0, %0"
+			    :
+			    : "f" (fp_min));
+    }
+  if (_fex & FP_EX_INEXACT)
+    {
+      __asm__ __volatile__ ("fsub %0, %0, %1"
+			    :
+			    : "f" (fp_max), "f" (fp_one));
+    }
+}
Index: libgcc/config/rs6000/floattikf.c
===================================================================
--- libgcc/config/rs6000/floattikf.c	(revision 0)
+++ libgcc/config/rs6000/floattikf.c	(revision 0)
@@ -0,0 +1,50 @@
+/* Software floating-point emulation.
+   Convert a 128bit signed integer to IEEE quad
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+TFtype
+__floattikf (TItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  TFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_Q (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_Q (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
+#endif
Index: libgcc/config/rs6000/extendkftf2.c
===================================================================
--- libgcc/config/rs6000/extendkftf2.c	(revision 0)
+++ libgcc/config/rs6000/extendkftf2.c	(revision 0)
@@ -0,0 +1,62 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Convert IEEE 128-bit floating point to IBM long double.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+extern __ibm128 __extendkftf2 (__float128);
+
+__ibm128
+__extendkftf2 (__float128 value)
+{
+  double high, low;
+
+  high = (double) value;
+  if (__builtin_isnan (high) || __builtin_isinf (high))
+    low = 0.0;
+
+  else
+    {
+	  double high_temp;
+
+      low = (double) (value - (__float128)high);
+      /* now renormalized the high/low into canonical IBM long double form.  */
+      high_temp = high + low;
+      low = (high - high_temp) + low;
+      high = high_temp;
+    }
+
+  return __builtin_pack_longdouble (high, low);
+}
Index: libgcc/config/rs6000/trunctfkf2.c
===================================================================
--- libgcc/config/rs6000/trunctfkf2.c	(revision 0)
+++ libgcc/config/rs6000/trunctfkf2.c	(revision 0)
@@ -0,0 +1,70 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Convert IBM long double to IEEE 128-bit floating point.  */
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#else
+#if 0
+typedef long double __ibm128;
+typedef long double __float128;
+#endif
+#endif
+
+extern __float128 __trunctfkf2 (__ibm128);
+
+#ifdef __LITTLE_ENDIAN__
+#define HIGH_WORD	1
+#define LOW_WORD	0
+#else
+#define HIGH_WORD	0
+#define LOW_WORD	1
+#endif
+
+__float128
+__trunctfkf2 (__ibm128 value)
+{
+  double high = __builtin_unpack_longdouble (value, HIGH_WORD);
+  double low = __builtin_unpack_longdouble (value, LOW_WORD);
+
+  /* Handle the special cases of NAN and inifinity.  */
+  if (__builtin_isnan (high) || __builtin_isinf (high))
+    return (__float128) high;
+
+  /* If low is 0.0, there no need to do the add.  In addition, avoiding the add
+     produces the correct sign if high is -0.0.  */
+  if (low == 0.0)
+    return (__float128) high;
+
+  return ((__float128)high) + ((__float128)low);
+}
Index: libgcc/config/rs6000/sfp-machine.h
===================================================================
--- libgcc/config/rs6000/sfp-machine.h	(revision 230345)
+++ libgcc/config/rs6000/sfp-machine.h	(working copy)
@@ -1,7 +1,26 @@
+/* Decide whether to use 64 or 32-bit types to do the emulation.  If we are
+   doing IEEE-128 with VSX, use 64-bit emulation even if we are compiling for a
+   32-bit target.  */
+
+#if defined(_ARCH_PPC64) || defined(__VSX__) || defined(__FLOAT128__)
+#define _FP_W_TYPE_SIZE		64
+#define _FP_W_TYPE		unsigned long long
+#define _FP_WS_TYPE		signed long long
+#define _FP_I_TYPE		long long
+
+#ifdef _ARCH_PPC64
+typedef int TItype __attribute__ ((mode (TI)));
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+
+#define TI_BITS (__CHAR_BIT__ * (int)sizeof(TItype))
+#endif
+
+#else	/* 32-bits  */
 #define _FP_W_TYPE_SIZE		32
-#define _FP_W_TYPE		unsigned long
-#define _FP_WS_TYPE		signed long
-#define _FP_I_TYPE		long
+#define _FP_W_TYPE		unsigned int
+#define _FP_WS_TYPE		signed int
+#define _FP_I_TYPE		int
+#endif	/* 32-bits  */
 
 /* The type of the result of a floating point comparison.  This must
    match `__libgcc_cmp_return__' in GCC for the target.  */
@@ -10,18 +29,39 @@ typedef int __gcc_CMPtype __attribute__ 
 
 #define _FP_MUL_MEAT_S(R,X,Y)				\
   _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_MUL_MEAT_D(R,X,Y)				\
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)				\
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+#else
 #define _FP_MUL_MEAT_D(R,X,Y)				\
   _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
 #define _FP_MUL_MEAT_Q(R,X,Y)				\
   _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+#endif
 
 #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_loop(S,R,X,Y)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)   _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+#else
 #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+#endif
 
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
+
+#if (_FP_W_TYPE_SIZE==64)
+#define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+#else
 #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1), -1
 #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#endif
+
 #define _FP_NANSIGN_S		0
 #define _FP_NANSIGN_D		0
 #define _FP_NANSIGN_Q		0
@@ -64,6 +104,46 @@ typedef int __gcc_CMPtype __attribute__ 
 # endif
 #endif
 
+#define ISA_BIT(x) (1 << (63 - x))
+
+/* Use the same bits of the FPSCR.  */
+# define FP_EX_INVALID		ISA_BIT(34)
+# define FP_EX_OVERFLOW		ISA_BIT(35)
+# define FP_EX_UNDERFLOW	ISA_BIT(36)
+# define FP_EX_DIVZERO		ISA_BIT(37)
+# define FP_EX_INEXACT		ISA_BIT(38)
+# define FP_EX_ALL							\
+  (FP_EX_INVALID | FP_EX_OVERFLOW | FP_EX_UNDERFLOW | FP_EX_DIVZERO	\
+   | FP_EX_INEXACT)
+
+void __sfp_handle_exceptions (int);
+
+# define FP_HANDLE_EXCEPTIONS			\
+  do {						\
+    if (__builtin_expect (_fex, 0))		\
+      __sfp_handle_exceptions (_fex);		\
+  } while (0);
+/* A set bit indicates an exception is masked and a clear bit indicates it is
+   trapping.  */
+# define FP_TRAPPING_EXCEPTIONS (~_fpscr & (FP_EX_ALL >> 22))
+
+# define FP_RND_NEAREST	0x0
+# define FP_RND_ZERO	0x1
+# define FP_RND_PINF	0x2
+# define FP_RND_MINF	0x3
+# define FP_RND_MASK	0x3
+
+# define _FP_DECL_EX \
+  unsigned long long _fpscr __attribute__ ((unused)) = FP_RND_NEAREST
+
+#define FP_INIT_ROUNDMODE			\
+  do {						\
+    __asm__ __volatile__ ("mtfsf 255, %0"	\
+			  :			\
+			  : "f" (_fpscr));	\
+  } while (0)
+
+# define FP_ROUNDMODE	(_fpscr & FP_RND_MASK)
 
 /* Define ALIASNAME as a strong alias for NAME.  */
 # define strong_alias(name, aliasname) _strong_alias(name, aliasname)
Index: libgcc/config/rs6000/fixunskfti.c
===================================================================
--- libgcc/config/rs6000/fixunskfti.c	(revision 0)
+++ libgcc/config/rs6000/fixunskfti.c	(revision 0)
@@ -0,0 +1,50 @@
+/* Software floating-point emulation.
+   Convert IEEE quad to 128bit unsigned integer
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+UTItype
+__fixunskfti (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_TO_INT_Q (r, A, TI_BITS, 0);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
+#endif
Index: libgcc/config/rs6000/fixkfti.c
===================================================================
--- libgcc/config/rs6000/fixkfti.c	(revision 0)
+++ libgcc/config/rs6000/fixkfti.c	(revision 0)
@@ -0,0 +1,50 @@
+/* Software floating-point emulation.
+   Convert IEEE quad to 128bit signed integer
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+TItype
+__fixkfti (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_TO_INT_Q (r, A, TI_BITS, 1);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
+#endif
Index: libgcc/config/rs6000/cmpukf2.c
===================================================================
--- libgcc/config/rs6000/cmpukf2.c	(revision 0)
+++ libgcc/config/rs6000/cmpukf2.c	(revision 0)
@@ -0,0 +1,101 @@
+/* Software IEEE 128-bit floating-point emulation for PowerPC.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+	Joseph Myers (joseph@codesourcery.com),
+	Richard Henderson (rth@cygnus.com) and
+	Jakub Jelinek (jj@ultra.linux.cz).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* This function is called for the IEEE comparisons that specifically handle
+   NaNs.  The normal comparisons use eqkf2, gekf2, lekf2, etc.  */
+
+#include "soft-fp.h"
+#include "double.h"
+#include "single.h"
+#include "quad-float128.h"
+
+/* PowerPC condition register bits.  */
+#define PPC_UNORDERED		0x1		/* isnan (a) || isnan (b).  */
+#define PPC_EQUAL		0x2		/* a == b.  */
+#define PPC_GREATER_THEN	0x4		/* a > b.  */
+#define PPC_LESS_THEN		0x8		/* a < b.  */
+
+/* Map FP_CMP_Q output to PowerPC condition register bits.  */
+#define CMP_UNORDERED		(-2)		/* isnan (a) || isnan (b).  */
+#define CMP_LESS_THEN		(-1)		/* a < b.  */
+#define CMP_EQUAL		0		/* a == b.  */
+#define CMP_GREATER_THEN	1		/* a < b.  */
+#define CMP_INVALID		2		/* raise invalid exception.  */
+
+#define CMP_LOW			CMP_UNORDERED	/* comparison low value.  */
+#define CMP_HIGH		CMP_INVALID	/* comparison high value.  */
+
+static const unsigned char ppc_cr_map[] = {
+  PPC_UNORDERED,				/* -2: unordered.  */
+  PPC_LESS_THEN,				/* -1: a < b.  */
+  PPC_EQUAL,					/*  0: a == b.  */
+  PPC_GREATER_THEN,				/*  1: a > b.  */
+  PPC_UNORDERED,				/*  2: invalid.  */
+};
+
+/* Compare two IEEE 128-bit floating point values and return the status.  We
+   return the status as a 4-bit value that uses the same values as the PowerPC
+   condition code register.  */
+
+CMPtype
+__cmpukf2 (TFtype a, TFtype b)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_Q (B);
+  CMPtype r, r2;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_Q (A, a);
+  FP_UNPACK_RAW_Q (B, b);
+
+  /* First do the unordered comparison.  */
+  FP_CMP_UNORD_Q (r, A, B, 1);
+  if (r)
+    r2 = PPC_UNORDERED;
+
+  else
+    {
+      /* If the value is not unordered, do the normal comparison.  */
+      FP_CMP_Q (r, A, B, 2, 2);
+      if (r == CMP_INVALID)
+	FP_SET_EXCEPTION (FP_EX_INVALID);
+
+      r2 = ((r < CMP_LOW || r > CMP_HIGH)
+	    ? PPC_UNORDERED
+	    : ppc_cr_map[r-CMP_LOW]);
+    }
+
+  FP_HANDLE_EXCEPTIONS;
+
+  return r2;
+}
Index: libgcc/config/rs6000/floatuntikf.c
===================================================================
--- libgcc/config/rs6000/floatuntikf.c	(revision 0)
+++ libgcc/config/rs6000/floatuntikf.c	(revision 0)
@@ -0,0 +1,50 @@
+/* Software floating-point emulation.
+   Convert a 128bit unsigned integer to IEEE quad
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com)
+   Code is based on the main soft-fp library written by:
+   	   Uros Bizjak (ubizjak@gmail.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifdef _ARCH_PPC64
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+TFtype
+__floatuntikf (UTItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  TFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_Q (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_Q (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
+#endif
Index: libgcc/config/rs6000/quad-float128.h
===================================================================
--- libgcc/config/rs6000/quad-float128.h	(revision 0)
+++ libgcc/config/rs6000/quad-float128.h	(revision 0)
@@ -0,0 +1,87 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Quad Precision on the PowerPC.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Michael Meissner (meissner@linux.vnet.ibm.com).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* quad.h defines the TFtype type by:
+   typedef float TFtype __attribute__ ((mode (TF)));
+
+   This define forces it to use KFmode (aka, ieee 128-bit floating point).  */
+#define TF KF
+
+/* Force the use of the VSX instruction set.  */
+#if defined(_ARCH_PPC) && (!defined(__VSX__) || !defined(__FLOAT128__))
+#pragma GCC target ("vsx,float128")
+#endif
+
+#include <quad.h>
+
+/* Add prototypes of the library functions created.  In case the appropriate
+   int/long types are not declared in scope by the time quad.h is included,
+   provide our own version.  */
+typedef int	 SItype_ppc  __attribute__ ((__mode__ (__SI__)));
+typedef int	 DItype_ppc  __attribute__ ((__mode__ (__DI__)));
+typedef unsigned USItype_ppc __attribute__ ((__mode__ (__SI__)));
+typedef unsigned UDItype_ppc __attribute__ ((__mode__ (__DI__)));
+
+#ifdef _ARCH_PPC64
+typedef int	 TItype_ppc  __attribute__ ((__mode__ (__TI__)));
+typedef unsigned UTItype_ppc __attribute__ ((__mode__ (__TI__)));
+#endif
+
+extern TFtype __addkf3 (TFtype, TFtype);
+extern TFtype __subkf3 (TFtype, TFtype);
+extern TFtype __mulkf3 (TFtype, TFtype);
+extern TFtype __divkf3 (TFtype, TFtype);
+extern TFtype __negkf2 (TFtype);
+extern CMPtype __eqkf2 (TFtype, TFtype);
+extern CMPtype __nekf2 (TFtype, TFtype);
+extern CMPtype __gekf2 (TFtype, TFtype);
+extern CMPtype __gtkf2 (TFtype, TFtype);
+extern CMPtype __lekf2 (TFtype, TFtype);
+extern CMPtype __ltkf2 (TFtype, TFtype);
+extern CMPtype __unordkf2 (TFtype, TFtype);
+extern CMPtype __cmpukf2 (TFtype, TFtype);
+extern TFtype __extendsfkf2 (float);
+extern TFtype __extenddfkf2 (double);
+extern float __trunckfsf2 (TFtype);
+extern double __trunckfdf2 (TFtype);
+extern SItype_ppc __fixkfsi (TFtype);
+extern DItype_ppc __fixkfdi (TFtype);
+extern USItype_ppc __fixunskfsi (TFtype);
+extern UDItype_ppc __fixunskfdi (TFtype);
+extern TFtype __floatsikf (SItype_ppc);
+extern TFtype __floatdikf (DItype_ppc);
+extern TFtype __floatunsikf (USItype_ppc);
+extern TFtype __floatundikf (UDItype_ppc);
+
+#ifdef _ARCH_PPC64
+extern TItype_ppc __fixkfti (TFtype);
+extern UTItype_ppc __fixunskfti (TFtype);
+extern TFtype __floattikf (TItype_ppc);
+extern TFtype __floatuntikf (UTItype_ppc);
+#endif
Index: libgcc/config/rs6000/t-float128
===================================================================
--- libgcc/config/rs6000/t-float128	(revision 0)
+++ libgcc/config/rs6000/t-float128	(revision 0)
@@ -0,0 +1,80 @@
+# Support for adding __float128 to the powerpc.
+
+# The standard 128-bit floating point support functions are TFmode.  Most
+# PowerPC targets use a long double format that has a pair of doubles to give
+# you more precision, but no extra expoenent range.  This long double format is
+# mostly compatible with the format used by the IBM XL compilers.  Some of the
+# names used by the IBM double-double format use TF in them, so we rename
+# all of the functions provided for the new IEEE 128-bit support.
+#
+# We use the TF functions in soft-fp for 128-bit floating point support, using
+# sed to transform the names in the files from TF names to KF names.
+
+# Emulator functions from the soft-fp directory
+fp128_softfp_funcs	= addkf3 subkf3 mulkf3 divkf3 negkf2 \
+			  unordkf2 eqkf2 gekf2 lekf2 \
+			  extendsfkf2 extenddfkf2 trunckfsf2 trunckfdf2 \
+			  fixkfsi fixkfdi fixunskfsi fixunskfdi \
+			  floatsikf floatdikf floatunsikf floatundikf
+
+fp128_softfp_src	= $(addsuffix .c,$(fp128_softfp_funcs))
+fp128_softfp_static_obj	= $(addsuffix $(objext),$(fp128_softfp_funcs))
+fp128_softfp_shared_obj	= $(addsuffix _s$(objext),$(fp128_softfp_funcs))
+fp128_softfp_obj	= $(fp128_softfp_static_obj) $(fp128_softfp_shared_obj)
+
+# New functions
+fp128_ppc_funcs		= floattikf floatuntikf fixkfti fixunskfti \
+			  extendkftf2 trunctfkf2 sfp-exceptions cmpukf2
+
+fp128_ppc_src		= $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \
+				.c,$(fp128_ppc_funcs)))
+fp128_ppc_static_obj	= $(addsuffix $(objext),$(fp128_ppc_funcs))
+fp128_ppc_shared_obj	= $(addsuffix _s$(objext),$(fp128_ppc_funcs))
+fp128_ppc_obj		= $(fp128_ppc_static_obj) $(fp128_ppc_shared_obj)
+
+# All functions
+fp128_funcs		= $(fp128_softfp_funcs) $(fp128_ppc_funcs)
+fp128_src		= $(fp128_softfp_src) $(fp128_ppc_src)
+fp128_obj		= $(fp128_softfp_obj) $(fp128_ppc_obj)
+fp128_sed		= $(srcdir)/config/rs6000/float128-sed
+fp128_dep		= $(fp128_sed) $(srcdir)/config/rs6000/t-float128
+
+fp128_includes		= $(srcdir)/soft-fp/double.h \
+			  $(srcdir)/soft-fp/op-1.h \
+			  $(srcdir)/soft-fp/op-4.h \
+			  $(srcdir)/soft-fp/op-common.h \
+			  $(srcdir)/soft-fp/single.h \
+			  $(srcdir)/soft-fp/extended.h \
+			  $(srcdir)/soft-fp/op-2.h \
+			  $(srcdir)/soft-fp/op-8.h \
+			  $(srcdir)/soft-fp/quad.h \
+			  $(srcdir)/soft-fp/soft-fp.h
+
+EXTRA_CLEAN		+= $(fp128_softfp_src)
+
+FP128_CFLAGS		 = -Wno-type-limits -mvsx -mfloat128 \
+			   -I$(srcdir)/soft-fp \
+			   -I$(srcdir)/config/rs6000
+
+$(fp128_obj)		 : INTERNAL_CFLAGS += $(FP128_CFLAGS)
+$(fp128_obj)		 : $(fp128_includes)
+$(fp128_obj)		 : $(srcdir)/config/rs6000/quad-float128.h
+
+$(fp128_softfp_src) : $(srcdir)/soft-fp/$(subst kf,tf,$@) $(fp128_dep)
+	@src="$(srcdir)/soft-fp/$(subst kf,tf,$@)"; \
+	echo "Create $@"; \
+	(echo "/* file created from $$src */"; \
+	 echo; \
+	 sed -f $(fp128_sed) < $$src) > $@
+
+test:
+	@echo "fp128_src:"; \
+	for x in $(fp128_src); do echo "    $$x"; done; \
+	echo; \
+	echo "fp128_obj:"; \
+	for x in $(fp128_obj); do echo "    $$x"; done;
+
+# For now, only put it in the static library
+# LIB2ADD += $(fp128_src)
+
+LIB2ADD_ST += $(fp128_src)
Index: libgcc/config/rs6000/float128-sed
===================================================================
--- libgcc/config/rs6000/float128-sed	(revision 0)
+++ libgcc/config/rs6000/float128-sed	(revision 0)
@@ -0,0 +1,25 @@
+s/__addtf3/__addkf3/g
+s/__divtf3/__divkf3/g
+s/__eqtf2/__eqkf2/g
+s/__extenddftf2/__extenddfkf2/g
+s/__extendsftf2/__extendsfkf2/g
+s/__fixtfdi/__fixkfdi/g
+s/__fixtfsi/__fixkfsi/g
+s/__fixunstfdi/__fixunskfdi/g
+s/__fixunstfsi/__fixunskfsi/g
+s/__floatditf/__floatdikf/g
+s/__floatsitf/__floatsikf/g
+s/__floatunditf/__floatundikf/g
+s/__floatunsitf/__floatunsikf/g
+s/__getf2/__gekf2/g
+s/__gttf2/__gtkf2/g
+s/__letf2/__lekf2/g
+s/__lttf2/__ltkf2/g
+s/__multf3/__mulkf3/g
+s/__negtf2/__negkf2/g
+s/__netf2/__nekf2/g
+s/quad[.]h/quad-float128.h/g
+s/__subtf3/__subkf3/g
+s/__trunctfdf2/__trunckfdf2/g
+s/__trunctfsf2/__trunckfsf2/g
+s/__unordtf2/__unordkf2/g
Index: libgcc/configure
===================================================================
--- libgcc/configure	(revision 230345)
+++ libgcc/configure	(working copy)
@@ -4766,6 +4766,29 @@ esac
 ;;
 esac
 
+case ${host} in
+powerpc*-*-linux*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do __float128" >&5
+$as_echo_n "checking whether the PowerPC compiler can do __float128... " >&6; }
+if test "${libgcc_cv_powerpc_float128+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#pragma GCC target ("vsx,float128")
+     __float128 add (__float128 *a) { return *a + *(a+1); }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libgcc_cv_powerpc_float128=yes
+else
+  libgcc_cv_powerpc_float128=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128" >&5
+$as_echo "$libgcc_cv_powerpc_float128" >&6; }
+esac
+
 # Collect host-machine-specific information.
 . ${srcdir}/config.host
 

^ permalink raw reply	[flat|nested] 78+ messages in thread

* Re: [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits, revised)
  2015-11-14  0:02             ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits, revised) Michael Meissner
@ 2015-11-16 23:06               ` Joseph Myers
  0 siblings, 0 replies; 78+ messages in thread
From: Joseph Myers @ 2015-11-16 23:06 UTC (permalink / raw)
  To: Michael Meissner
  Cc: gcc-patches, dje.gcc, Steve Munroe, Tulio Magno Quites Machado Filho

On Fri, 13 Nov 2015, Michael Meissner wrote:

> This patch should address the following IEEE problems with the libgcc emulator
> with exceptions, etc.  Steve is working on patches to libdfp for Decimal
> conversions.

Are the libgcc2.c functions for KFmode and the corresponding complex mode 
KCmode (__divkc3 __mulkc3 __powikf2) also planned for GCC 6?

> 	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Update
> 	defintiions to use 64-bit types for 64-bit systems or 32-bit VSX
> 	systems with IEEE 128-bit floating point support.
> 	(_FP_W_TYPE): Likewise.
> 	(_FP_WS_TYPE): Likewise.
> 	(_FP_I_TYPE): Likewise.
> 	(TItype): Add defintions for IEEE 128-bit floating point support.
> 	(UTItype): Likewise.
> 	(TI_BITS): Likewise.
> 	(_FP_MUL_MEAT_Q): Use 64-bit types on 64-bit systems and for
> 	32-bit VSX systems with IEEE 128-bit floating point.
> 	(_FP_DIV_MEAT_Q): Likewise.
> 	(_FP_NANFRAC_Q): Likewise.

This ChangeLog entry doesn't seem to have been updated for the exceptions 
/ rounding modes support.

> +#define ISA_BIT(x) (1 << (63 - x))

I think all the new sfp-machine.h code for integration with hardware 
exceptions and rounding modes needs to be conditional on hard-float + 
FPRs, so it doesn't affect building for SFmode / DFmode for soft-float / 
e500.

> +  /* First do the unordered comparison.  */
> +  FP_CMP_UNORD_Q (r, A, B, 1);
> +  if (r)
> +    r2 = PPC_UNORDERED;
> +
> +  else
> +    {
> +      /* If the value is not unordered, do the normal comparison.  */
> +      FP_CMP_Q (r, A, B, 2, 2);
> +      if (r == CMP_INVALID)
> +	FP_SET_EXCEPTION (FP_EX_INVALID);
> +
> +      r2 = ((r < CMP_LOW || r > CMP_HIGH)
> +	    ? PPC_UNORDERED
> +	    : ppc_cr_map[r-CMP_LOW]);

This may be correct, but it's overly complicated.  All the handling in the 
"else" case for exceptions / unordered is dead code, since in that case 
you know that the values aren't unordered.  And you can more simply do

  FP_CMP_Q (r, A, B, 2, 1);

at which point "invalid" has been raised if appropriate (for signaling 
NaNs but not for other arguments), and r contains one of the values -1, 0, 
1, 2, which you can map directly to the appropriate return value.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 78+ messages in thread

end of thread, other threads:[~2015-11-16 23:06 UTC | newest]

Thread overview: 78+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-29 20:14 [PATCH], PowerPC IEEE 128-bit patch #4 Michael Meissner
2015-07-29 22:38 ` Segher Boessenkool
2015-07-29 22:48   ` Michael Meissner
2015-07-29 22:56     ` Segher Boessenkool
2015-07-29 23:48       ` Michael Meissner
2015-07-30 19:57 ` [PATCH], PowerPC IEEE 128-bit patch #4c (revised) Michael Meissner
2015-08-01 19:48   ` David Edelsohn
2015-07-31  2:49 ` [PATCH], PowerPC IEEE 128-bit patch #4 Joseph Myers
2015-08-03 19:02   ` Michael Meissner
2015-08-03 21:18     ` Joseph Myers
2015-08-14 15:47 ` [PATCH], PowerPC IEEE 128-bit patch #5 Michael Meissner
2015-08-19 12:47   ` Segher Boessenkool
2015-08-25 23:33     ` Michael Meissner
2015-08-26 13:16       ` David Edelsohn
2015-08-14 15:49 ` [PATCH], PowerPC IEEE 128-bit patch #6 Michael Meissner
2015-08-26 13:57   ` David Edelsohn
2015-08-14 15:56 ` [PATCH], PowerPC IEEE 128-bit patch #7 Michael Meissner
2015-08-14 16:24   ` Michael Meissner
2015-10-23 17:24   ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
2015-10-23 17:30     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #01 Michael Meissner
2015-10-29 14:28       ` David Edelsohn
2015-10-23 17:31     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #02 Michael Meissner
2015-10-29 14:29       ` David Edelsohn
2015-10-23 17:35     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #03 Michael Meissner
2015-10-29 14:29       ` David Edelsohn
2015-10-23 17:38     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #04 Michael Meissner
2015-10-23 20:24       ` Michael Meissner
2015-10-29 14:29       ` David Edelsohn
2015-10-23 17:39     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 Michael Meissner
2015-10-23 18:08       ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 (patch included) Michael Meissner
2015-10-29 14:33       ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #05 David Edelsohn
2015-10-23 17:44     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #06 Michael Meissner
2015-10-29 14:36       ` David Edelsohn
2015-10-29 17:56         ` Michael Meissner
2015-10-23 17:45     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #07 Michael Meissner
2015-10-29 14:36       ` David Edelsohn
2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #09 Michael Meissner
2015-10-23 20:17       ` Joseph Myers
2015-10-23 20:23         ` Michael Meissner
2015-10-29 14:39       ` David Edelsohn
2015-10-23 17:47     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #08 Michael Meissner
2015-10-29 14:38       ` David Edelsohn
2015-10-23 17:52     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #10 Michael Meissner
2015-10-29 14:40       ` David Edelsohn
2015-10-23 17:57     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #11 Michael Meissner
2015-10-29 14:42       ` David Edelsohn
2015-10-23 17:58     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #12 Michael Meissner
2015-10-29 14:44       ` David Edelsohn
2015-10-23 18:00     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #13 Michael Meissner
2015-10-29 14:46       ` David Edelsohn
2015-10-23 18:01     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #14 Michael Meissner
2015-10-29 14:46       ` David Edelsohn
2015-10-23 18:03     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #15 Michael Meissner
2015-10-29 14:50       ` David Edelsohn
2015-10-23 18:04     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #16 Michael Meissner
2015-10-29 15:02       ` David Edelsohn
2015-10-23 20:06     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2) Segher Boessenkool
2015-10-23 20:25       ` Michael Meissner
2015-10-27 19:48     ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised #2), Subpatch #17 Michael Meissner
2015-11-04 15:47       ` David Edelsohn
2015-10-27 22:27     ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Michael Meissner
2015-10-27 23:39       ` Joseph Myers
2015-11-03 22:17         ` Michael Meissner
2015-11-03 22:53           ` Michael Meissner
2015-11-14  0:02             ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits, revised) Michael Meissner
2015-11-16 23:06               ` Joseph Myers
2015-11-03 22:55           ` [PATCH], PowerPC IEEE 128-bit patch #8 (libgcc bits) Mike Stump
2015-11-03 23:41           ` Joseph Myers
2015-10-27 22:35     ` [PATCH], PowerPC IEEE 128-bit patch #9 (enable __float128 by default on VSX systems) Michael Meissner
2015-10-29 14:08       ` Segher Boessenkool
2015-10-29 19:02         ` Joseph Myers
2015-10-29 21:09         ` Michael Meissner
2015-09-16 22:50 ` [PATCH], PowerPC IEEE 128-bit patch #7 (revised) Michael Meissner
2015-09-22  0:19   ` Michael Meissner
2015-10-08 19:04   ` [Patch] PowerPC IEEE 128-bit patch #7 (revised #2) Michael Meissner
2015-10-08 21:30     ` Joseph Myers
2015-10-13 18:11       ` Michael Meissner
2015-10-13 23:44         ` Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).