diff mbox

, Add IEEE 128-bit floating point to PowerPC, patch #1

Message ID 20150522212414.GA25650@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner May 22, 2015, 9:24 p.m. UTC
This patch is the first in a series of patches that will eventually add support
for IEEE 128-bit floating point support to the PowerPC GCC compiler.  At the
current time, we do not plan to change the default for long double.  I added a
new type keyword (__float128) to get access to IEEE 128-bit floating point, and
another (__ibm128) to get access to IBM extended double type.

Until all of the GCC and LIBGCC patches have been committed, you will not be
able to use IEEE 128-bit floating point, and -mfloat128-software will not be
turned on by default.

This patch adds the new modes (KFmode and IFmode) and the switches
(-mfloat128-{none,software}).

Due to the fact that TFmode in the PowerPC compiler either represents IEEE
128-bit floating point or the IBM extended double (double-double) format.  For
most PowerPC users, the default is to use IBM extended double for long double.
Because TFmode can be either floating point format, I added new new modes:

	KFmode	-- IEEE 128-bit floating point
	IFmode	-- IBM extended double floating point

If the default for TFmode is ibm extended double, the port will eventually use
KFmode for IEEE 128-bit floating point.  Likewise if the default for TFmode is
IEEE 128-bit floating point, the port will use TFmode for IEEE 128-bit floating
point, and IFmode for IBM extended double.

I have bootstraped these patches on a power7 and compared them to the unpatched
compiler.  There were no changes when running make check.  Are these patches ok
to install in the trunk?

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

	* config/rs6000/rs6000-modes.def (IFmode): Define IFmode to
	provide access to the IBM extended double floating point mode if
	long double is IEEE 128-bit floating point.
	(KFmode): Define KFmode to provide access to IEEE 128-bit floating
	point if long double is the IBM extended double type.

	* config/rs6000/rs6000.opt (-mfloat128-none): New switches to
	enable adding IEEE 128-bit floating point support.
	(-mfloat128-software): Likewise.
	(-mfloat128-sw): Likewise.

	* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Do not allow
	128-bit floating point types to occupy any register if
	-mlong-double-64.  Do not allow use of IFmode/KFmode unless
	-mfloat128-software is enabled.
	(rs6000_debug_reg_global): Add IEEE 128-bit floating point debug
	support.
	(rs6000_option_override_internal): Add -mfloat128-* support.
	(rs6000_init_builtins): Setup __ibm128 and __float128 type modes.

	* config/rs6000/rs6000.h (rs6000_builtin_type_index): Add ibm128
	and float128 type nodes.
	(ieee128_float_type_node): Likewise.
	(ibm128_float_type_node): Likewise.

Comments

David Edelsohn June 2, 2015, 5:43 p.m. UTC | #1
On Fri, May 22, 2015 at 5:24 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> This patch is the first in a series of patches that will eventually add support
> for IEEE 128-bit floating point support to the PowerPC GCC compiler.  At the
> current time, we do not plan to change the default for long double.  I added a
> new type keyword (__float128) to get access to IEEE 128-bit floating point, and
> another (__ibm128) to get access to IBM extended double type.
>
> Until all of the GCC and LIBGCC patches have been committed, you will not be
> able to use IEEE 128-bit floating point, and -mfloat128-software will not be
> turned on by default.
>
> This patch adds the new modes (KFmode and IFmode) and the switches
> (-mfloat128-{none,software}).
>
> Due to the fact that TFmode in the PowerPC compiler either represents IEEE
> 128-bit floating point or the IBM extended double (double-double) format.  For
> most PowerPC users, the default is to use IBM extended double for long double.
> Because TFmode can be either floating point format, I added new new modes:
>
>         KFmode  -- IEEE 128-bit floating point
>         IFmode  -- IBM extended double floating point
>
> If the default for TFmode is ibm extended double, the port will eventually use
> KFmode for IEEE 128-bit floating point.  Likewise if the default for TFmode is
> IEEE 128-bit floating point, the port will use TFmode for IEEE 128-bit floating
> point, and IFmode for IBM extended double.
>
> I have bootstraped these patches on a power7 and compared them to the unpatched
> compiler.  There were no changes when running make check.  Are these patches ok
> to install in the trunk?

Mike,

What is the purpose of the TARGET_LONG_DOUBLE_128 change in
rs6000_hard_regno_mode_ok()?

+  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
+     types from going in any registers.  Similarly if __float128 is not
+     supported, don't allow __float128/__ibm128 types.  */
+  if (!TARGET_LONG_DOUBLE_128
+      && (mode == TFmode || mode == KFmode || mode == IFmode))
+    return false;

Why is this necessary now?

Thanks, David
Joseph Myers June 2, 2015, 5:55 p.m. UTC | #2
Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over 
floating-point modes including these modes when they shouldn't, as 
discussed previously?

If so, how do you deal (in subsequent patches?) with iterations that 
*should* include these modes?  In particular, where libgcc uses 
__LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an 
interation in c-cppbuiltin.c, how do you handle getting the relevant 
information in libgcc to build applicable libgcc functions for these 
modes?  (I'm presuming that you do want complex arithmetic to work for 
both 128-bit types, for example, although you won't want them to be used 
for intermediate conversions in libgcc operations on other types.)
Michael Meissner June 2, 2015, 6:27 p.m. UTC | #3
On Tue, Jun 02, 2015 at 01:43:08PM -0400, David Edelsohn wrote:
> Mike,
> 
> What is the purpose of the TARGET_LONG_DOUBLE_128 change in
> rs6000_hard_regno_mode_ok()?
> 
> +  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
> +     types from going in any registers.  Similarly if __float128 is not
> +     supported, don't allow __float128/__ibm128 types.  */
> +  if (!TARGET_LONG_DOUBLE_128
> +      && (mode == TFmode || mode == KFmode || mode == IFmode))
> +    return false;
> 
> Why is this necessary now?

I was trying to avoid problems if there was no move/convert patterns for
KFmode/IFmode.  I made it when I transitioned from SPECIAL_FLOAT_MODE to
FRACTIONAL_FLOAT_MODE.  Given there are 2 fractional float modes now, if the
compiler was automatically trying to find a larger type than DFmode, it would
first try IFmode, then KFmode, and finally TFmode (under the old
SPECIAL_FLOAT_MODE, it wouldn't look at those types in the normal course of
things).

With the current set of patches, there is no move or convert options for
IFmode/KFmode, but also the emulator functions are not properly defined.

I can remove the lines and do the build again, if you would prefer.  I don't
think it is strictly necessary.
Michael Meissner June 2, 2015, 6:32 p.m. UTC | #4
On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote:
> Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over 
> floating-point modes including these modes when they shouldn't, as 
> discussed previously?
> 
> If so, how do you deal (in subsequent patches?) with iterations that 
> *should* include these modes?  In particular, where libgcc uses 
> __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an 
> interation in c-cppbuiltin.c, how do you handle getting the relevant 
> information in libgcc to build applicable libgcc functions for these 
> modes?  (I'm presuming that you do want complex arithmetic to work for 
> both 128-bit types, for example, although you won't want them to be used 
> for intermediate conversions in libgcc operations on other types.)

I have a catch-22 situation.  We can't really do the glibc stuff until we have
the compiler.  Right now, I use a makefile on libgcc/config/rs6000 that copies
the various TF files and modifies it for KF files.

After we get the basic support in, we can then start tackling glibc.  It may be
when we get to doing the work in glibc itself, we will need to make further
modifications.  However, in order for the glibc people to start, I need the
basic support in the compiler in the tree.
David Edelsohn June 2, 2015, 7:26 p.m. UTC | #5
On Tue, Jun 2, 2015 at 2:27 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> On Tue, Jun 02, 2015 at 01:43:08PM -0400, David Edelsohn wrote:
>> Mike,
>>
>> What is the purpose of the TARGET_LONG_DOUBLE_128 change in
>> rs6000_hard_regno_mode_ok()?
>>
>> +  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
>> +     types from going in any registers.  Similarly if __float128 is not
>> +     supported, don't allow __float128/__ibm128 types.  */
>> +  if (!TARGET_LONG_DOUBLE_128
>> +      && (mode == TFmode || mode == KFmode || mode == IFmode))
>> +    return false;
>>
>> Why is this necessary now?
>
> I was trying to avoid problems if there was no move/convert patterns for
> KFmode/IFmode.  I made it when I transitioned from SPECIAL_FLOAT_MODE to
> FRACTIONAL_FLOAT_MODE.  Given there are 2 fractional float modes now, if the
> compiler was automatically trying to find a larger type than DFmode, it would
> first try IFmode, then KFmode, and finally TFmode (under the old
> SPECIAL_FLOAT_MODE, it wouldn't look at those types in the normal course of
> things).
>
> With the current set of patches, there is no move or convert options for
> IFmode/KFmode, but also the emulator functions are not properly defined.

The first patch is okay.  This clearly is going to require a lot of
interations with libgcc and GLIBC.

Thanks, David
Joseph Myers June 2, 2015, 8:14 p.m. UTC | #6
On Tue, 2 Jun 2015, Michael Meissner wrote:

> On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote:
> > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over 
> > floating-point modes including these modes when they shouldn't, as 
> > discussed previously?
> > 
> > If so, how do you deal (in subsequent patches?) with iterations that 
> > *should* include these modes?  In particular, where libgcc uses 
> > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an 
> > interation in c-cppbuiltin.c, how do you handle getting the relevant 
> > information in libgcc to build applicable libgcc functions for these 
> > modes?  (I'm presuming that you do want complex arithmetic to work for 
> > both 128-bit types, for example, although you won't want them to be used 
> > for intermediate conversions in libgcc operations on other types.)
> 
> I have a catch-22 situation.  We can't really do the glibc stuff until we have
> the compiler.  Right now, I use a makefile on libgcc/config/rs6000 that copies
> the various TF files and modifies it for KF files.

The functions I'm mainly thinking of are the libgcc2.c ones rather than 
the soft-fp ones (powi?f2 mul?c3 div?c3).

> After we get the basic support in, we can then start tackling glibc.  It may be
> when we get to doing the work in glibc itself, we will need to make further
> modifications.  However, in order for the glibc people to start, I need the
> basic support in the compiler in the tree.

It's not obvious what glibc support should look like in the absence of a 
change to the default for long double; that would require discussion on 
libc-alpha at an early stage to establish a consensus on the design.

libquadmath support should be easy (given working compiler / libgcc 
support).  But if you want more than libquadmath support, there are 
several possible forms for support in glibc proper depending on e.g. 
whether you want to support a -m option to change long double, or using 
the functions via the __float128 type name and separate names for the 
functions, or both.
David Edelsohn June 2, 2015, 8:24 p.m. UTC | #7
On Tue, Jun 2, 2015 at 4:14 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> On Tue, 2 Jun 2015, Michael Meissner wrote:
>
>> On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote:
>> > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over
>> > floating-point modes including these modes when they shouldn't, as
>> > discussed previously?
>> >
>> > If so, how do you deal (in subsequent patches?) with iterations that
>> > *should* include these modes?  In particular, where libgcc uses
>> > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an
>> > interation in c-cppbuiltin.c, how do you handle getting the relevant
>> > information in libgcc to build applicable libgcc functions for these
>> > modes?  (I'm presuming that you do want complex arithmetic to work for
>> > both 128-bit types, for example, although you won't want them to be used
>> > for intermediate conversions in libgcc operations on other types.)
>>
>> I have a catch-22 situation.  We can't really do the glibc stuff until we have
>> the compiler.  Right now, I use a makefile on libgcc/config/rs6000 that copies
>> the various TF files and modifies it for KF files.
>
> The functions I'm mainly thinking of are the libgcc2.c ones rather than
> the soft-fp ones (powi?f2 mul?c3 div?c3).
>
>> After we get the basic support in, we can then start tackling glibc.  It may be
>> when we get to doing the work in glibc itself, we will need to make further
>> modifications.  However, in order for the glibc people to start, I need the
>> basic support in the compiler in the tree.
>
> It's not obvious what glibc support should look like in the absence of a
> change to the default for long double; that would require discussion on
> libc-alpha at an early stage to establish a consensus on the design.
>
> libquadmath support should be easy (given working compiler / libgcc
> support).  But if you want more than libquadmath support, there are
> several possible forms for support in glibc proper depending on e.g.
> whether you want to support a -m option to change long double, or using
> the functions via the __float128 type name and separate names for the
> functions, or both.

Sounds like a fun night at a Czech pub during GNU Cauldron.

- David
Michael Meissner June 2, 2015, 8:50 p.m. UTC | #8
On Tue, Jun 02, 2015 at 08:14:12PM +0000, Joseph Myers wrote:
> On Tue, 2 Jun 2015, Michael Meissner wrote:
> 
> > On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote:
> > > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over 
> > > floating-point modes including these modes when they shouldn't, as 
> > > discussed previously?
> > > 
> > > If so, how do you deal (in subsequent patches?) with iterations that 
> > > *should* include these modes?  In particular, where libgcc uses 
> > > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an 
> > > interation in c-cppbuiltin.c, how do you handle getting the relevant 
> > > information in libgcc to build applicable libgcc functions for these 
> > > modes?  (I'm presuming that you do want complex arithmetic to work for 
> > > both 128-bit types, for example, although you won't want them to be used 
> > > for intermediate conversions in libgcc operations on other types.)
> > 
> > I have a catch-22 situation.  We can't really do the glibc stuff until we have
> > the compiler.  Right now, I use a makefile on libgcc/config/rs6000 that copies
> > the various TF files and modifies it for KF files.
> 
> The functions I'm mainly thinking of are the libgcc2.c ones rather than 
> the soft-fp ones (powi?f2 mul?c3 div?c3).

Ok, I will look into those.

> > After we get the basic support in, we can then start tackling glibc.  It may be
> > when we get to doing the work in glibc itself, we will need to make further
> > modifications.  However, in order for the glibc people to start, I need the
> > basic support in the compiler in the tree.
> 
> It's not obvious what glibc support should look like in the absence of a 
> change to the default for long double; that would require discussion on 
> libc-alpha at an early stage to establish a consensus on the design.
> 
> libquadmath support should be easy (given working compiler / libgcc 
> support).  But if you want more than libquadmath support, there are 
> several possible forms for support in glibc proper depending on e.g. 
> whether you want to support a -m option to change long double, or using 
> the functions via the __float128 type name and separate names for the 
> functions, or both.

There already is an option to change long double, but it currently does not
work (and in fact is disabled in 64-bit environments).

I see there are many roadblocks to changing the type of long double
(i.e. making sure printf %Lg works correctly, etc.).  None of the distros want
another multilib (where long double is IEEE 128-bit).  For the scope of GCC
6.0, my assumption is long double will remain IBM extended double.

My assumption of the steps are:

1) Get the basic compiler support in.

2) Add the basic soft-float, either with my current hack or preferrably doing
   it right in glibc (I suspect we may want to temporarily do it via the hack,
   and when the glibc support is in, remove the hack).

3) Deal with all of the complexities of libgcc2 and glibc for the additional
   type.

4) Add float128 versions of the basic math libraries.  For this it will
   probably be simpler if we can force long double to be IEEE 128-bit so you
   don't have to change as much code, but you want to suppress whatever check
   there will be to prevent user code from linking against the wrong library.

5) Add support in other libraries as needed (IBM's MASS library, the new vector
   library, libquadmath, etc.).

Note, by the time of GCC 7.0, the C17/C++-17 standards may be final, and there
they have new names for IEEE 128-bit, etc.
Joseph Myers June 2, 2015, 9:09 p.m. UTC | #9
On Tue, 2 Jun 2015, Michael Meissner wrote:

> 4) Add float128 versions of the basic math libraries.  For this it will
>    probably be simpler if we can force long double to be IEEE 128-bit so you
>    don't have to change as much code, but you want to suppress whatever check
>    there will be to prevent user code from linking against the wrong library.

I'd say it's simpler if you don't force long double to be IEEE 128-bit 
(because then one answer is simply libquadmath, which already exists, to 
provide versions of libm functions for __float128, while making long 
double IEEE 128-bit affects a huge number of printf variant functions; 
libquadmath is a few years out of date with respect to glibc, but updating 
it shouldn't be hard).  Building libm twice with different options seems 
much nastier.

> Note, by the time of GCC 7.0, the C17/C++-17 standards may be final, and there
> they have new names for IEEE 128-bit, etc.

Since there is no project for a new major revision of the C standard (no 
work ongoing, no NWIP, etc.) I'm skeptical of any reference to "C17".  And 
the last suggestion I saw referring to integration of the IEEE 754-2008 
bindings into the C standard only suggested putting parts 1 and 2 in there 
(and even that involved some misconception about the extent to which those 
have been implemented).  The relevant part for this is part 3, defining 
the _Float128 type name, functions such as sinf128, etc.

Now, I think it would make sense eventually to support TS 18661 (any or 
all parts) in glibc, including providing the *f128 functions and so 
superseding libquadmath.  That is, I think it would be appropriate to 
revisit the rejection of such support in 
<https://sourceware.org/ml/libc-alpha/2004-03/msg00326.html> and 
<https://sourceware.org/ml/libc-alpha/2004-05/msg00055.html> now 
appropriate standard bindings exist (but this is only my view, not a 
community consensus).  But making the functions support building both for 
long double and for _Float128 would certainly be a large project.

Support in accordance with TS 18661-3 would *not* involve any printf 
changes, since the TS 18661 approach is to use the strfrom* functions (new 
in part 1) for that purpose rather than e.g. adding new printf formats.
diff mbox

Patch

Index: gcc/config/rs6000/rs6000-modes.def
===================================================================
--- gcc/config/rs6000/rs6000-modes.def	(revision 223458)
+++ gcc/config/rs6000/rs6000-modes.def	(working copy)
@@ -18,6 +18,13 @@ 
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
+/* IBM 128-bit floating point.  IFmode and KFmode use the fractional float
+   support in order to declare 3 128-bit floating point types.  */
+FRACTIONAL_FLOAT_MODE (IF, 106, 16, ibm_extended_format);
+
+/* Explicit IEEE 128-bit floating point.  */
+FRACTIONAL_FLOAT_MODE (KF, 113, 16, ieee_quad_format);
+
 /* 128-bit floating point.  ABI_V4 uses IEEE quad, AIX/Darwin
    adjust this in rs6000_option_override_internal.  */
 FLOAT_MODE (TF, 16, ieee_quad_format);
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 223458)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -600,3 +600,19 @@  Allow float/double variables in upper re
 moptimize-swaps
 Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save
 Analyze and remove doubleword swaps from VSX computations.
+
+mfloat128-
+Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save
+-mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used.
+
+Enum
+Name(float128_type_t) Type(enum float128_type_t)
+
+EnumValue
+Enum(float128_type_t) String(none) Value(FLOAT128_NONE)
+
+EnumValue
+Enum(float128_type_t) String(software) Value(FLOAT128_SW)
+
+EnumValue
+Enum(float128_type_t) String(sw) Value(FLOAT128_SW)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 223458)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1817,6 +1817,16 @@  rs6000_hard_regno_mode_ok (int regno, ma
 	    && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO)
 	    && ((regno & 1) == 0));
 
+  /* If we don't allow 128-bit binary floating point, disallow the 128-bit
+     types from going in any registers.  Similarly if __float128 is not
+     supported, don't allow __float128/__ibm128 types.  */
+  if (!TARGET_LONG_DOUBLE_128
+      && (mode == TFmode || mode == KFmode || mode == IFmode))
+    return false;
+
+  if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+    return false;
+
   /* VSX registers that overlap the FPR registers are larger than for non-VSX
      implementations.  Don't allow an item to be split between a FP register
      and an Altivec register.  Allow TImode in all VSX registers if the user
@@ -2086,6 +2096,7 @@  rs6000_debug_reg_global (void)
   const char *trace_str;
   const char *abi_str;
   const char *cmodel_str;
+  const char *float128_str;
   struct cl_target_option cl_opts;
 
   /* Modes we want tieable information on.  */
@@ -2099,6 +2110,8 @@  rs6000_debug_reg_global (void)
     SFmode,
     DFmode,
     TFmode,
+    IFmode,
+    KFmode,
     SDmode,
     DDmode,
     TDmode,
@@ -2445,6 +2458,15 @@  rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_S, "e500_double",
 	   (TARGET_E500_DOUBLE ? "true" : "false"));
 
+  switch (TARGET_FLOAT128)
+    {
+    case FLOAT128_NONE:	float128_str = "none";		break;
+    case FLOAT128_SW:	float128_str = "software";	break;
+    default:		float128_str = "unknown";	break;
+    }
+
+  fprintf (stderr, DEBUG_FMT_S, "float128", float128_str);
+
   if (TARGET_LINK_STACK)
     fprintf (stderr, DEBUG_FMT_S, "link_stack", "true");
 
@@ -3703,6 +3725,13 @@  rs6000_option_override_internal (bool gl
       && optimize >= 3)
     rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN;
 
+  /* Set the appropriate IEEE 128-bit floating option.  Do not enable float128
+     support by default until the libgcc support is added.  */
+  if (TARGET_FLOAT128 == FLOAT128_UNSET)
+    TARGET_FLOAT128 = FLOAT128_NONE;
+  else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX)
+    error ("-mfloat128-software requires VSX support");
+
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
     rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags);
 
@@ -14320,6 +14349,8 @@  rs6000_init_builtins (void)
   tree tdecl;
   tree ftype;
   machine_mode mode;
+  machine_mode ieee128_mode;
+  machine_mode ibm128_mode;
 
   if (TARGET_DEBUG_BUILTIN)
     fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n",
@@ -14387,6 +14418,32 @@  rs6000_init_builtins (void)
   dfloat128_type_internal_node = dfloat128_type_node;
   void_type_internal_node = void_type_node;
 
+  /* 128-bit floating point support.  KFmode is IEEE 128-bit floating point.
+     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_IEEEQUAD)
+    {
+      ieee128_mode = TFmode;
+      ibm128_mode = IFmode;
+    }
+  else
+    {
+      ieee128_mode = KFmode;
+      ibm128_mode = TFmode;
+    }
+
+  ieee128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ieee128_float_type_node) = 128;
+  layout_type (ieee128_float_type_node);
+  SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode);
+
+  ibm128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ibm128_float_type_node) = 128;
+  layout_type (ibm128_float_type_node);
+  SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode);
+
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
   builtin_mode_to_type[QImode][0] = integer_type_node;
@@ -14399,6 +14456,8 @@  rs6000_init_builtins (void)
   builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node;
   builtin_mode_to_type[SFmode][0] = float_type_node;
   builtin_mode_to_type[DFmode][0] = double_type_node;
+  builtin_mode_to_type[IFmode][0] = ibm128_float_type_node;
+  builtin_mode_to_type[KFmode][0] = ieee128_float_type_node;
   builtin_mode_to_type[TFmode][0] = long_double_type_node;
   builtin_mode_to_type[DDmode][0] = dfloat64_type_node;
   builtin_mode_to_type[TDmode][0] = dfloat128_type_node;
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 223458)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -2715,6 +2715,8 @@  enum rs6000_builtin_type_index
   RS6000_BTI_dfloat64,		 /* dfloat64_type_node */
   RS6000_BTI_dfloat128,		 /* dfloat128_type_node */
   RS6000_BTI_void,	         /* void_type_node */
+  RS6000_BTI_ieee128_float,	 /* ieee 128-bit floating point */
+  RS6000_BTI_ibm128_float,	 /* IBM 128-bit floating point */
   RS6000_BTI_MAX
 };
 
@@ -2769,6 +2771,8 @@  enum rs6000_builtin_type_index
 #define dfloat64_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_dfloat64])
 #define dfloat128_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_dfloat128])
 #define void_type_internal_node		 (rs6000_builtin_types[RS6000_BTI_void])
+#define ieee128_float_type_node		 (rs6000_builtin_types[RS6000_BTI_ieee128_float])
+#define ibm128_float_type_node		 (rs6000_builtin_types[RS6000_BTI_ibm128_float])
 
 extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
 extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
Index: gcc/config/rs6000/rs6000-opts.h
===================================================================
--- gcc/config/rs6000/rs6000-opts.h	(revision 223458)
+++ gcc/config/rs6000/rs6000-opts.h	(working copy)
@@ -79,6 +79,15 @@  enum fpu_type_t
   FPU_DF_FULL			/* Full Double Single Precision FPU */
 };
 
+
+/* Float128 support.  */
+enum float128_type_t
+{
+  FLOAT128_UNSET	= -1,	/* Initial value.  */
+  FLOAT128_NONE,		/* No __float128 support.  */
+  FLOAT128_SW			/* software __float128 support.  */
+};
+
 /* Types of costly dependences.  */
 enum rs6000_dependence_cost
 {