diff mbox

[RFC] Proposed PowerPC IEEE 128-bit floating point changes

Message ID 20170721191757.GA11603@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner July 21, 2017, 7:17 p.m. UTC
This patch makes some changes to the way the PowerPC handles IEEE 128-bit
floating point, and I wanted to point out where I would like to change the
compiler, but be open to doing it in other ways.

There are 3 changes in this patch, and presumably more work to do beyond this
patch.

The first change is to enable the C language to use _Float128 keyword (but not
__float128) without having to use the -mfloat128 option on power7-power9
systems.  My question is in the TR that introduced _Float128, is there any
expectation that outside of the built-in functions we already provide, that we
need to provide runtime functions?  Yes, glibc 2.26 will be coming along
shortly, and it should provide most/all of the F128 functions, but distros
won't pick this library up for some time.

I would like to enable it, but I want to avoid the problem that we have with
__float128 in that once the keyword is supported, it is assumed everything is
supported.  GCC and GLIBC run on different cycles (and different people work on
it), and so you typically have to have GCC add support before GLIBC can use it.

We've discovered that boost and libstdc++ both assume the full library support
exists if the __float128 keyword is used.  We will eventually need to tackle
both of these libraries, but we need to the full GLIBC support (or libquadmath)
to provide this functionality.

Part of the reason for wanting to enable _Float128 without library support or
an explicit -mfloat128 is the types and built-in functions have to be set up at
compiler startup, and it makes the second change simpler.

The second change is to allow #pragma GCC target and attribute((target(...)))
to enable IEEE 128-bit __float128 on a per module basis (PR 70589).  If I don't
enable _Float128 unconditionally, I've discovered that I couldn't find a way to
allow _Float128 access after compiler startup.

In the second change, I changed how we handle __float128 internally.
Previously, we would create the keyword __float128 if -mfloat128, and we would
create the same type with the undocumented __ieee128 keyword (you need a
keyword to enable the type).  Now, I always create the __ieee128 keyword, and
if -mfloat128 (or pragma/attribute) is enabled, I add a define:

	#define __float128 __ieee128

It was a lot simpler to do it this way, rather than trying to keep track of
whether the real keyword was __float128 or __ieee128, and do the appropriate
define or undef.

The third change is to add cpu names 'power7f', 'power8f', and 'power9f' that
enable the appropriate power<n> architecture but also does a -mfloat128.  The
motavation here is you cannot use either #pragma GCC target anywhere or the
target attribute on the function with a target_clones attribute declaration.

The question is do people see the need for -mcpu=power9f?  Or should those be
dropped? Assuming we are keeping those, is there a name people prefer instead
of just using a 'f' suffix.  Note, the GCC infrastructure does not allow a
hyphen in the name in creating configargs.h for --with-cpu=<xxx>, etc.

At the current time, you cannot use --with-cpu=power8f (it fails in configuring
libstdc++, which says that GLIBC supports __float128), but as GLIBC 2.26
becomes more refined, hopefully it will work someday.

In writing the tests, I discovered two of the float128 tests could have the
target requiements/options tweaked, and I included those changes here.  I also
discovered we had parallel bits for setting up power7, and I used the ISA 2.06
mask in the power7 definition.

So comments on how to proceed?

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

	PR target/70589
	* config.gcc (powerpc*-*-*): Add support for -mcpu=power{7,8,9}f
	that combines -mcpu=power{7,8,9} with -mfloat128.
	* config/rs6000/rs6000-cpus.def (OTHER_IEEE_SW_MASKS): New mask of
	the float128 software/hardware options.
	(OTHER_IEEE_HW_MASKS): Likewise.
	(power7 cpu): Replace masks with ISA_2_6_MASKS_SERVER.
	(power7f): New cpu target that combines a particular machine with
	-mfloat128.
	(power8f): Likewise.
	(power9f): Likewise.
	* config/rs6000/rs6000-tables.opt: Regenerate.
	* config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Add
	support for allowing -mfloat128 to be enabled via target pragma or
	attribute.  Always use __ieee128 for the IEEE 128-bit floating
	point internal type, and if -mfloat128, add a define from
	__float128 to __ieee128.
	(rs6000_cpu_cpp_builtins): Likewise.
	* config/rs6000/rs6000.c (rs6000_init_builtins): Enable _Float128
	if -mfloat128-type is enabled (on by default for VSX systems)
	rather than -mfloat128 (which controls __float128).
	(rs6000_floatn_mode): Likewise.
	(rs6000_opt_masks): Allow float128 and float128-hardware target
	options to be set.
	* doc/invoke.texi (PowerPC options): Document -mcpu=power{7,8,9}f.

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

	PR target/70589
	* gcc/testsuite/gcc.target/powerpc/float128-3.c: New test.
	* gcc/testsuite/gcc.target/powerpc/float128-4.c: Likewise.
	* gcc/testsuite/gcc.target/powerpc/float128-5.c: Likewise.
	* gcc/testsuite/gcc.target/powerpc/float128-1.c: Fix test to just
	use -mvsx instead of hardwiring the cpu to power7.  Delete the
	option -static-libgcc, which is not needed.
	* gcc/testsuite/gcc.target/powerpc/float128-2.c: Likewise.

Comments

Segher Boessenkool July 24, 2017, 9:21 a.m. UTC | #1
On Fri, Jul 21, 2017 at 03:17:57PM -0400, Michael Meissner wrote:
> The first change is to enable the C language to use _Float128 keyword (but not
> __float128) without having to use the -mfloat128 option on power7-power9
> systems.  My question is in the TR that introduced _Float128, is there any
> expectation that outside of the built-in functions we already provide, that we
> need to provide runtime functions?  Yes, glibc 2.26 will be coming along
> shortly, and it should provide most/all of the F128 functions, but distros
> won't pick this library up for some time.
> 
> I would like to enable it, but I want to avoid the problem that we have with
> __float128 in that once the keyword is supported, it is assumed everything is
> supported.  GCC and GLIBC run on different cycles (and different people work on
> it), and so you typically have to have GCC add support before GLIBC can use it.
> 
> We've discovered that boost and libstdc++ both assume the full library support
> exists if the __float128 keyword is used.  We will eventually need to tackle
> both of these libraries, but we need to the full GLIBC support (or libquadmath)
> to provide this functionality.

There isn't much we can do about libraries (or any other code) making
bad assumptions.  Reducing the pain is the best we can do.

> The third change is to add cpu names 'power7f', 'power8f', and 'power9f' that
> enable the appropriate power<n> architecture but also does a -mfloat128.  The
> motavation here is you cannot use either #pragma GCC target anywhere or the
> target attribute on the function with a target_clones attribute declaration.

Eww.  What a horrible hack.  Let's please find a sane way to handle this.

Float128 is not a feature only some power[789] variants have (and also it
could work on *all* targets), it also isn't some specific configuration
of the target (like LE is).


Segher
Joseph Myers July 31, 2017, 8:43 p.m. UTC | #2
On Fri, 21 Jul 2017, Michael Meissner wrote:

> The first change is to enable the C language to use _Float128 keyword (but not
> __float128) without having to use the -mfloat128 option on power7-power9
> systems.  My question is in the TR that introduced _Float128, is there any
> expectation that outside of the built-in functions we already provide, that we
> need to provide runtime functions?  Yes, glibc 2.26 will be coming along
> shortly, and it should provide most/all of the F128 functions, but distros
> won't pick this library up for some time.

In formal standards terms, TS 18661-3 builds on TS 18661-1 (for binary 
floating point) or 18661-2 (for decimal floating point), both of which add 
the contents of <fenv.h>, <math.h> and the numeric conversion functions 
from <stdlib.h> to the library features required of freestanding 
implementations.

I don't think that makes any difference to what GCC should do, however.  
Just as stdatomic.h is provided by GCC, though strictly a hosted library 
feature rather than one required of freestanding implementations, and just 
as GCC always requires a C library to provide memcpy / memmove / memset, 
even the case of a freestanding implementation requires a cooperating 
compiler / library pair, and in this case it makes the most sense for 
those library facilities (both C11 ones and newer TS 18661 ones such as 
for float128) to come from an external libc/libm.  At some point I should 
update standards.texi to discuss these variations from the old rule of 
thumb of GCC providing exactly those library facilities required of 
freestanding implementations.  Practically, code expecting compiler 
support for _Float128 to imply library support is just like code expecting 
__STDC_VERSION__ to imply C11 library support; people may write such code, 
but it's not practically portable.
diff mbox

Patch

Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config.gcc)	(revision 250405)
+++ gcc/config.gcc	(.../gcc/config.gcc)	(working copy)
@@ -461,7 +461,7 @@  powerpc*-*-*)
 	extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h"
 	extra_headers="${extra_headers} paired.h"
 	case x$with_cpu in
-	    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500)
+	    xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500|xpower[789]f)
 		cpu_is_64bit=yes
 		;;
 	esac
@@ -4296,7 +4296,7 @@  case "${target}" in
 				eval "with_$which=405"
 				;;
 			"" | common | native \
-			| power[3456789] | power5+ | power6x \
+			| power[3456789] | power5+ | power6x | power[789]f \
 			| powerpc | powerpc64 | powerpc64le \
 			| rs64 \
 			| 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
Index: gcc/config/rs6000/rs6000-tables.opt
===================================================================
--- gcc/config/rs6000/rs6000-tables.opt	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 250405)
+++ gcc/config/rs6000/rs6000-tables.opt	(.../gcc/config/rs6000)	(working copy)
@@ -183,14 +183,23 @@  EnumValue
 Enum(rs6000_cpu_opt_value) String(power9) Value(51)
 
 EnumValue
-Enum(rs6000_cpu_opt_value) String(powerpc) Value(52)
+Enum(rs6000_cpu_opt_value) String(power7f) Value(52)
 
 EnumValue
-Enum(rs6000_cpu_opt_value) String(powerpc64) Value(53)
+Enum(rs6000_cpu_opt_value) String(power8f) Value(53)
 
 EnumValue
-Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(54)
+Enum(rs6000_cpu_opt_value) String(power9f) Value(54)
 
 EnumValue
-Enum(rs6000_cpu_opt_value) String(rs64) Value(55)
+Enum(rs6000_cpu_opt_value) String(powerpc) Value(55)
+
+EnumValue
+Enum(rs6000_cpu_opt_value) String(powerpc64) Value(56)
+
+EnumValue
+Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(57)
+
+EnumValue
+Enum(rs6000_cpu_opt_value) String(rs64) Value(58)
 
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 250405)
+++ gcc/config/rs6000/rs6000-cpus.def	(.../gcc/config/rs6000)	(working copy)
@@ -73,6 +73,12 @@ 
 				 | OPTION_MASK_P9_MISC			\
 				 | OPTION_MASK_P9_VECTOR)
 
+/* Extra masks to turn on for IEEE 128-bit floating point support.  */
+#define OTHER_IEEE_SW_MASKS	(OPTION_MASK_FLOAT128_TYPE		\
+				 | OPTION_MASK_FLOAT128_KEYWORD)
+
+#define OTHER_IEEE_HW_MASKS	(OTHER_IEEE_SW_MASKS | OPTION_MASK_FLOAT128_HW)
+
 /* Support for the IEEE 128-bit floating point hardware requires a lot of the
    VSX instructions that are part of ISA 3.0.  */
 #define ISA_3_0_MASKS_IEEE	(OPTION_MASK_VSX			\
@@ -251,13 +257,16 @@  RS6000_CPU ("power6", PROCESSOR_POWER6, 
 RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT
 	    | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND
 	    | MASK_CMPB | MASK_DFP | MASK_MFPGPR | MASK_RECIP_PRECISION)
-RS6000_CPU ("power7", PROCESSOR_POWER7,   /* Don't add MASK_ISEL by default */
-	    POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF
-	    | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD
-	    | MASK_VSX | MASK_RECIP_PRECISION | OPTION_MASK_UPPER_REGS_DF
-	    | OPTION_MASK_UPPER_REGS_DI)
+RS6000_CPU ("power7", PROCESSOR_POWER7, MASK_POWERPC64 | ISA_2_6_MASKS_SERVER)
 RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
 RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER)
+/* Variants that enable -mfloat128 automatically.  */
+RS6000_CPU ("power7f", PROCESSOR_POWER7, MASK_POWERPC64 \
+	    | ISA_2_6_MASKS_SERVER | OTHER_IEEE_SW_MASKS)
+RS6000_CPU ("power8f", PROCESSOR_POWER8, MASK_POWERPC64 \
+	    | ISA_2_7_MASKS_SERVER | OTHER_IEEE_SW_MASKS)
+RS6000_CPU ("power9f", PROCESSOR_POWER9, MASK_POWERPC64 \
+	    | ISA_3_0_MASKS_SERVER | OTHER_IEEE_HW_MASKS)
 RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0)
 RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64)
 RS6000_CPU ("powerpc64le", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER)
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 250405)
+++ gcc/config/rs6000/rs6000-c.c	(.../gcc/config/rs6000)	(working copy)
@@ -609,6 +609,21 @@  rs6000_target_modify_macros (bool define
      2. If TARGET_P8_VECTOR is off.  */
   if ((flags & OPTION_MASK_UPPER_REGS_SF) != 0)
     rs6000_define_or_undefine_macro (define_p, "__UPPER_REGS_SF__");
+  /* OPTION_MASK_FLOAT128 can be turned on via the -mfloat128 option or via the
+     target attribute/pragma.  The -mfloat128-keyword option must be in
+     effect.  */
+  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
@@ -636,24 +651,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/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 250405)
+++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
@@ -16991,16 +16991,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);
@@ -17014,24 +17015,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");
     }
 
@@ -36212,7 +36199,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;
@@ -36236,7 +36223,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;
@@ -36326,9 +36313,9 @@  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",			OPTION_MASK_FLOAT128_KEYWORD,	false, true  },
   { "float128-type",		OPTION_MASK_FLOAT128_TYPE,	false, false },
-  { "float128-hardware",	OPTION_MASK_FLOAT128_HW,	false, false },
+  { "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/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/doc)	(revision 250405)
+++ gcc/doc/invoke.texi	(.../gcc/doc)	(working copy)
@@ -21675,6 +21675,7 @@  Supported values for @var{cpu_type} are 
 @samp{titan}, @samp{power3}, @samp{power4}, @samp{power5}, @samp{power5+},
 @samp{power6}, @samp{power6x}, @samp{power7}, @samp{power8},
 @samp{power9}, @samp{powerpc}, @samp{powerpc64}, @samp{powerpc64le},
+@samp{power7f}, @samp{power8f}, @samp{power9f}
 and @samp{rs64}.
 
 @option{-mcpu=powerpc}, @option{-mcpu=powerpc64}, and
@@ -21687,6 +21688,10 @@  The other options specify a specific pro
 those options runs best on that processor, and may not run at all on
 others.
 
+The options @samp{power7f}, @samp{power8f}, and @samp{power9f} set the
+processor to power7, power8, or power9, and also enable the
+@option{-mfloat128} option.
+
 The @option{-mcpu} options automatically enable or disable the
 following options:
 
@@ -21961,6 +21966,10 @@  If you use the ISA 3.0 instruction set (
 IEEE 128-bit floating point instructions.  Otherwise, IEEE 128-bit
 floating point will be done with software emulation.
 
+If you use @option{-mcpu=power7f} or @option{-mcpu=power8f}, it sets
+the @option{-mfloat128} option as well as setting the processor type
+to @var{power7} (ISA 2.05) or @var{power8} (ISA 2.06).
+
 @item -mfloat128-hardware
 @itemx -mno-float128-hardware
 @opindex mfloat128-hardware
@@ -21975,6 +21984,10 @@  If you select ISA 3.0 instructions with 
 not use either @option{-mfloat128} or @option{-mfloat128-hardware},
 the IEEE 128-bit floating point support will not be enabled.
 
+If you use @option{-mcpu=power9f}, it sets the @option{-mfloat128}
+option as well as setting the processor to @var{power9} (i.e. ISA
+3.0).
+
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
 @opindex mfloat-gprs
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 250406)
@@ -0,0 +1,150 @@ 
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7f" } } */
+/* { dg-options "-mcpu=power7f -O2" } */
+
+/* This test is a clone of float128-1.c, using -mcpu=power7f.  */
+
+#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-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 250406)
@@ -0,0 +1,150 @@ 
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_hw } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9f" } } */
+/* { dg-options "-mcpu=power9f -O2" } */
+
+/* This test is a clone of float128-1.c, using -mcpu=power9f.  */
+
+#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-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 250406)
@@ -0,0 +1,21 @@ 
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target powerpc_float128_sw_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-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 250405)
+++ 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 -mfloat128" } */
 
 #ifdef DEBUG
 #include <stdio.h>
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 250405)
+++ 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 -mfloat128" } */
 
 /*
  * Test program to make sure we are getting more precision than the 53 bits we