diff mbox

, Enable -mfloat128 by default on PowerPC VSX systems

Message ID 20170816225950.GA2292@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Aug. 16, 2017, 10:59 p.m. UTC
This patch enables -mfloat128 to be the default on PowerPC Linux VSX systems.

This patch depends on the libquadmatch/81848 patch being approved and
installed:
https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00977.html

In this patch, I removed the old undocumented -mfloat128-type switch, and made
the default to be on for PowerPC Linux systems.  The default is off for other
systems (such as AIX) because they don't build the float128 emulation routines
in libgcc.

This patch also supersedes the patch for target/70589 that was previously
submitted.  It includes the changes for that bug to enable/disable -mfloat128
via target pragmas/attributes with the exception that the option
-mfloat128-type is now deleted:
https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00894.html

I fixed up all of the float128 tests to remove the explict -mfloat128 option
and add -mno-float128 as needed.

I've checked this on a big endian power7 system (both 32-bit and 64-bit) and a
little endian power8 system.  It bootstrapped fine and had no regressions in
the test suite.  I also built the latest boost library and got the same results
for the pre -mfloat128 compiler and the compiler with -mfloat128 as the
default, and there were no changes.  I also built and ran spec 2006 FP tests
with the two compilers, and there no changes in runtime of the tests.

Can I check this into the trunk once the patch for 81848 has been applied?

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

	PR target/81872
	* config/rs6000/rs6000-cpus.def (OTHER_VSX_VECTOR_MASKS): Delete
	OPTION_MASK_FLOAT128_TYPE.
	(POWERPC_MASKS): Likewise.
	* config/rs6000/rs6000.opt (TARGET_FLOAT128_ENABLE_TYPE): Make
	this a variable instead of a target switch.
	(-mfloat128-type): Delete switch.
	* config/rs6000/rs6000.c (rs6000_option_override_internal): Set
	-mfloat128 by default on Linux VSX systems.  Remove support for
	an explicit -mfloat128-type option.  Rework how
	-mfloat128-hardware is set on ISA 3.0 systems.  Even if
	-mno-float128 is used, enable the IEEE 128-bit type support
	internally.
	(rs6000_opt_masks): Delete -mfloat128-type.
	* config/rs6000/rs6000.h (MASK_FLOAT128_TYPE): Delete.
	(MASK_FLOAT128_KEYWORD): Define.
	(RS6000_BTM_FLOAT128): Use the mask for -mfloat128 instead of
	-mfloat128-type to signal we should build the IEEE 128-bit
	built-in functions.  The function rs6000_builtin_mask_calculate in
	rs6000.c still uses TARGET_FLOAT128_ENABLE_TYPE to determine
	whether to enable the built-in functions or not.
	* doc/invoke.texi (RS/6000 and PowerPC Options): Update -mfloat128
	and -mfloat128-hardware documentation.

	PR target/70589
	* config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Make the
	real keyword for IEEE 128-bit be __ieee128 for VSX runs, and define
	__float128 to be __ieee128 if -mfloat128 is used or a float128
	target attribute/pragma is used.  Enable _Float128 all of the
	time.
	(rs6000_cpu_cpp_builtins): Likewise.
	* config/rs6000/rs6000.c (rs6000_init_builtins): Likewise.
	(rs6000_floatn_mode): Likewise.
	(rs6000_opt_masks): Likewise.

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

	PR target/81872
	* gcc.target/powerpc/float128-1.c: Change float128 tests to assume
	-mfloat128 is on by default.  Explicitly use -mno-float128 to test
	when the __float128 keyword should not be available.  Use -mvsx,
	-mpower8-vector, or -mpower9-vector instead of -mcpu=power7/8/9 in
	many cases.
	* gcc.target/powerpc/float128-2.c: Likewise.
	* gcc.target/powerpc/float128-cmp.c: Likewise.
	* gcc.target/powerpc/float128-complex-1.c: Likewise.
	* gcc.target/powerpc/float128-complex-2.c: Likewise.
	* gcc.target/powerpc/float128-hw.c: Likewise.
	* gcc.target/powerpc/float128-mix.c: Likewise.
	* gcc.target/powerpc/float128-type-1.c: Likewise.
	* gcc.target/powerpc/float128-type-2.c: Likewise.

	PR target/70589
	* gcc.target/powerpc/float128-3.c: New test.
	* gcc.target/powerpc/float128-4.c: Likewise.
	* gcc.target/powerpc/float128-5.c: Likewise.

Comments

Segher Boessenkool Aug. 18, 2017, 8:57 p.m. UTC | #1
On Wed, Aug 16, 2017 at 06:59:50PM -0400, Michael Meissner wrote:
> This patch enables -mfloat128 to be the default on PowerPC Linux VSX systems.
> 
> This patch depends on the libquadmatch/81848 patch being approved and
> installed:
> https://gcc.gnu.org/ml/gcc-patches/2017-08/msg00977.html

That patch is still waiting, but I'll review this one already.

> I've checked this on a big endian power7 system (both 32-bit and 64-bit) and a
> little endian power8 system.

It may be good to test it on a system without VSX as well, if you can?

> +The default for @option{-mfloat128} is enabled on PowerPC Linux
> +systems using the VSX instruction set, and disabled on other systems.
> +
> +The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7},
> +@option{-mcpu=power8}) must be enabled to use the IEEE 128-bit
> +floating point support.  The IEEE 128-bit floating point support only
> +works on PowerPC Linux systems.

Maybe swap these two?  More logical that way I think.

> +The default for @option{-mfloat128-hardware} is enabled on PowerPC
> +Linux systems using the ISA 3.0 instruction set, and disabled on other
> +systems.

You cannot enable it without ISA 3.0, it looks like it does not say that?


The patch looks fine (maybe improve the doc a bit), it's approved for
trunk.  Thanks!


Segher
Michael Meissner Sept. 6, 2017, 5:48 a.m. UTC | #2
Here is a respin of the patch to enable -mfloat128 on PowerPC Linux systems now
that the libquadmath patch has been applied.  I rebased the patches against the
top of the trunk on Tuesday (subversion id 251609).

I tweaked the documentation a bit based on your comments.

I built the patch on the following systems.  There are no regressions, and the
tests float128-type-{1,2}.c now pass (previously they had regressed due to
other float128 changes).

    *	Power7, bootstrap, big endian, --with-cpu=power7
    *	Power7, bootstrap, big endian, --with-cpu=power5
    *	Power8, bootstrap, little endian, --with-cpu=power8
    *	Power9 prototype bootstrap, little endian, --with-cpu=power9

Can I check these patches into the trunk?

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

	* config/rs6000/rs6000-cpus.def (OTHER_VSX_VECTOR_MASKS): Delete
	OPTION_MASK_FLOAT128_KEYWORD.
	(POWERPC_MASKS): Likewise.
	* config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Delete
	support for the -mfloat128-type option, and make -mfloat128
	default on PowerPC Linux systems.  Define or undefine
	__FLOAT128__ and  __FLOAT128_HARDWARE__ for the current options.
	Define __float128 to be __ieee128 if IEEE 128-bit support is
	enabled, or undefine it.
	(rs6000_cpu_cpp_builtins): Delete defining __FLOAT128__ here.
	Delete defining __FLOAT128_TYPE__.
	* config/rs6000/rs6000.opt (x_TARGET_FLOAT128_TYPE): Delete the
	-mfloat128-type option and make -mfloat128 default on PowerPC
	Linux systems.
	(TARGET_FLOAT128_TYPE): Likewise.
	(-mfloat128-type): Likewise.
	* config/rs6000/rs6000.c (rs6000_option_override_internal):
	Delete the -mfloat128-type option and make -mfloat128 default on
	PowerPC Linux systems.  Always use __ieee128 to be the keyword for
	the IEEE 128-bit type, and map __float128 to __ieee128 if IEEE
	128-bit floating point is enabled.  Change tests from using
	-mfloat128-type to -mfloat128.
	(rs6000_mangle_type): Use the correct mangling for the __float128
	type even if normal long double is restricted to 64-bits.
	(floatn_mode): Enable the _Float128 type by default on VSX Linux
	systems.
	* config/rs6000/rs6000.h (MASK_FLOAT128_TYPE): Delete.
	(MASK_FLOAT128_KEYWORD): Define new shortcut macro.
	(RS6000BTM_FLOAT128): Define in terms of -mfloat128, not
	-mfloat128-type.
	* doc/invoke.texi (RS/6000 and PowerPC Options): Update
	documentation for -mfloat128.

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

	* gcc.target/powerpc/float128-1.c: Update options to know that
	-mfloat128 is now on by default on PowerPC VSX systems.  Remove
	-static-libgcc option which is no longer needed.  Use -mvsx or
	-mpower9-vector to enable VSX or hardware IEEE support, rather
	than specifying a particular CPU.
	* gcc.target/powerpc/float128-2.c: Likewise.
	* gcc.target/powerpc/float128-cmp.c: Likewise.
	* gcc.target/powerpc/float128-complex-1.c: Likewise.
	* gcc.target/powerpc/float128-complex-2.c: Likewise.
	* gcc.target/powerpc/float128-hw.c: Likewise.
	* gcc.target/powerpc/float128-mix.c: Likewise.
	* gcc.target/powerpc/float128-type-1.c: Likewise.
	* gcc.target/powerpc/float128-type-2.c: Likewise.
	* gcc.target/powerpc/float128-3.c: New test.
	* gcc.target/powerpc/float128-4.c: Likewise.
	* gcc.target/powerpc/float128-5.c: Likewise.
Segher Boessenkool Sept. 6, 2017, 4:59 p.m. UTC | #3
On Wed, Sep 06, 2017 at 01:48:38AM -0400, Michael Meissner wrote:
> Here is a respin of the patch to enable -mfloat128 on PowerPC Linux systems now
> that the libquadmath patch has been applied.  I rebased the patches against the
> top of the trunk on Tuesday (subversion id 251609).
> 
> I tweaked the documentation a bit based on your comments.
> 
> I built the patch on the following systems.  There are no regressions, and the
> tests float128-type-{1,2}.c now pass (previously they had regressed due to
> other float128 changes).
> 
>     *	Power7, bootstrap, big endian, --with-cpu=power7
>     *	Power7, bootstrap, big endian, --with-cpu=power5
>     *	Power8, bootstrap, little endian, --with-cpu=power8
>     *	Power9 prototype bootstrap, little endian, --with-cpu=power9
> 
> Can I check these patches into the trunk?

It looks fine, please commit.  Thanks!


Segher
diff mbox

Patch

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 251056)
+++ gcc/config/rs6000/rs6000-cpus.def	(.../gcc/config/rs6000)	(working copy)
@@ -92,7 +92,6 @@ 
 #define OTHER_VSX_VECTOR_MASKS	(OTHER_P8_VECTOR_MASKS			\
 				 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX	\
 				 | OPTION_MASK_FLOAT128_KEYWORD		\
-				 | OPTION_MASK_FLOAT128_TYPE		\
 				 | OPTION_MASK_P8_VECTOR		\
 				 | OPTION_MASK_VSX_TIMODE)
 
@@ -119,7 +118,6 @@ 
 				 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX	\
 				 | 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 251056)
+++ gcc/config/rs6000/rs6000.opt	(.../gcc/config/rs6000)	(working copy)
@@ -100,6 +100,14 @@  HOST_WIDE_INT rs6000_builtin_mask
 TargetVariable
 unsigned int rs6000_debug
 
+;; Whether to enable the -mfloat128 stuff without necessarily enabling the
+;; __float128 keyword.
+TargetSave
+unsigned char x_TARGET_FLOAT128_TYPE
+
+Variable
+unsigned char TARGET_FLOAT128_TYPE
+
 ;; This option existed in the past, but now is always on.
 mpowerpc
 Target RejectNegative Undocumented Ignore
@@ -590,14 +598,6 @@  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_KEYWORD) Var(rs6000_isa_flags)
 Enable IEEE 128-bit floating point via the __float128 keyword.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 251056)
+++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
@@ -4611,72 +4611,42 @@  rs6000_option_override_internal (bool gl
 #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;
+     sytems.  In GCC 7, we would enable the the IEEE 128-bit floating point
+     infrastructure (-mfloat128-type) but not enable the actual __float128 type
+     unless the user used the explicit -mfloat128.  In GCC 8, we enable both
+     the keyword as well as the type.  */
+  TARGET_FLOAT128_TYPE = TARGET_FLOAT128_ENABLE_TYPE && TARGET_VSX;
 
   /* IEEE 128-bit floating point requires VSX support.  */
-  if (!TARGET_VSX)
+  if (TARGET_FLOAT128_KEYWORD)
     {
-      if (TARGET_FLOAT128_KEYWORD)
+      if (!TARGET_VSX)
 	{
 	  if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) != 0)
 	    error ("-mfloat128 requires VSX support");
 
-	  rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
-				| OPTION_MASK_FLOAT128_KEYWORD
+	  TARGET_FLOAT128_TYPE = 0;
+	  rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_KEYWORD
 				| OPTION_MASK_FLOAT128_HW);
 	}
-
-      else if (TARGET_FLOAT128_TYPE)
+      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);
+	  TARGET_FLOAT128_TYPE = 1;
+	  warning (0, "The -mfloat128 option may not be fully supported");
 	}
     }
 
-  /* -mfloat128 and -mfloat128-hardware internally require the underlying IEEE
-      128-bit floating point support to be enabled.  */
-  if (!TARGET_FLOAT128_TYPE)
-    {
-      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);
-	}
-    }
+  /* Enable the __float128 keyword under Linux by default.  */
+  if (TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_KEYWORD
+      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) == 0)
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_KEYWORD;
 
-  /* 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
+  /* If we have are supporting the float128 type and full ISA 3.0 support,
+     enable -mfloat128-hardware by default.  However, don't enable the
+     __float128 keyword if it was explicitly turned off.  64-bit mode is needed
+     because sometimes the compiler wants to put things in an integer
+     container, and if we don't have __int128 support, it is impossible.  */
+  if (TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW && TARGET_64BIT
       && (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;
@@ -4698,11 +4668,6 @@  rs6000_option_override_internal (bool gl
       rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
     }
 
-  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)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
@@ -4769,10 +4734,12 @@  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
-			   | OPTION_MASK_FLOAT128_TYPE
-			   | OPTION_MASK_FLOAT128_KEYWORD)
-			  & ~rs6000_isa_flags_explicit);
+    {
+      TARGET_FLOAT128_TYPE = 0;
+      rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC
+			     | OPTION_MASK_FLOAT128_KEYWORD)
+			    & ~rs6000_isa_flags_explicit);
+    }
 
   /* Enable Altivec ABI for AIX -maltivec.  */
   if (TARGET_XCOFF && (TARGET_ALTIVEC || TARGET_VSX))
@@ -16868,16 +16835,17 @@  rs6000_init_builtins (void)
      format that uses a pair of doubles, depending on the switches and
      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 if the type is the same as
      long double.  Instead we add a #define for __ibm128 in
-     rs6000_cpu_cpp_builtins to long double.  */
+     rs6000_cpu_cpp_builtins to long double.
+
+     For IEEE 128-bit floating point, always create the type __ieee128.  If the
+     user used -mfloat128, rs6000-c.c will create a define from __float128 to
+     __ieee128.  */
   if (TARGET_LONG_DOUBLE_128 && FLOAT128_IEEE_P (TFmode))
     {
       ibm128_float_type_node = make_node (REAL_TYPE);
@@ -16891,24 +16859,10 @@  rs6000_init_builtins (void)
   else
     ibm128_float_type_node = long_double_type_node;
 
-  if (TARGET_FLOAT128_KEYWORD)
+  if (TARGET_FLOAT128_TYPE)
     {
       ieee128_float_type_node = float128_type_node;
       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;
-      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
-      layout_type (ieee128_float_type_node);
-
-      /* If we are not exporting the __float128/_Float128 keywords, we need a
-	 keyword to get the types created.  Use __ieee128 as the dummy
-	 keyword.  */
-      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
 					      "__ieee128");
     }
 
@@ -32506,11 +32460,14 @@  rs6000_mangle_type (const_tree type)
       if (type == ieee128_float_type_node)
 	return "U10__float128";
 
-      if (type == ibm128_float_type_node)
-	return "g";
+      if (TARGET_LONG_DOUBLE_128)
+	{
+	  if (type == long_double_type_node)
+	    return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
 
-      if (type == long_double_type_node && TARGET_LONG_DOUBLE_128)
-	return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
+	  if (type == ibm128_float_type_node)
+	    return "g";
+	}
     }
 
   /* Mangle IBM extended float long double as `g' (__float128) on
@@ -35987,7 +35944,7 @@  rs6000_floatn_mode (int n, bool extended
 	  return DFmode;
 
 	case 64:
-	  if (TARGET_FLOAT128_KEYWORD)
+	  if (TARGET_FLOAT128_TYPE)
 	    return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
 	  else
 	    return VOIDmode;
@@ -36011,7 +35968,7 @@  rs6000_floatn_mode (int n, bool extended
 	  return DFmode;
 
 	case 128:
-	  if (TARGET_FLOAT128_KEYWORD)
+	  if (TARGET_FLOAT128_TYPE)
 	    return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
 	  else
 	    return VOIDmode;
@@ -36101,9 +36058,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_KEYWORD,	false, false },
-  { "float128-type",		OPTION_MASK_FLOAT128_TYPE,	false, false },
-  { "float128-hardware",	OPTION_MASK_FLOAT128_HW,	false, false },
+  { "float128",			OPTION_MASK_FLOAT128_KEYWORD,	false, true  },
+  { "float128-hardware",	OPTION_MASK_FLOAT128_HW,	false, true  },
   { "fprnd",			OPTION_MASK_FPRND,		false, true  },
   { "hard-dfp",			OPTION_MASK_DFP,		false, true  },
   { "htm",			OPTION_MASK_HTM,		false, true  },
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 251056)
+++ gcc/config/rs6000/rs6000.h	(.../gcc/config/rs6000)	(working copy)
@@ -643,7 +643,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_TYPE		OPTION_MASK_FLOAT128_TYPE
+#define MASK_FLOAT128_KEYWORD		OPTION_MASK_FLOAT128_KEYWORD
 #define MASK_FPRND			OPTION_MASK_FPRND
 #define MASK_P8_FUSION			OPTION_MASK_P8_FUSION
 #define MASK_HARD_FLOAT			OPTION_MASK_HARD_FLOAT
@@ -2590,7 +2590,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_TYPE /* IEEE 128-bit float.  */
+#define RS6000_BTM_FLOAT128	MASK_FLOAT128_KEYWORD /* IEEE 128-bit float.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
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 251056)
+++ gcc/config/rs6000/rs6000-c.c	(.../gcc/config/rs6000)	(working copy)
@@ -575,6 +575,18 @@  rs6000_target_modify_macros (bool define
      2. If TARGET_ALTIVEC is turned off.  */
   if ((flags & OPTION_MASK_CRYPTO) != 0)
     rs6000_define_or_undefine_macro (define_p, "__CRYPTO__");
+  if ((flags & OPTION_MASK_FLOAT128_KEYWORD) != 0)
+    {
+      rs6000_define_or_undefine_macro (define_p, "__FLOAT128__");
+      if (define_p)
+	rs6000_define_or_undefine_macro (true, "__float128=__ieee128");
+      else
+	rs6000_define_or_undefine_macro (false, "__float128");
+    }
+  /* OPTION_MASK_FLOAT128_HARDWARE can be turned on if -mcpu=power9 is used or
+     via the target attribute/pragma.  */
+  if ((flags & OPTION_MASK_FLOAT128_HW) != 0)
+    rs6000_define_or_undefine_macro (define_p, "__FLOAT128_HARDWARE__");
 
   /* options from the builtin masks.  */
   /* Note that RS6000_BTM_PAIRED is enabled only if
@@ -602,24 +614,14 @@  rs6000_cpu_cpp_builtins (cpp_reader *pfi
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
-  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 && FLOAT128_IBM_P (TFmode))
     builtin_define ("__ibm128=long double");
 #ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
   builtin_define ("__BUILTIN_CPU_SUPPORTS__");
 #endif
 
-  /* We needed to create a keyword if -mfloat128-type was used but not -mfloat,
-     so we used __ieee128.  If -mfloat128 was used, create a #define back to
-     the real keyword in case somebody used it.  */
-  if (TARGET_FLOAT128_KEYWORD)
-    builtin_define ("__ieee128=__float128");
-
   if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM)
     {
       /* Define the AltiVec syntactic elements.  */
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/doc)	(revision 251056)
+++ gcc/doc/invoke.texi	(.../gcc/doc)	(working copy)
@@ -21946,15 +21946,19 @@  Enable/disable the @var{__float128} keyw
 and use either software emulation for IEEE 128-bit floating point or
 hardware instructions.
 
-The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7}, or
-@option{-mcpu=power8}) must be enabled to use the @option{-mfloat128}
-option.  The @option{-mfloat128} option only works on PowerPC 64-bit
-Linux systems.
-
-If you use the ISA 3.0 instruction set (@option{-mcpu=power9}), the
-@option{-mfloat128} option will also enable the generation of ISA 3.0
-IEEE 128-bit floating point instructions.  Otherwise, IEEE 128-bit
-floating point will be done with software emulation.
+The default for @option{-mfloat128} is enabled on PowerPC Linux
+systems using the VSX instruction set, and disabled on other systems.
+
+The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7},
+@option{-mcpu=power8}) must be enabled to use the IEEE 128-bit
+floating point support.  The IEEE 128-bit floating point support only
+works on PowerPC Linux systems.
+
+If you use the ISA 3.0 instruction set (@option{-mpower9-vector} or
+@option{-mcpu=power9}) on a 64-bit system, the IEEE 128-bit floating
+point support will also enable the generation of ISA 3.0 IEEE 128-bit
+floating point instructions.  Otherwise, IEEE 128-bit floating point
+will be done with software emulation.
 
 @item -mfloat128-hardware
 @itemx -mno-float128-hardware
@@ -21963,12 +21967,9 @@  floating point will be done with softwar
 Enable/disable using ISA 3.0 hardware instructions to support the
 @var{__float128} data type.
 
-If you use @option{-mfloat128-hardware}, it will enable the option
-@option{-mfloat128} as well.
-
-If you select ISA 3.0 instructions with @option{-mcpu=power9}, but do
-not use either @option{-mfloat128} or @option{-mfloat128-hardware},
-the IEEE 128-bit floating point support will not be enabled.
+The default for @option{-mfloat128-hardware} is enabled on PowerPC
+Linux systems using the ISA 3.0 instruction set, and disabled on other
+systems.
 
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
Index: gcc/testsuite/gcc.target/powerpc/float128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-1.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-1.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-do run { target { powerpc*-*-linux* } } } */
 /* { dg-require-effective-target ppc_float128_sw } */
-/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mvsx -O2" } */
 
 #ifdef DEBUG
 #include <stdio.h>
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 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-mix.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,7 +1,6 @@ 
 /* { dg-do compile { target { powerpc*-*-linux* } } } */
-/* { dg-require-effective-target powerpc_float128_sw_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx" } */
 
 
 /* Test to make sure that __float128 and long double cannot be combined together.  */
Index: gcc/testsuite/gcc.target/powerpc/float128-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-2.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-2.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-do run { target { powerpc*-*-linux* } } } */
 /* { dg-require-effective-target ppc_float128_sw } */
-/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mvsx -O2" } */
 
 /*
  * Test program to make sure we are getting more precision than the 53 bits we
Index: gcc/testsuite/gcc.target/powerpc/float128-3.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-3.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-3.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 251130)
@@ -0,0 +1,21 @@ 
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx -mno-float128" } */
+
+/* Test that we can use #pragma GCC target to enable -mfloat128.  */
+
+#ifdef __FLOAT128__
+#error "-mno-float128 should disable initially defining __FLOAT128__"
+#endif
+
+#pragma GCC target("float128")
+
+#ifndef __FLOAT128__
+#error "#pragma GCC target(\"float128\") should enable -mfloat128"
+#endif
+
+__float128
+qadd (__float128 a, __float128 b)
+{
+  return a+b;
+}
Index: gcc/testsuite/gcc.target/powerpc/float128-hw.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-hw.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-hw.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,7 +1,6 @@ 
 /* { dg-do compile { target { powerpc*-*-* && 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" } */
+/* { dg-options "-mpower9-vector -O2" } */
 
 __float128 f128_add (__float128 a, __float128 b) { return a+b; }
 __float128 f128_sub (__float128 a, __float128 b) { return a-b; }
Index: gcc/testsuite/gcc.target/powerpc/float128-5.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-5.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-5.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 251134)
@@ -0,0 +1,24 @@ 
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-O2 -mpower9-vector -mno-float128" } */
+
+/* Test that we can use #pragma GCC target to enable -mfloat128 and generate
+   code on ISA 3.0 for the float128 built-in functions.  */
+
+#ifdef __FLOAT128__
+#error "-mno-float128 should disable initially defining __FLOAT128__"
+#endif
+
+#pragma GCC target("float128")
+
+#ifndef __FLOAT128__
+#error "#pragma GCC target(\"float128\") should enable -mfloat128"
+#endif
+
+__float128
+qabs (__float128 a)
+{
+  return __builtin_fabsq (a);
+}
+
+/* { dg-final { scan-assembler "xsabsqp"  } } */
Index: gcc/testsuite/gcc.target/powerpc/float128-complex-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-complex-1.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-complex-1.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,7 +1,6 @@ 
 /* { dg-do compile { target { powerpc*-*-linux* } } } */
 /* { dg-require-effective-target powerpc_float128_sw_ok } */
-/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */
-/* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
+/* { dg-options "-O2 -mvsx" } */
 
 #ifndef NO_FLOAT
 typedef _Complex float	float_complex;
Index: gcc/testsuite/gcc.target/powerpc/float128-complex-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-complex-2.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-complex-2.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,7 +1,7 @@ 
 /* { dg-do compile { target { powerpc*-*-linux* } } } */
 /* { dg-require-effective-target powerpc_float128_hw_ok } */
 /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
-/* { dg-options "-O2 -mcpu=power9 -mfloat128 -mfloat128-hardware" } */
+/* { dg-options "-O2 -mpower9-vector -mfloat128-hardware" } */
 
 #ifndef NO_FLOAT
 typedef _Complex float	float_complex;
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 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-type-1.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,16 +1,21 @@ 
 /* { dg-do compile { target { powerpc64*-*-linux* && lp64 } } } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
 /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
-/* { dg-options "-mcpu=power8 -O2" } */
+/* { dg-options "-mcpu=power8 -O2 -mno-float128" } */
 
-/* This test tests whether -mfloat128-type (which enables the underlying IEEE
-   128-bit floating point) is enabled by default on VSX Linux 64-bit systems,
-   even if the keywords __float128 and _Float128 (-mfloat128) are not enabled
-   via the -mfloat128 switch.  Test that power8 generates a call to the
+/* This test tests whether the underlying IEEE 128-bit floating point) is
+   enabled by default on VSX Linux 64-bit systems, even if the keyword
+   __float128 is not enabled .  Test that power8 generates a call to the
    __addkf3 emulation function.  */
 
+#ifdef __LONG_DOUBLE_IEEE128
+typedef double          __attribute__((__mode__(__TF__))) f128_t;
+typedef _Complex double __attribute__((__mode__(__TC__))) f128c_t;
+
+#else
 typedef double          __attribute__((__mode__(__KF__))) f128_t;
 typedef _Complex double __attribute__((__mode__(__KC__))) f128c_t;
+#endif
 
 f128_t
 add_scalar (f128_t a, f128_t b)
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 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-type-2.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,19 +1,21 @@ 
 /* { 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" } */
+/* { dg-options "-mcpu=power9 -O2 -mno-float128" } */
 
-/* This test tests whether -mfloat128-type (which enables the underlying IEEE
-   128-bit floating point) is enabled by default on VSX Linux 64-bit systems,
-   even if the keywords __float128 and _Float128 (-mfloat128) are not enabled
-   via the -mfloat128 switch.  Test that power9 generates the xsaddqp
+/* This test tests whether the underlying IEEE 128-bit floating point) is
+   enabled by default on VSX Linux 64-bit systems, even if the keyword
+   __float128 is not enabled .  Test that power9 generates the xsaddqp
    instruction.  */
 
-/* The effective target powerpc_float128_hw_ok is not used, as that will pass
-   -mfloat128.  */
+#ifdef __LONG_DOUBLE_IEEE128
+typedef double          __attribute__((__mode__(__TF__))) f128_t;
+typedef _Complex double __attribute__((__mode__(__TC__))) f128c_t;
 
+#else
 typedef double          __attribute__((__mode__(__KF__))) f128_t;
 typedef _Complex double __attribute__((__mode__(__KC__))) f128c_t;
+#endif
 
 f128_t
 add_scalar (f128_t a, f128_t b)
Index: gcc/testsuite/gcc.target/powerpc/float128-cmp.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-cmp.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 251056)
+++ gcc/testsuite/gcc.target/powerpc/float128-cmp.c	(.../gcc/testsuite/gcc.target/powerpc)	(working copy)
@@ -1,6 +1,6 @@ 
 /* { dg-do run { target { powerpc*-*-linux* } } } */
 /* { dg-require-effective-target ppc_float128_sw } */
-/* { dg-options "-mvsx -O2 -mfloat128" } */
+/* { dg-options "-mvsx -O2" } */
 
 #include <stddef.h>
 #include <stdlib.h>
Index: gcc/testsuite/gcc.target/powerpc/float128-4.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-4.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc)	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-4.c	(.../gcc/testsuite/gcc.target/powerpc)	(revision 251105)
@@ -0,0 +1,152 @@ 
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mvsx -O2" } */
+
+/* This is the same as test float128-1.c, using the _Float128 keyword instead
+   of __float128, and not using -mfloat128.  */
+
+#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.0f128;
+  _Float128 two		= 2.0f128;
+  _Float128 three	= 3.0f128;
+  _Float128 four	= 4.0f128;
+  _Float128 five	= 5.0f128;
+  _Float128 add_result = (1.0f128 + 2.0f128);
+  _Float128 mul_result = ((1.0f128 + 2.0f128) * 3.0f128);
+  _Float128 div_result = (((1.0f128 + 2.0f128) * 3.0f128) / 4.0f128);
+  _Float128 sub_result = ((((1.0f128 + 2.0f128) * 3.0f128) / 4.0f128)
+			  - 5.0f128);
+  _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;
+}