diff mbox

Patch, Split powerpc -mfloat128 into 2 parts

Message ID 20161004213209.GA537@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Oct. 4, 2016, 9:32 p.m. UTC
In working on the IEEE 128-bit floating point support, I've run into situations
where it would be to have the basic KFmode type available under Linux, but not
allow the __float128 and _Float128 keywords to be used until the library work
is done.  But the library functions might want to use some IEEE 128-bit support
in order to implement the support, but you might need to add -mfloat128 to the
builds.

Originally, I thought no problem, just use a target attribute to enable the
IEEE 128-bit floating point support, but it turns out if the -mfloat128 option
is not set at compilation type, the appropriate types are not created and the
target support won't work to set it later (PR 70589).

Another thing that I've seen occasionally is whether internally __ibm128 is the
same as long double or a sepate type.  Right now, __ibm128 is a separate type.
When we eventually switch to long double being IEEE 128, we might have the same
logical problem with __float128.

This patch attempts to fix both of these problems.  It splits -mfloat128 into
two switches, -mfloat128-type that does all of the underylying type stuff, and
the current -mfloat128 which enables the keywords.  On 64-bit powerpc Linux
systems, the compiler will enable -mfloat128-type by default for VSX targets
(both 32/64-bit on big endian, and 64-bit on little endian).  On other systems
like AIX, it will not enable -mfloat128-type by default.

It also changes __ibm128/__float128, and only registers the keywords if the
long double type is not IBM extended double or IEEE 128-bit floating point
respectively.  If the long double type matches one of those types, instead it
will issue a #define {__ibm128,__float128} long double, and the user will
always pick up the long double type.

I have built these patches on a little endian 64-bit power8 system and a big
endian power7 system that supports both 32-bit/64-bit targets.  Note, due to
bug 77847, I had to build the big endian compiler so that the default code
generation was power5 instead of power7.  There were no regressions, is it ok
to install this pach in the trunk?

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

	* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Split
	-mfloat128 into -mfloat128-type that enables the IEEE 128-bit
	floating point type infrastructre, and -mfloat128 that enables the
	keyword.  Define __FLOAT128__ if -mfloat128, and __FLOAT128_TYPE__
	if -mfloat128-type.  Define __ibm128 or __float128 if that type is
	available, and it matches the long double type.
	* config/rs6000/rs6000.c (rs6000_debug_reg_global): Print whether
	the IEEE 128-bit floating point type infrastructure should
	automatically be enabled.
	(rs6000_init_hard_regno_mode_ok): Switch to use -mfloat128-type
	instead of -mfloat128 to enable KFmode.
	(rs6000_option_override_internal): Split the option -mfloat128
	into -mfloat128-type and -mfloat128.  On Linux PowerPC 64-bit
	systems, automatically set -mfloat128-type, but don't enable it on
	other operating systems.  Move setting the long double size and
	IEEE quad support before the IEEE 128-bit floating point changes.
	(rs6000_init_builtins): Do not create a unique type for __ibm128
	if long double is IBM extended double, instead rely on __ibm128
	being defined as 'long double'.  For IEEE 128-bit floating point,
	if __float128/_Float128 are not enabled, create a unique type for
	IEEE 128-bit floating point.
	(rs6000_init_libfuncs): Use -mfloat128-type instead of
	-mfloat128 for tests about the types, but keep tests for
	-mfloat128 to enable the keyword support.
	(rs6000_complex_function_value): Likewise.
	(rs6000_scalar_mode_supported_p): Likewise.
	(rs6000_floatn_mode): Likewise.
	(rs6000_c_mode_for_suffix): Likewise.
	(rs6000_opt_masks): Add -mfloat128-type.
	* config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add support for
	-mfloat128-type being split from -mfloat128.  Add
	-mfloat128-hardware, which was missing.
	* config/rs6000/rs6000.opt (-mfloat128): Split -mfloat128 into
	-mfloat128 and -mfloat128-type:
	(-mfloat128-type): Likewise.
	* config/rs6000/linux64.h (TARGET_FLOAT128_ENABLE_TYPE): Define so
	that 64-bit Linux systems with enable -mfloat128-type by default
	on VSX systems.
	* config/rs6000/rs6000.h (TARGET_FLOAT128_ENABLE_TYPE): Likewise.
	(FLOAT128_VECTOR_P): Switch IEEE 128-bit floating points to use
	-mfloat128-type instead of -mfloat128.
	(FLOAT128_2REG_P): Likewise.
	(MASK_FLOAT128_TYPE): Likewise.
	(ALTIVEC_ARG_MAX_RETURN): Likewise.
	(RS6000_BTM_FLOAT128): Likewise.
	(TARGET_FLOAT128): Poison old identifiers.
	(OPTION_MASK_FLOAT128): Likewise.
	(MASK_FLOAT128): Likewise.
	* config/rs6000/rs6000.md (FP): Likewise.
	(FLOAT128): Likewise.
	(fix_trunc<mode>di2): Likewise.
	(fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
	(floatdi<mode>2): Likewise.
	(floatuns<SDI:mode><IEEE128:mode>2): Likewise.
	(neg<mode>2, FLOAT128 iterator): Likewise.
	(abs<mode>2, FLOAT128 iterator): Likewise.
	(ieee_128bit_negative_zero): 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.
	(extendiftf2): Likewise.
	(extendifkf2): Likewise.
	(extendtfkf2): Likewise.
	(trunciftf2): Likewise.
	(truncifkf2): Likewise.
	(trunckftf2): Likewise.
	(trunctfif2): Likewise.
	(extendkftf2): Likewise.
	(trunctfkf2): Likewise.

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

	* gcc.target/powerpc/float128-mix.c: Change error message to
	reflect that __ibm128 is now #define'ed to be long double.
	* gcc.target/powerpc/float128-type-1.c: New test to check that
	PowerPC 64-bit Linux enables -mfloat128-type by default.
	* gcc.target/powerpc/float128-type-2.c: Likewise.

Comments

Joseph Myers Oct. 4, 2016, 9:42 p.m. UTC | #1
On Tue, 4 Oct 2016, Michael Meissner wrote:

> It also changes __ibm128/__float128, and only registers the keywords if the
> long double type is not IBM extended double or IEEE 128-bit floating point
> respectively.  If the long double type matches one of those types, instead it
> will issue a #define {__ibm128,__float128} long double, and the user will
> always pick up the long double type.

_Float128, when it exists, is always a distinct type from long double even 
if they are ABI-compatible.  So if they are ABI-compatible, you would have 
__float128 the same as long double but different from _Float128, which 
seems confusing - are you doing it that way because of the lack of 
_Float128 in C++ means a simple define to _Float128 could only be used for 
C?
Michael Meissner Oct. 4, 2016, 9:56 p.m. UTC | #2
On Tue, Oct 04, 2016 at 09:42:21PM +0000, Joseph Myers wrote:
> On Tue, 4 Oct 2016, Michael Meissner wrote:
> 
> > It also changes __ibm128/__float128, and only registers the keywords if the
> > long double type is not IBM extended double or IEEE 128-bit floating point
> > respectively.  If the long double type matches one of those types, instead it
> > will issue a #define {__ibm128,__float128} long double, and the user will
> > always pick up the long double type.
> 
> _Float128, when it exists, is always a distinct type from long double even 
> if they are ABI-compatible.  So if they are ABI-compatible, you would have 
> __float128 the same as long double but different from _Float128, which 
> seems confusing - are you doing it that way because of the lack of 
> _Float128 in C++ means a simple define to _Float128 could only be used for 
> C?

Right now, if -mfloat128 is used, __float128 and _Float128 use the same type.
If -mfloat128 is not used (but -mfloat128-type is), it creates a unique type.
At this point, I was mainly worrying about __ibm128 being the same as long
double.  I am open to suggestions on what __float128 should be somewhere down
the road (gcc 8 or 9 time frame) when the switch becomes an option.
diff mbox

Patch

Index: gcc/config/rs6000/rs6000-c.c
===================================================================
--- gcc/config/rs6000/rs6000-c.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/rs6000-c.c	(.../gcc/config/rs6000)	(working copy)
@@ -425,10 +425,19 @@  rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_KEYWORD)
     builtin_define ("__FLOAT128__");
+  if (TARGET_FLOAT128_TYPE)
+    builtin_define ("__FLOAT128_TYPE__");
   if (TARGET_FLOAT128_HW)
     builtin_define ("__FLOAT128_HARDWARE__");
+  if (TARGET_LONG_DOUBLE_128)
+    {
+      if (FLOAT128_IBM_P (TFmode))
+	builtin_define ("__ibm128=long double");
+      else if (TARGET_FLOAT128_KEYWORD && FLOAT128_IEEE_P (TFmode))
+	builtin_define ("__float128=long double");
+    }
 
   if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM)
     {
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
@@ -2718,6 +2718,9 @@  rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_D, "Number of rs6000 builtins",
 	   (int)RS6000_BUILTIN_COUNT);
 
+  fprintf (stderr, DEBUG_FMT_D, "Enable float128 on VSX",
+	   (int)TARGET_FLOAT128_ENABLE_TYPE);
+
   if (TARGET_VSX)
     fprintf (stderr, DEBUG_FMT_D, "VSX easy 64-bit scalar element",
 	     (int)VECTOR_ELEMENT_SCALAR_64BIT);
@@ -2956,7 +2959,7 @@  rs6000_init_hard_regno_mode_ok (bool glo
 
   /* 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)
+  if (TARGET_FLOAT128_TYPE)
     {
       rs6000_vector_mem[KFmode] = VECTOR_VSX;
       rs6000_vector_align[KFmode] = 128;
@@ -3162,7 +3165,7 @@  rs6000_init_hard_regno_mode_ok (bool glo
   if (TARGET_LFIWZX)
     rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;	/* DImode  */
 
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;	/* KFmode  */
       if (FLOAT128_IEEE_P (TFmode))
@@ -3701,7 +3704,7 @@  rs6000_builtin_mask_calculate (void)
 	  | ((TARGET_DFP)		    ? RS6000_BTM_DFP	   : 0)
 	  | ((TARGET_HARD_FLOAT)	    ? RS6000_BTM_HARD_FLOAT : 0)
 	  | ((TARGET_LONG_DOUBLE_128)	    ? RS6000_BTM_LDBL128   : 0)
-	  | ((TARGET_FLOAT128)		    ? RS6000_BTM_FLOAT128  : 0));
+	  | ((TARGET_FLOAT128_TYPE)	    ? RS6000_BTM_FLOAT128  : 0));
 }
 
 /* Implement TARGET_MD_ASM_ADJUST.  All asm statements are considered
@@ -4405,28 +4408,96 @@  rs6000_option_override_internal (bool gl
 	}
     }
 
-  /* __float128 requires VSX support.  */
-  if (TARGET_FLOAT128 && !TARGET_VSX)
+  /* Set long double size before the IEEE 128-bit tests.  */
+  if (!global_options_set.x_rs6000_long_double_type_size)
+    {
+      if (main_target_opt != NULL
+	  && (main_target_opt->x_rs6000_long_double_type_size
+	      != RS6000_DEFAULT_LONG_DOUBLE_SIZE))
+	error ("target attribute or pragma changes long double size");
+      else
+	rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+    }
+
+  /* Set -mabi=ieeelongdouble on some old targets.  Note, AIX and Darwin
+     explicitly redefine TARGET_IEEEQUAD to 0, so those systems will not
+     pick up this default.  */
+#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
+  if (!global_options_set.x_rs6000_ieeequad)
+    rs6000_ieeequad = 1;
+#endif
+
+  /* Enable the default support for IEEE 128-bit floating point on Linux VSX
+     sytems, but don't enable the __float128 keyword.  */
+  if (TARGET_VSX && TARGET_LONG_DOUBLE_128
+      && (TARGET_FLOAT128_ENABLE_TYPE || TARGET_IEEEQUAD)
+      && ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_TYPE) == 0))
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_TYPE;
+
+  /* IEEE 128-bit floating point requires VSX support.  */
+  if (!TARGET_VSX)
     {
-      if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) != 0)
-	error ("-mfloat128 requires VSX support");
+      if (TARGET_FLOAT128_KEYWORD)
+	{
+	  if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) != 0)
+	    error ("-mfloat128 requires VSX support");
 
-      rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128 | OPTION_MASK_FLOAT128_HW);
+	  rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+				| OPTION_MASK_FLOAT128_KEYWORD
+				| OPTION_MASK_FLOAT128_HW);
+	}
+
+      else if (TARGET_FLOAT128_TYPE)
+	{
+	  if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_TYPE) != 0)
+	    error ("-mfloat128-type requires VSX support");
+
+	  rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+				| OPTION_MASK_FLOAT128_KEYWORD
+				| OPTION_MASK_FLOAT128_HW);
+	}
     }
 
-  /* If we have -mfloat128 and full ISA 3.0 support, enable -mfloat128-hardware
-     by default.  */
-  if (TARGET_FLOAT128 && !TARGET_FLOAT128_HW
-      && (rs6000_isa_flags & ISA_3_0_MASKS_IEEE) == ISA_3_0_MASKS_IEEE
-      && !(rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW))
+  /* -mfloat128 and -mfloat128-hardware internally require the underlying IEEE
+      128-bit floating point support to be enabled.  */
+  if (!TARGET_FLOAT128_TYPE)
     {
-      rs6000_isa_flags |= OPTION_MASK_FLOAT128_HW;
-      if ((rs6000_isa_flags & OPTION_MASK_FLOAT128) != 0)
-	rs6000_isa_flags_explicit |= OPTION_MASK_FLOAT128_HW;
+      if (TARGET_FLOAT128_KEYWORD)
+	{
+	  if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) != 0)
+	    {
+	      error ("-mfloat128 requires -mfloat128-type");
+	      rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+				    | OPTION_MASK_FLOAT128_KEYWORD
+				    | OPTION_MASK_FLOAT128_HW);
+	    }
+	  else
+	    rs6000_isa_flags |= OPTION_MASK_FLOAT128_TYPE;
+	}
+
+      if (TARGET_FLOAT128_HW)
+	{
+	  if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW) != 0)
+	    {
+	      error ("-mfloat128-hardware requires -mfloat128-type");
+	      rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
+	    }
+	  else
+	    rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+				  | OPTION_MASK_FLOAT128_KEYWORD
+				  | OPTION_MASK_FLOAT128_HW);
+	}
     }
 
-  /* IEEE 128-bit floating point hardware instructions imply enabling
-     __float128.  */
+  /* If we have -mfloat128-type and full ISA 3.0 support, enable
+     -mfloat128-hardware by default.  However, don't enable the __float128
+     keyword.  If the user explicitly turned on -mfloat128-hardware, enable the
+     -mfloat128 option as well if it was not already set.  */
+  if (TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW
+      && (rs6000_isa_flags & ISA_3_0_MASKS_IEEE) == ISA_3_0_MASKS_IEEE
+      && !(rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW))
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_HW;
+
   if (TARGET_FLOAT128_HW
       && (rs6000_isa_flags & ISA_3_0_MASKS_IEEE) != ISA_3_0_MASKS_IEEE)
     {
@@ -4436,9 +4507,10 @@  rs6000_option_override_internal (bool gl
       rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
     }
 
-  if (TARGET_FLOAT128_HW
-      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) == 0)
-    rs6000_isa_flags |= OPTION_MASK_FLOAT128;
+  if (TARGET_FLOAT128_HW && !TARGET_FLOAT128_KEYWORD
+      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW) != 0
+      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) == 0)
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_KEYWORD;
 
   /* Print the options after updating the defaults.  */
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
@@ -4501,28 +4573,14 @@  rs6000_option_override_internal (bool gl
 	}
     }
 
-  if (!global_options_set.x_rs6000_long_double_type_size)
-    {
-      if (main_target_opt != NULL
-	  && (main_target_opt->x_rs6000_long_double_type_size
-	      != RS6000_DEFAULT_LONG_DOUBLE_SIZE))
-	error ("target attribute or pragma changes long double size");
-      else
-	rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
-    }
-
-#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
-  if (!global_options_set.x_rs6000_ieeequad)
-    rs6000_ieeequad = 1;
-#endif
-
   /* Disable VSX and Altivec silently if the user switched cpus to power7 in a
      target attribute or pragma which automatically enables both options,
      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
-			   | OPTION_MASK_FLOAT128)
+			   | OPTION_MASK_FLOAT128_TYPE
+			   | OPTION_MASK_FLOAT128_KEYWORD)
 			  & ~rs6000_isa_flags_explicit);
 
   /* Enable Altivec ABI for AIX -maltivec.  */
@@ -16505,29 +16563,53 @@  rs6000_init_builtins (void)
      IFmode is the IBM extended 128-bit format that is a pair of doubles.
      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_FLOAT128)
+     defaults.
+
+     We do not enable the actual __float128 keyword unless the user explicitly
+     asks for it, because the library support is not yet complete.
+
+     If we don't support for either 128-bit IBM double double or IEEE 128-bit
+     floating point, we need make sure the type is non-zero or else self-test
+     fails during bootstrap.
+
+     We don't register a built-in type for __ibm128 or __float128 if the type
+     is the same as long double.  Instead we add a #define for __ibm128 or
+     __float128 in rs6000_cpu_cpp_builtins to long double.  */
+  if (TARGET_IEEEQUAD || !TARGET_LONG_DOUBLE_128)
     {
       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 = float128_type_node;
-
-      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
-					      "__float128");
-
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
 					      "__ibm128");
     }
   else
+    ibm128_float_type_node = long_double_type_node;
+
+  if (TARGET_FLOAT128_KEYWORD)
     {
-      /* All types must be nonzero, or self-test barfs during bootstrap.  */
-      ieee128_float_type_node = long_double_type_node;
-      ibm128_float_type_node = long_double_type_node;
+      ieee128_float_type_node = float128_type_node;
+      if (!FLOAT128_IEEE_P (TFmode))
+	lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+						"__float128");
     }
 
+  else if (TARGET_FLOAT128_TYPE)
+    {
+      ieee128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ibm128_float_type_node) = 128;
+      layout_type (ieee128_float_type_node);
+      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
+
+      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+					      "__ieee128");
+    }
+
+  else
+    ieee128_float_type_node = long_double_type_node;
+
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
   builtin_mode_to_type[QImode][0] = integer_type_node;
@@ -18316,7 +18398,7 @@  static void
 rs6000_init_libfuncs (void)
 {
   /* __float128 support.  */
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       init_float128_ibm (IFmode);
       init_float128_ieee (KFmode);
@@ -33425,7 +33507,7 @@  rs6000_mangle_type (const_tree type)
   /* 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 (TARGET_FLOAT128_TYPE)
     {
       if (type == ieee128_float_type_node)
 	return "U10__float128";
@@ -36397,7 +36479,7 @@  rs6000_complex_function_value (machine_m
   machine_mode inner = GET_MODE_INNER (mode);
   unsigned int inner_bytes = GET_MODE_UNIT_SIZE (mode);
 
-  if (TARGET_FLOAT128
+  if (TARGET_FLOAT128_TYPE
       && (mode == KCmode
 	  || (mode == TCmode && TARGET_IEEEQUAD)))
     regno = ALTIVEC_ARG_RETURN;
@@ -36804,7 +36886,7 @@  rs6000_scalar_mode_supported_p (machine_
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
-  else if (TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+  else if (TARGET_FLOAT128_TYPE && (mode == KFmode || mode == IFmode))
     return true;
   else
     return default_scalar_mode_supported_p (mode);
@@ -36843,7 +36925,7 @@  rs6000_floatn_mode (int n, bool extended
 	  return DFmode;
 
 	case 64:
-	  if (TARGET_FLOAT128)
+	  if (TARGET_FLOAT128_KEYWORD)
 	    return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
 	  else
 	    return VOIDmode;
@@ -36867,7 +36949,7 @@  rs6000_floatn_mode (int n, bool extended
 	  return DFmode;
 
 	case 128:
-	  if (TARGET_FLOAT128)
+	  if (TARGET_FLOAT128_KEYWORD)
 	    return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
 	  else
 	    return VOIDmode;
@@ -36883,7 +36965,7 @@  rs6000_floatn_mode (int n, bool extended
 static machine_mode
 rs6000_c_mode_for_suffix (char suffix)
 {
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       if (suffix == 'q' || suffix == 'Q')
 	return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
@@ -36984,7 +37066,8 @@  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, false },
+  { "float128",			OPTION_MASK_FLOAT128_KEYWORD,	false, false },
+  { "float128-type",		OPTION_MASK_FLOAT128_TYPE,	false, false },
   { "float128-hardware",	OPTION_MASK_FLOAT128_HW,	false, false },
   { "fprnd",			OPTION_MASK_FPRND,		false, true  },
   { "hard-dfp",			OPTION_MASK_DFP,		false, true  },
Index: gcc/config/rs6000/rs6000-cpus.def
===================================================================
--- gcc/config/rs6000/rs6000-cpus.def	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/rs6000-cpus.def	(.../gcc/config/rs6000)	(working copy)
@@ -103,7 +103,9 @@ 
 				 | OPTION_MASK_DIRECT_MOVE		\
 				 | OPTION_MASK_DLMZB			\
 				 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX	\
-				 | OPTION_MASK_FLOAT128			\
+				 | OPTION_MASK_FLOAT128_HW		\
+				 | OPTION_MASK_FLOAT128_KEYWORD		\
+				 | OPTION_MASK_FLOAT128_TYPE		\
 				 | OPTION_MASK_FPRND			\
 				 | OPTION_MASK_HTM			\
 				 | OPTION_MASK_ISEL			\
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/rs6000.opt	(.../gcc/config/rs6000)	(working copy)
@@ -645,8 +645,16 @@  mmodulo
 Target Undocumented Report Mask(MODULO) Var(rs6000_isa_flags)
 Generate the integer modulo instructions.
 
+; We want to enable the internal support for the IEEE 128-bit floating point
+; type without necessarily enabling the __float128 keyword.  This is to allow
+; Boost and other libraries that know about __float128 to work until the
+; official library support is finished.
+mfloat128-type
+Target Undocumented Mask(FLOAT128_TYPE) Var(rs6000_isa_flags)
+Allow the IEEE 128-bit types without requiring the __float128 keyword.
+
 mfloat128
-Target Report Mask(FLOAT128) Var(rs6000_isa_flags)
+Target Report Mask(FLOAT128_KEYWORD) Var(rs6000_isa_flags)
 Enable IEEE 128-bit floating point via the __float128 keyword.
 
 mfloat128-hardware
Index: gcc/config/rs6000/linux64.h
===================================================================
--- gcc/config/rs6000/linux64.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/linux64.h	(.../gcc/config/rs6000)	(working copy)
@@ -634,3 +634,9 @@  extern int dot_symbols;
   || (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 19)
 #define RS6000_GLIBC_ATOMIC_FENV 1
 #endif
+
+/* The IEEE 128-bit emulator is only built on Linux systems.  Flag that we
+   should enable the type handling for KFmode on VSX systems even if we are not
+   enabling the __float128 keyword.  */
+#undef	TARGET_FLOAT128_ENABLE_TYPE
+#define TARGET_FLOAT128_ENABLE_TYPE 1
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/rs6000.h	(.../gcc/config/rs6000)	(working copy)
@@ -363,6 +363,10 @@  extern const char *host_detect_local_cpu
 #define SET_TARGET_LINK_STACK(X) do { } while (0)
 #endif
 
+#ifndef TARGET_FLOAT128_ENABLE_TYPE
+#define TARGET_FLOAT128_ENABLE_TYPE 0
+#endif
+
 /* Return 1 for a symbol ref for a thread-local storage symbol.  */
 #define RS6000_SYMBOL_REF_TLS_P(RTX) \
   (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
@@ -449,12 +453,12 @@  extern const char *host_detect_local_cpu
 
 /* Helper macros to say whether a 128-bit floating point type can go in a
    single vector register, or whether it needs paired scalar values.  */
-#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE))
+#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (MODE))
 
 #define FLOAT128_2REG_P(MODE)						\
   (FLOAT128_IBM_P (MODE)						\
    || ((MODE) == TDmode)						\
-   || (!TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE)))
+   || (!TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (MODE)))
 
 /* Return true for floating point that does not use a vector register.  */
 #define SCALAR_FLOAT_MODE_NOT_VECTOR_P(MODE)				\
@@ -637,7 +641,7 @@  extern int rs6000_vector_align[];
 #define MASK_DIRECT_MOVE		OPTION_MASK_DIRECT_MOVE
 #define MASK_DLMZB			OPTION_MASK_DLMZB
 #define MASK_EABI			OPTION_MASK_EABI
-#define MASK_FLOAT128			OPTION_MASK_FLOAT128
+#define MASK_FLOAT128_TYPE		OPTION_MASK_FLOAT128_TYPE
 #define MASK_FPRND			OPTION_MASK_FPRND
 #define MASK_P8_FUSION			OPTION_MASK_P8_FUSION
 #define MASK_HARD_FLOAT			OPTION_MASK_HARD_FLOAT
@@ -1821,7 +1825,7 @@  extern enum reg_class rs6000_constraints
 			   : (FP_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
 #define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2		\
 				? (ALTIVEC_ARG_RETURN			\
-				   + (TARGET_FLOAT128 ? 1 : 0))		\
+				   + (TARGET_FLOAT128_TYPE ? 1 : 0))	\
 			        : (ALTIVEC_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
 
 /* Flags for the call/call_value rtl operations set up by function_arg */
@@ -2728,7 +2732,7 @@  extern int frame_pointer_needed;
 #define RS6000_BTM_HARD_FLOAT	MASK_SOFT_FLOAT	/* Hardware floating point.  */
 #define RS6000_BTM_LDBL128	MASK_MULTIPLE	/* 128-bit long double.  */
 #define RS6000_BTM_64BIT	MASK_64BIT	/* 64-bit addressing.  */
-#define RS6000_BTM_FLOAT128	MASK_FLOAT128	/* IEEE 128-bit float.  */
+#define RS6000_BTM_FLOAT128	MASK_FLOAT128_TYPE /* IEEE 128-bit float.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
@@ -2914,3 +2918,7 @@  extern GTY(()) tree rs6000_builtin_types
 extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
 
 #define TARGET_SUPPORTS_WIDE_INT 1
+
+#if (GCC_VERSION >= 3000)
+#pragma GCC poison TARGET_FLOAT128 OPTION_MASK_FLOAT128 MASK_FLOAT128
+#endif
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 240680)
+++ gcc/config/rs6000/rs6000.md	(.../gcc/config/rs6000)	(working copy)
@@ -376,8 +376,8 @@  (define_mode_iterator FP [
   (TF "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
-  (IF "TARGET_FLOAT128")
-  (KF "TARGET_FLOAT128")
+  (IF "TARGET_LONG_DOUBLE_128")
+  (KF "TARGET_FLOAT128_TYPE")
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
@@ -506,8 +506,8 @@  (define_mode_iterator IEEE128 [(KF "FLOA
 			       (TF "FLOAT128_IEEE_P (TFmode)")])
 
 ; Iterator for 128-bit floating point
-(define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128")
-				(IF "TARGET_FLOAT128")
+(define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128_TYPE")
+				(IF "TARGET_FLOAT128_TYPE")
 				(TF "TARGET_LONG_DOUBLE_128")])
 
 ; Iterator for signbit on 64-bit machines with direct move
@@ -7298,7 +7298,7 @@  (define_insn_and_split "*fix_trunc<mode>
 (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"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7307,7 +7307,7 @@  (define_expand "fix_trunc<mode>di2"
 (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"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
@@ -7316,7 +7316,7 @@  (define_expand "fixuns_trunc<IEEE128:mod
 (define_expand "floatdi<mode>2"
   [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
 	(float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7325,7 +7325,7 @@  (define_expand "floatdi<mode>2"
 (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"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
@@ -7351,7 +7351,7 @@  (define_expand "neg<mode>2"
 	  else
 	    gcc_unreachable ();
 	}
-      else if (TARGET_FLOAT128)
+      else if (TARGET_FLOAT128_TYPE)
 	{
 	  if (<MODE>mode == TFmode)
 	    emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
@@ -7411,7 +7411,7 @@  (define_expand "abs<mode>2"
 	    FAIL;
 	  DONE;
 	}
-      else if (TARGET_FLOAT128)
+      else if (TARGET_FLOAT128_TYPE)
 	{
 	  if (<MODE>mode == TFmode)
 	    emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
@@ -7471,7 +7471,7 @@  (define_expand "abs<mode>2_internal"
 
 (define_expand "ieee_128bit_negative_zero"
   [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rtvec v = rtvec_alloc (16);
   int i, high;
@@ -7498,7 +7498,7 @@  (define_insn_and_split "ieee_128bit_vsx_
   [(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 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
@@ -7518,7 +7518,7 @@  (define_insn "*ieee_128bit_vsx_neg<mode>
   [(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 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "xxlxor %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
@@ -7527,7 +7527,7 @@  (define_insn_and_split "ieee_128bit_vsx_
   [(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 && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
@@ -7547,7 +7547,7 @@  (define_insn "*ieee_128bit_vsx_abs<mode>
   [(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 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "xxlandc %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
@@ -7558,7 +7558,8 @@  (define_insn_and_split "*ieee_128bit_vsx
 	 (abs:IEEE128
 	  (match_operand:IEEE128 1 "register_operand" "wa"))))
    (clobber (match_scratch:V16QI 2 "=v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW
+   && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
@@ -7580,7 +7581,7 @@  (define_insn "*ieee_128bit_vsx_nabs<mode
 	 (abs:IEEE128
 	  (match_operand:IEEE128 1 "register_operand" "wa"))))
    (use (match_operand:V16QI 2 "register_operand" "v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "xxlor %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
@@ -7590,7 +7591,7 @@  (define_insn "*ieee_128bit_vsx_nabs<mode
 (define_expand "extendiftf2"
   [(set (match_operand:TF 0 "gpc_reg_operand" "")
 	(float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7599,7 +7600,7 @@  (define_expand "extendiftf2"
 (define_expand "extendifkf2"
   [(set (match_operand:KF 0 "gpc_reg_operand" "")
 	(float_extend:KF (match_operand:IF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7608,7 +7609,7 @@  (define_expand "extendifkf2"
 (define_expand "extendtfkf2"
   [(set (match_operand:KF 0 "gpc_reg_operand" "")
 	(float_extend:KF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7617,7 +7618,7 @@  (define_expand "extendtfkf2"
 (define_expand "trunciftf2"
   [(set (match_operand:IF 0 "gpc_reg_operand" "")
 	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7626,7 +7627,7 @@  (define_expand "trunciftf2"
 (define_expand "truncifkf2"
   [(set (match_operand:IF 0 "gpc_reg_operand" "")
 	(float_truncate:IF (match_operand:KF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7635,7 +7636,7 @@  (define_expand "truncifkf2"
 (define_expand "trunckftf2"
   [(set (match_operand:TF 0 "gpc_reg_operand" "")
 	(float_truncate:TF (match_operand:KF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -7644,7 +7645,7 @@  (define_expand "trunckftf2"
 (define_expand "trunctfif2"
   [(set (match_operand:IF 0 "gpc_reg_operand" "")
 	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
@@ -13724,7 +13725,7 @@  (define_insn "extend<SFDF:mode><IEEE128:
 (define_insn_and_split "extendkftf2"
   [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa")
 	(float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))]
-  "TARGET_FLOAT128 && TARGET_IEEEQUAD"
+  "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
   "@
    #
    xxlor %x0,%x1,%x1"
@@ -13740,7 +13741,7 @@  (define_insn_and_split "extendkftf2"
 (define_insn_and_split "trunctfkf2"
   [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa")
 	(float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))]
-  "TARGET_FLOAT128 && TARGET_IEEEQUAD"
+  "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
   "@
    #
    xxlor %x0,%x1,%x1"
Index: gcc/testsuite/gcc.target/powerpc/float128-mix.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-mix.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 240680)
+++ gcc/testsuite/gcc.target/powerpc/float128-mix.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -4,13 +4,13 @@ 
 /* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
 
 
-/* Test to make sure that __float128 and __ibm128 cannot be combined together.  */
-__float128 add (__float128 a, __ibm128 b)
+/* Test to make sure that __float128 and long double cannot be combined together.  */
+__float128 add (__float128 a, long double b)
 {
-  return a+b;	/* { dg-error "__float128 and __ibm128 cannot be used in the same expression" "" } */
+  return a+b;	/* { dg-error "__float128 and long double cannot be used in the same expression" "" } */
 }
 
-__ibm128 sub (__ibm128 a, __float128 b)
+__ibm128 sub (long double a, __float128 b)
 {
-  return a-b;	/* { dg-error "__float128 and __ibm128 cannot be used in the same expression" "" } */
+  return a-b;	/* { dg-error "__float128 and long double cannot be used in the same expression" "" } */
 }
Index: gcc/testsuite/gcc.target/powerpc/float128-type-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-type-1.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-type-1.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 240728)
@@ -0,0 +1,24 @@ 
+/* { dg-do compile { target { powerpc64*-*-linux* && lp64 } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2" } */
+
+/* -mfloat128-type is enabled by default on VSX Linux 64-bit systems.  */
+
+typedef double          __attribute__((__mode__(__KF__))) f128_t;
+typedef _Complex double __attribute__((__mode__(__KC__))) f128c_t;
+
+f128_t
+add_scalar (f128_t a, f128_t b)
+{
+  return a+b;
+}
+
+
+f128c_t
+add_complex (f128c_t a, f128c_t b)
+{
+  return a+b;
+}
+
+/* { dg-final { scan-assembler "bl __addkf3" } } */
Index: gcc/testsuite/gcc.target/powerpc/float128-type-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-type-2.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-type-2.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 240728)
@@ -0,0 +1,26 @@ 
+/* { dg-do compile { target { powerpc64-*-linux* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+/* -mfloat128-type is enabled by default on VSX Linux 64-bit systems.  */
+/* Note, do not use effective target powerpc_float128_hw_ok, as that
+   will pass -mfloat128.  */
+
+typedef double          __attribute__((__mode__(__KF__))) f128_t;
+typedef _Complex double __attribute__((__mode__(__KC__))) f128c_t;
+
+f128_t
+add_scalar (f128_t a, f128_t b)
+{
+  return a+b;
+}
+
+
+f128c_t
+add_complex (f128c_t a, f128c_t b)
+{
+  return a+b;
+}
+
+/* { dg-final { scan-assembler "xsaddqp" } } */