public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
@ 2015-05-22 21:47 Michael Meissner
  2015-06-02 17:51 ` David Edelsohn
  2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers
  0 siblings, 2 replies; 13+ messages in thread
From: Michael Meissner @ 2015-05-22 21:47 UTC (permalink / raw)
  To: gcc-patches, dje.gcc

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

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.

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

[-- Attachment #2: ieee128-patch01b --]
[-- Type: text/plain, Size: 7913 bytes --]

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
 {

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-05-22 21:47 [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Michael Meissner
@ 2015-06-02 17:51 ` David Edelsohn
  2015-06-02 18:33   ` Michael Meissner
  2015-06-16 22:33   ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner
  2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers
  1 sibling, 2 replies; 13+ messages in thread
From: David Edelsohn @ 2015-06-02 17:51 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

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

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-05-22 21:47 [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Michael Meissner
  2015-06-02 17:51 ` David Edelsohn
@ 2015-06-02 17:57 ` Joseph Myers
  2015-06-02 18:40   ` Michael Meissner
  1 sibling, 1 reply; 13+ messages in thread
From: Joseph Myers @ 2015-06-02 17:57 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

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.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 17:51 ` David Edelsohn
@ 2015-06-02 18:33   ` Michael Meissner
  2015-06-02 19:32     ` David Edelsohn
  2015-06-16 22:33   ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner
  1 sibling, 1 reply; 13+ messages in thread
From: Michael Meissner @ 2015-06-02 18:33 UTC (permalink / raw)
  To: David Edelsohn; +Cc: Michael Meissner, GCC Patches

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, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers
@ 2015-06-02 18:40   ` Michael Meissner
  2015-06-02 20:25     ` Joseph Myers
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Meissner @ 2015-06-02 18:40 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc

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.

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

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 18:33   ` Michael Meissner
@ 2015-06-02 19:32     ` David Edelsohn
  0 siblings, 0 replies; 13+ messages in thread
From: David Edelsohn @ 2015-06-02 19:32 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

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

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 18:40   ` Michael Meissner
@ 2015-06-02 20:25     ` Joseph Myers
  2015-06-02 20:50       ` David Edelsohn
  2015-06-02 20:56       ` Michael Meissner
  0 siblings, 2 replies; 13+ messages in thread
From: Joseph Myers @ 2015-06-02 20:25 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 20:25     ` Joseph Myers
@ 2015-06-02 20:50       ` David Edelsohn
  2015-06-02 20:56       ` Michael Meissner
  1 sibling, 0 replies; 13+ messages in thread
From: David Edelsohn @ 2015-06-02 20:50 UTC (permalink / raw)
  To: Joseph Myers, munroesj; +Cc: Michael Meissner, GCC Patches

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

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 20:25     ` Joseph Myers
  2015-06-02 20:50       ` David Edelsohn
@ 2015-06-02 20:56       ` Michael Meissner
  2015-06-02 21:18         ` Joseph Myers
  1 sibling, 1 reply; 13+ messages in thread
From: Michael Meissner @ 2015-06-02 20:56 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Michael Meissner, gcc-patches, dje.gcc

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.

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

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1
  2015-06-02 20:56       ` Michael Meissner
@ 2015-06-02 21:18         ` Joseph Myers
  0 siblings, 0 replies; 13+ messages in thread
From: Joseph Myers @ 2015-06-02 21:18 UTC (permalink / raw)
  To: Michael Meissner; +Cc: gcc-patches, dje.gcc

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2
  2015-06-02 17:51 ` David Edelsohn
  2015-06-02 18:33   ` Michael Meissner
@ 2015-06-16 22:33   ` Michael Meissner
  2015-07-09  0:02     ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b Michael Meissner
  1 sibling, 1 reply; 13+ messages in thread
From: Michael Meissner @ 2015-06-16 22:33 UTC (permalink / raw)
  To: David Edelsohn, GCC Patches

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

This is the second of my IEEE 128-bit floating point support.  This patch adds
new helper macros to the infrastructure, and changes the code in rs6000.c where
we are supporting floating point to deal with IEEE 128-bit floating point when
the rest of the patches are installed.

I have tested these patches on a big endian power7 and a little endian power8
with no regressions.  Are these patches ok to install in the trunk?

2015-06-16  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000-protos.h (rs6000_secondary_reload_memory):
	Use machine mode, not enum machine_mode in the prototype.

	* config/rs6000/rs6000.h (FLOAT128_IEEE_P): New helper macros to
	classify 128-bit floating point support.
	(FLOAT128_IBM_P): Likewise.
	(FLOAT128_VECTOR_P): Likewise.
	(FLOAT128_2REG_P): Likewise.
	(SCALAR_FLOAT_MODE_NOT_VECTOR_P): Likewise.
	(SLOW_UNALIGNED_ACCESS): Add IEEE 128-bit floating point support.
	(HARD_REGNO_CALLER_SAVE_MODE): Likewise.
	(HARD_REGNO_CALL_PART_CLOBBERED): Likewise.

	* config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Drop
	tests against TFmode/TDmode, since those modes do not use VSX
	addresses.
	(rs6000_hard_regno_mode_ok): Add IEEE 128-bit floating point
	support.
	(rs6000_init_hard_regno_mode_ok): Use new helper macros instead of
	tests against TFmode, etc.
	(invalid_e500_subreg): Add tests against IFmode/KFmode.
	(reg_offset_addressing_ok_p): Likewise.
	(rs6000_legitimate_offset_address_p): Likewise.
	(rs6000_legitimize_address): Likewise.
	(rs6000_legitimize_reload_address): Likewise.
	(rs6000_legitimate_address_p): Clean up tests against TFmode and
	TDmode to use the new helper macros, which will include IFmode and
	KFmode.
	(rs6000_emit_move): Likewise.
	(rs6000_darwin64_record_arg_recurse): Likewise.
	(print_operand): Likewise.
	(rs6000_member_type_forces_blk): Treat IEEE 128-bit floating point
	that uses a single vector register as a vector and not as a
	floating point register in terms of the calling sequence.
	(rs6000_discover_homogeneous_aggregate): Likewise.
	(rs6000_return_in_memory): Likewise.
	(init_cumulative_args): Likewise.
	(rs6000_function_arg_boundary): Likewise.
	(rs6000_function_arg_advance_1): Likewise.
	(rs6000_function_arg): Likewise.
	(rs6000_pass_by_reference): Likewise.
	(rs6000_gimplify_va_arg): Likewise.
	(rs6000_secondary_reload_memory): Use machine_mode not enum
	machine mode.
	(rs6000_split_multireg_move): Use new helper macros.
	(spe_func_has_64bit_regs_p): Likewise.
	(rs6000_output_function_epilogue): Add IFmode/KFmode support.
	(output_toc): Use new helper macros.
	(rs6000_register_move_cost): Likewise.
	(rs6000_function_value): Add IEEE 128-bit floating point calling
	sequence support.
	(rs6000_libcall_value): Likewise.
	(rs6000_scalar_mode_supported_p): Add support for IEEE 128-bit
	floating point support.
	(rs6000_vector_mode_supported_p): Likewise.

Note, I will be on vacation starting on Friday evening, and I will return on
July 1st.  If the patch approval comes after Thursday, I will hold these
patches until I return and retest them.

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

[-- Attachment #2: ieee128-patch02b --]
[-- Type: text/plain, Size: 21492 bytes --]

Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 224486)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -133,8 +133,7 @@ extern void rs6000_split_multireg_move (
 extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
 extern rtx rs6000_secondary_memory_needed_rtx (machine_mode);
-extern machine_mode rs6000_secondary_memory_needed_mode (enum
-							      machine_mode);
+extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
 extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
 						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 224486)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -402,6 +402,33 @@ extern const char *host_detect_local_cpu
 #define TARGET_DEBUG_TARGET	(rs6000_debug & MASK_DEBUG_TARGET)
 #define TARGET_DEBUG_BUILTIN	(rs6000_debug & MASK_DEBUG_BUILTIN)
 
+/* Helper macros for TFmode.  Quad floating point (TFmode) can be either IBM
+   long double format that uses a pair of doubles, or IEEE 128-bit floating
+   point.  KFmode was added as a way to represent IEEE 128-bit floating point,
+   even if the default for long double is the IBM long double format.
+   Similarly IFmode is the IBM long double format even if the default is IEEE
+   128-bit.  */
+#define FLOAT128_IEEE_P(MODE)						\
+  (((MODE) == KFmode)							\
+   || (((MODE) == TFmode) && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128))
+
+#define FLOAT128_IBM_P(MODE)						\
+  ((((MODE) == TFmode) && !TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)	\
+   || ((MODE) == IFmode))
+
+/* Helper macros to say whether a 128-bit floating point type can go in a
+   single vector register, or whether it needs paired scalar values.  */
+#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE))
+
+#define FLOAT128_2REG_P(MODE)						\
+  (FLOAT128_IBM_P (MODE)						\
+   || ((MODE) == TDmode)						\
+   || (!TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE)))
+
+/* Return true for floating point that does not use a vector register.  */
+#define SCALAR_FLOAT_MODE_NOT_VECTOR_P(MODE)				\
+  (SCALAR_FLOAT_MODE_P (MODE) && !FLOAT128_VECTOR_P (MODE))
+
 /* Describe the vector unit used for arithmetic operations.  */
 extern enum rs6000_vector rs6000_vector_unit[];
 
@@ -888,11 +915,10 @@ enum data_align { align_abi, align_opt, 
    aligned to 4 or 8 bytes.  */
 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN)				\
   (STRICT_ALIGNMENT							\
-   || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode	\
-	|| (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)	\
-       && (ALIGN) < 32)							\
+   || (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) && (ALIGN) < 32)		\
    || (!TARGET_EFFICIENT_UNALIGNED_VSX                                  \
-       && (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))))
+       && ((VECTOR_MODE_P (MODE) || FLOAT128_VECTOR_P (MODE))		\
+	   && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))))
 
 \f
 /* Standard register usage.  */
@@ -1174,7 +1200,7 @@ enum data_align { align_abi, align_opt, 
    ? V2DFmode								\
    : TARGET_E500_DOUBLE && ((MODE) == VOIDmode || (MODE) == DFmode)	\
    ? DFmode								\
-   : !TARGET_E500_DOUBLE && (MODE) == TFmode && FP_REGNO_P (REGNO)	\
+   : !TARGET_E500_DOUBLE && FLOAT128_IBM_P (MODE) && FP_REGNO_P (REGNO)	\
    ? DFmode								\
    : !TARGET_E500_DOUBLE && (MODE) == TDmode && FP_REGNO_P (REGNO)	\
    ? DImode								\
@@ -1185,8 +1211,7 @@ enum data_align { align_abi, align_opt, 
      && (GET_MODE_SIZE (MODE) > 4)					\
      && INT_REGNO_P (REGNO)) ? 1 : 0)					\
    || (TARGET_VSX && FP_REGNO_P (REGNO)					\
-       && GET_MODE_SIZE (MODE) > 8 && ((MODE) != TDmode) 		\
-       && ((MODE) != TFmode)))
+       && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE)))
 
 #define VSX_VECTOR_MODE(MODE)		\
 	 ((MODE) == V4SFmode		\
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 224486)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1750,9 +1750,11 @@ rs6000_hard_regno_nregs_internal (int re
 {
   unsigned HOST_WIDE_INT reg_size;
 
-  /* TF/TD modes are special in that they always take 2 registers.  */
+  /* 128-bit floating point usually takes 2 registers, unless it is IEEE
+     128-bit floating point that can go in vector registers, which has VSX
+     memory addressing.  */
   if (FP_REGNO_P (regno))
-    reg_size = ((VECTOR_MEM_VSX_P (mode) && mode != TDmode && mode != TFmode)
+    reg_size = (VECTOR_MEM_VSX_P (mode)
 		? UNITS_PER_VSX_WORD
 		: UNITS_PER_FP_WORD);
 
@@ -1809,6 +1811,7 @@ rs6000_hard_regno_mode_ok (int regno, ma
      asked for it.  */
   if (TARGET_VSX && VSX_REGNO_P (regno)
       && (VECTOR_MEM_VSX_P (mode)
+	  || FLOAT128_VECTOR_P (mode)
 	  || reg_addr[mode].scalar_in_vmx_p
 	  || (TARGET_VSX_TIMODE && mode == TImode)
 	  || (TARGET_VADDUQM && mode == V1TImode)))
@@ -1834,6 +1837,9 @@ rs6000_hard_regno_mode_ok (int regno, ma
      modes and DImode.  */
   if (FP_REGNO_P (regno))
     {
+      if (FLOAT128_VECTOR_P (mode))
+	return false;
+
       if (SCALAR_FLOAT_MODE_P (mode)
 	  && (mode != TDmode || (regno % 2) == 0)
 	  && FP_REGNO_P (last_regno))
@@ -3009,9 +3015,9 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  machine_mode m2 = (machine_mode)m;
 	  int reg_size2 = reg_size;
 
-	  /* TFmode/TDmode always takes 2 registers, even in VSX.  */
-	  if (TARGET_VSX && VSX_REG_CLASS_P (c)
-	      && (m == TDmode || m == TFmode))
+	  /* TDmode & IBM 128-bit floating point always takes 2 registers, even
+	     in VSX.  */
+	  if (TARGET_VSX && VSX_REG_CLASS_P (c) && FLOAT128_2REG_P (m))
 	    reg_size2 = UNITS_PER_FP_WORD;
 
 	  rs6000_class_max_nregs[m][c]
@@ -6116,13 +6122,16 @@ invalid_e500_subreg (rtx op, machine_mod
 	      || mode == DDmode || mode == TDmode || mode == PTImode)
 	  && REG_P (SUBREG_REG (op))
 	  && (GET_MODE (SUBREG_REG (op)) == DFmode
-	      || GET_MODE (SUBREG_REG (op)) == TFmode))
+	      || GET_MODE (SUBREG_REG (op)) == TFmode
+	      || GET_MODE (SUBREG_REG (op)) == IFmode
+	      || GET_MODE (SUBREG_REG (op)) == KFmode))
 	return true;
 
       /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and
 	 reg:TI.  */
       if (GET_CODE (op) == SUBREG
-	  && (mode == DFmode || mode == TFmode)
+	  && (mode == DFmode || mode == TFmode || mode == IFmode
+	      || mode == KFmode)
 	  && REG_P (SUBREG_REG (op))
 	  && (GET_MODE (SUBREG_REG (op)) == DImode
 	      || GET_MODE (SUBREG_REG (op)) == TImode
@@ -6484,10 +6493,13 @@ reg_offset_addressing_ok_p (machine_mode
     case V2DImode:
     case V1TImode:
     case TImode:
+    case TFmode:
+    case KFmode:
       /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid.  While
 	 TImode is not a vector mode, if we want to use the VSX registers to
-	 move it around, we need to restrict ourselves to reg+reg
-	 addressing.  */
+	 move it around, we need to restrict ourselves to reg+reg addressing.
+	 Similarly for IEEE 128-bit floating point that is passed in a single
+	 vector register.  */
       if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
 	return false;
       break;
@@ -6753,6 +6765,8 @@ rs6000_legitimate_offset_address_p (mach
       break;
 
     case TFmode:
+    case IFmode:
+    case KFmode:
       if (TARGET_E500_DOUBLE)
 	return (SPE_CONST_OFFSET_OK (offset)
 		&& SPE_CONST_OFFSET_OK (offset + 8));
@@ -6946,6 +6960,8 @@ rs6000_legitimize_address (rtx x, rtx ol
     case TDmode:
     case TImode:
     case PTImode:
+    case IFmode:
+    case KFmode:
       /* As in legitimate_offset_address_p we do not assume
 	 worst-case.  The mode here is just a hint as to the registers
 	 used.  A TImode is usually in gprs, but may actually be in
@@ -7718,6 +7734,8 @@ rs6000_legitimize_reload_address (rtx x,
       && !reg_addr[mode].scalar_in_vmx_p
       && mode != TFmode
       && mode != TDmode
+      && mode != IFmode
+      && mode != KFmode
       && (mode != TImode || !TARGET_VSX_TIMODE)
       && mode != PTImode
       && (mode != DImode || TARGET_POWERPC64)
@@ -7871,8 +7889,7 @@ rs6000_legitimate_address_p (machine_mod
     return 1;
   if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict, false))
     return 1;
-  if (mode != TFmode
-      && mode != TDmode
+  if (!FLOAT128_2REG_P (mode)
       && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
 	  || TARGET_POWERPC64
 	  || (mode != DFmode && mode != DDmode)
@@ -8540,9 +8557,8 @@ rs6000_emit_move (rtx dest, rtx source, 
   /* 128-bit constant floating-point values on Darwin should really be loaded
      as two parts.  However, this premature splitting is a problem when DFmode
      values can go into Altivec registers.  */
-  if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
-      && !reg_addr[DFmode].scalar_in_vmx_p
-      && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
+  if (FLOAT128_IBM_P (mode) && !reg_addr[DFmode].scalar_in_vmx_p
+      && GET_CODE (operands[1]) == CONST_DOUBLE)
     {
       rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, 0),
 			simplify_gen_subreg (DFmode, operands[1], mode, 0),
@@ -8734,7 +8750,10 @@ rs6000_emit_move (rtx dest, rtx source, 
 
     case TFmode:
     case TDmode:
-      rs6000_eliminate_indexed_memrefs (operands);
+    case IFmode:
+    case KFmode:
+      if (FLOAT128_2REG_P (mode))
+	rs6000_eliminate_indexed_memrefs (operands);
       /* fall through */
 
     case DFmode:
@@ -8958,7 +8977,7 @@ rs6000_member_type_forces_blk (const_tre
 \f
 /* Nonzero if we can use a floating-point register to pass this arg.  */
 #define USE_FP_FOR_ARG_P(CUM,MODE)		\
-  (SCALAR_FLOAT_MODE_P (MODE)			\
+  (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE)		\
    && (CUM)->fregno <= FP_ARG_MAX_REG		\
    && TARGET_HARD_FLOAT && TARGET_FPRS)
 
@@ -9159,7 +9178,7 @@ rs6000_discover_homogeneous_aggregate (m
 
       if (field_count > 0)
 	{
-	  int n_regs = (SCALAR_FLOAT_MODE_P (field_mode)?
+	  int n_regs = (SCALAR_FLOAT_MODE_P (field_mode) ?
 			(GET_MODE_SIZE (field_mode) + 7) >> 3 : 1);
 
 	  /* The ELFv2 ABI allows homogeneous aggregates to occupy
@@ -9269,7 +9288,8 @@ rs6000_return_in_memory (const_tree type
       return true;
     }
 
-  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && TYPE_MODE (type) == TFmode)
+  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
+      && FLOAT128_IEEE_P (TYPE_MODE (type)))
     return true;
 
   return false;
@@ -9399,7 +9419,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      <= 8))
 		rs6000_returns_struct = true;
 	    }
-	  if (SCALAR_FLOAT_MODE_P (return_mode))
+	  if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (return_mode))
 	    rs6000_passes_float = true;
 	  else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
 		   || SPE_VECTOR_MODE (return_mode))
@@ -9537,8 +9557,10 @@ rs6000_function_arg_boundary (machine_mo
       && (GET_MODE_SIZE (mode) == 8
 	  || (TARGET_HARD_FLOAT
 	      && TARGET_FPRS
-	      && (mode == TFmode || mode == TDmode))))
+	      && FLOAT128_2REG_P (mode))))
     return 64;
+  else if (FLOAT128_VECTOR_P (mode))
+    return 128;
   else if (SPE_VECTOR_MODE (mode)
 	   || (type && TREE_CODE (type) == VECTOR_TYPE
 	       && int_size_in_bytes (type) >= 8
@@ -9810,7 +9832,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
   if (DEFAULT_ABI == ABI_V4
       && cum->escapes)
     {
-      if (SCALAR_FLOAT_MODE_P (mode))
+      if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode))
 	rs6000_passes_float = true;
       else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
 	rs6000_passes_vector = true;
@@ -9917,21 +9939,21 @@ rs6000_function_arg_advance_1 (CUMULATIV
       if (TARGET_HARD_FLOAT && TARGET_FPRS
 	  && ((TARGET_SINGLE_FLOAT && mode == SFmode)
 	      || (TARGET_DOUBLE_FLOAT && mode == DFmode)
-	      || (mode == TFmode && !TARGET_IEEEQUAD)
-	      || mode == SDmode || mode == DDmode || mode == TDmode))
+	      || FLOAT128_2REG_P (mode)
+	      || DECIMAL_FLOAT_MODE_P (mode)))
 	{
 	  /* _Decimal128 must use an even/odd register pair.  This assumes
 	     that the register number is odd when fregno is odd.  */
 	  if (mode == TDmode && (cum->fregno % 2) == 1)
 	    cum->fregno++;
 
-	  if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0)
+	  if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0)
 	      <= FP_ARG_V4_MAX_REG)
 	    cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
 	  else
 	    {
 	      cum->fregno = FP_ARG_V4_MAX_REG + 1;
-	      if (mode == DFmode || mode == TFmode
+	      if (mode == DFmode || FLOAT128_IBM_P (mode)
 		  || mode == DDmode || mode == TDmode)
 		cum->words += cum->words & 1;
 	      cum->words += rs6000_arg_size (mode, type);
@@ -9983,8 +10005,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
 
       cum->words = align_words + n_words;
 
-      if (SCALAR_FLOAT_MODE_P (elt_mode)
-	  && TARGET_HARD_FLOAT && TARGET_FPRS)
+      if (SCALAR_FLOAT_MODE_P (elt_mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
 	{
 	  /* _Decimal128 must be passed in an even/odd float register pair.
 	     This assumes that the register number is odd when fregno is
@@ -10226,7 +10247,7 @@ rs6000_darwin64_record_arg_recurse (CUMU
 	      = gen_rtx_EXPR_LIST (VOIDmode,
 				   gen_rtx_REG (mode, cum->fregno++),
 				   GEN_INT (bitpos / BITS_PER_UNIT));
-	    if (mode == TFmode || mode == TDmode)
+	    if (FLOAT128_2REG_P (mode))
 	      cum->fregno++;
 	  }
 	else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1))
@@ -10577,15 +10598,15 @@ rs6000_function_arg (cumulative_args_t c
       if (TARGET_HARD_FLOAT && TARGET_FPRS
 	  && ((TARGET_SINGLE_FLOAT && mode == SFmode)
 	      || (TARGET_DOUBLE_FLOAT && mode == DFmode)
-	      || (mode == TFmode && !TARGET_IEEEQUAD)
-	      || mode == SDmode || mode == DDmode || mode == TDmode))
+	      || FLOAT128_2REG_P (mode)
+	      || DECIMAL_FLOAT_MODE_P (mode)))
 	{
 	  /* _Decimal128 must use an even/odd register pair.  This assumes
 	     that the register number is odd when fregno is odd.  */
 	  if (mode == TDmode && (cum->fregno % 2) == 1)
 	    cum->fregno++;
 
-	  if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0)
+	  if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0)
 	      <= FP_ARG_V4_MAX_REG)
 	    return gen_rtx_REG (mode, cum->fregno);
 	  else
@@ -10647,7 +10668,7 @@ rs6000_function_arg (cumulative_args_t c
 	      machine_mode fmode = elt_mode;
 	      if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1)
 		{
-		  gcc_assert (fmode == TFmode || fmode == TDmode);
+		  gcc_assert (FLOAT128_2REG_P (fmode));
 		  fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode;
 		}
 
@@ -10821,10 +10842,11 @@ rs6000_pass_by_reference (cumulative_arg
 			  machine_mode mode, const_tree type,
 			  bool named ATTRIBUTE_UNUSED)
 {
-  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode)
+  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
+      && FLOAT128_IEEE_P (TYPE_MODE (type)))
     {
       if (TARGET_DEBUG_ARG)
-	fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
+	fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n");
       return 1;
     }
 
@@ -11499,10 +11521,8 @@ rs6000_gimplify_va_arg (tree valist, tre
       && ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode)
           || (TARGET_DOUBLE_FLOAT 
               && (TYPE_MODE (type) == DFmode 
- 	          || TYPE_MODE (type) == TFmode
-	          || TYPE_MODE (type) == SDmode
-	          || TYPE_MODE (type) == DDmode
-	          || TYPE_MODE (type) == TDmode))))
+		  || FLOAT128_2REG_P (TYPE_MODE (type))
+		  || DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))))))
     {
       /* FP args go in FP registers, if present.  */
       reg = fpr;
@@ -16765,7 +16785,7 @@ rs6000_secondary_reload_toc_costs (addr_
 static int
 rs6000_secondary_reload_memory (rtx addr,
 				enum reg_class rclass,
-				enum machine_mode mode)
+				machine_mode mode)
 {
   int extra_cost = 0;
   rtx reg, and_arg, plus_arg0, plus_arg1;
@@ -19063,7 +19083,7 @@ print_operand (FILE *file, rtx x, int co
 	/* Ugly hack because %y is overloaded.  */
 	if ((TARGET_SPE || TARGET_E500_DOUBLE)
 	    && (GET_MODE_SIZE (GET_MODE (x)) == 8
-		|| GET_MODE (x) == TFmode
+		|| FLOAT128_2REG_P (GET_MODE (x))
 		|| GET_MODE (x) == TImode
 		|| GET_MODE (x) == PTImode))
 	  {
@@ -21013,7 +21033,7 @@ rs6000_split_multireg_move (rtx dst, rtx
 	((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? DFmode : SFmode);
   else if (ALTIVEC_REGNO_P (reg))
     reg_mode = V16QImode;
-  else if (TARGET_E500_DOUBLE && mode == TFmode)
+  else if (TARGET_E500_DOUBLE && FLOAT128_2REG_P (mode))
     reg_mode = DFmode;
   else
     reg_mode = word_mode;
@@ -22090,7 +22110,8 @@ spe_func_has_64bit_regs_p (void)
 
 	      if (SPE_VECTOR_MODE (mode))
 		return true;
-	      if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode))
+	      if (TARGET_E500_DOUBLE
+		  && (mode == DFmode || FLOAT128_2REG_P (mode)))
 		return true;
 	    }
 	}
@@ -25853,6 +25874,8 @@ rs6000_output_function_epilogue (FILE *f
 			case DDmode:
 			case TFmode:
 			case TDmode:
+			case IFmode:
+			case KFmode:
 			  bits = 0x3;
 			  break;
 
@@ -26526,7 +26549,8 @@ output_toc (FILE *file, rtx x, int label
      TOC, things we put here aren't actually in the TOC, so we can allow
      FP constants.  */
   if (GET_CODE (x) == CONST_DOUBLE &&
-      (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode))
+      (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode
+       || GET_MODE (x) == IFmode || GET_MODE (x) == KFmode))
     {
       REAL_VALUE_TYPE rv;
       long k[4];
@@ -31050,7 +31074,7 @@ rs6000_register_move_cost (machine_mode 
 
   /* Moving between two similar registers is just one instruction.  */
   else if (reg_classes_intersect_p (to, from))
-    ret = (mode == TFmode || mode == TDmode) ? 4 : 2;
+    ret = (FLOAT128_2REG_P (mode)) ? 4 : 2;
 
   /* Everything else has to go through GENERAL_REGS.  */
   else
@@ -32117,7 +32141,7 @@ rs6000_function_value (const_tree valtyp
     {
       int first_reg, n_regs;
 
-      if (SCALAR_FLOAT_MODE_P (elt_mode))
+      if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (elt_mode))
 	{
 	  /* _Decimal128 must use even/odd register pairs.  */
 	  first_reg = (elt_mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
@@ -32154,7 +32178,7 @@ rs6000_function_value (const_tree valtyp
   if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
     /* _Decimal128 must use an even/odd register pair.  */
     regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
-  else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS
+  else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS
 	   && ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT))
     regno = FP_ARG_RETURN;
   else if (TREE_CODE (valtype) == COMPLEX_TYPE
@@ -32163,13 +32187,13 @@ rs6000_function_value (const_tree valtyp
   /* VSX is a superset of Altivec and adds V2DImode/V2DFmode.  Since the same
      return register is used in both cases, and we won't see V2DImode/V2DFmode
      for pure altivec, combine the two cases.  */
-  else if (TREE_CODE (valtype) == VECTOR_TYPE
+  else if ((TREE_CODE (valtype) == VECTOR_TYPE || FLOAT128_VECTOR_P (mode))
 	   && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
 	   && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
     regno = ALTIVEC_ARG_RETURN;
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
 	   && (mode == DFmode || mode == DCmode
-	       || mode == TFmode || mode == TCmode))
+	       || FLOAT128_IBM_P (mode) || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -32191,7 +32215,7 @@ rs6000_libcall_value (machine_mode mode)
   if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
     /* _Decimal128 must use an even/odd register pair.  */
     regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
-  else if (SCALAR_FLOAT_MODE_P (mode)
+  else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode)
 	   && TARGET_HARD_FLOAT && TARGET_FPRS
            && ((TARGET_SINGLE_FLOAT && mode == SFmode) || TARGET_DOUBLE_FLOAT))
     regno = FP_ARG_RETURN;
@@ -32205,7 +32229,7 @@ rs6000_libcall_value (machine_mode mode)
     return rs6000_complex_function_value (mode);
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
 	   && (mode == DFmode || mode == DCmode
-	       || mode == TFmode || mode == TCmode))
+	       || FLOAT128_IBM_P (mode) || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -32431,6 +32455,8 @@ rs6000_scalar_mode_supported_p (machine_
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
+  else if (mode == KFmode)
+    return TARGET_FLOAT128;
   else
     return default_scalar_mode_supported_p (mode);
 }
@@ -32446,7 +32472,10 @@ rs6000_vector_mode_supported_p (machine_
   if (TARGET_SPE && SPE_VECTOR_MODE (mode))
     return true;
 
-  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+  /* There is no vector form for IEEE 128-bit.  If we return true for IEEE
+     128-bit, the compiler might try to widen IEEE 128-bit to IBM
+     double-double.  */
+  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) && !FLOAT128_IEEE_P (mode))
     return true;
 
   else

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b
  2015-06-16 22:33   ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner
@ 2015-07-09  0:02     ` Michael Meissner
  2015-07-09  0:21       ` David Edelsohn
  0 siblings, 1 reply; 13+ messages in thread
From: Michael Meissner @ 2015-07-09  0:02 UTC (permalink / raw)
  To: David Edelsohn, GCC Patches

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

David asked me to change the definition of FLOAT128_IBM_P and FLOAT128_IEEE_P
so that they were more consistant.  In doing so, I realized that I didn't need
to test TARGET_LONG_DOUBLE_128 in those macros, since the mode would never be
TFmode, IFmode, or KFmode unless TARGET_LONG_DOUBLE_128 was true.

He also asked for better verification that the existing calling sequence with
long double (which needs the subsequent patches to test), and I will write such
tests and test them, putting them in the final patches.

It bootstraps fine with no regressions.  Is this patch ok to install?

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

	* config/rs6000/rs6000-protos.h (rs6000_secondary_reload_memory):
	Use machine mode, not enum machine_mode in the prototype.

	* config/rs6000/rs6000.h (FLOAT128_IEEE_P): New helper macros to
	classify 128-bit floating point support.
	(FLOAT128_IBM_P): Likewise.
	(FLOAT128_VECTOR_P): Likewise.
	(FLOAT128_2REG_P): Likewise.
	(SCALAR_FLOAT_MODE_NOT_VECTOR_P): Likewise.
	(SLOW_UNALIGNED_ACCESS): Add IEEE 128-bit floating point support.
	(HARD_REGNO_CALLER_SAVE_MODE): Likewise.
	(HARD_REGNO_CALL_PART_CLOBBERED): Likewise.

	* config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Drop
	tests against TFmode/TDmode, since those modes do not use VSX
	addresses.
	(rs6000_hard_regno_mode_ok): Add IEEE 128-bit floating point
	support.
	(rs6000_init_hard_regno_mode_ok): Use new helper macros instead of
	tests against TFmode, etc.
	(invalid_e500_subreg): Add tests against IFmode/KFmode.
	(reg_offset_addressing_ok_p): Likewise.
	(rs6000_legitimate_offset_address_p): Likewise.
	(rs6000_legitimize_address): Likewise.
	(rs6000_legitimize_reload_address): Likewise.
	(rs6000_legitimate_address_p): Clean up tests against TFmode and
	TDmode to use the new helper macros, which will include IFmode and
	KFmode.
	(rs6000_emit_move): Likewise.
	(rs6000_darwin64_record_arg_recurse): Likewise.
	(print_operand): Likewise.
	(rs6000_member_type_forces_blk): Treat IEEE 128-bit floating point
	that uses a single vector register as a vector and not as a
	floating point register in terms of the calling sequence.
	(rs6000_discover_homogeneous_aggregate): Likewise.
	(rs6000_return_in_memory): Likewise.
	(init_cumulative_args): Likewise.
	(rs6000_function_arg_boundary): Likewise.
	(rs6000_function_arg_advance_1): Likewise.
	(rs6000_function_arg): Likewise.
	(rs6000_pass_by_reference): Likewise.
	(rs6000_gimplify_va_arg): Likewise.
	(rs6000_secondary_reload_memory): Use machine_mode not enum
	machine mode.
	(rs6000_split_multireg_move): Use new helper macros.
	(spe_func_has_64bit_regs_p): Likewise.
	(rs6000_output_function_epilogue): Add IFmode/KFmode support.
	(output_toc): Use new helper macros.
	(rs6000_register_move_cost): Likewise.
	(rs6000_function_value): Add IEEE 128-bit floating point calling
	sequence support.
	(rs6000_libcall_value): Likewise.
	(rs6000_scalar_mode_supported_p): Add support for IEEE 128-bit
	floating point support.
	(rs6000_vector_mode_supported_p): Likewise.

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

[-- Attachment #2: ieee128-patch02b --]
[-- Type: text/plain, Size: 21435 bytes --]

Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 225574)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -133,8 +133,7 @@ extern void rs6000_split_multireg_move (
 extern void rs6000_emit_le_vsx_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
 extern rtx rs6000_secondary_memory_needed_rtx (machine_mode);
-extern machine_mode rs6000_secondary_memory_needed_mode (enum
-							      machine_mode);
+extern machine_mode rs6000_secondary_memory_needed_mode (machine_mode);
 extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, machine_mode,
 						    int, int, int, int *);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 225574)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1740,9 +1740,11 @@ rs6000_hard_regno_nregs_internal (int re
 {
   unsigned HOST_WIDE_INT reg_size;
 
-  /* TF/TD modes are special in that they always take 2 registers.  */
+  /* 128-bit floating point usually takes 2 registers, unless it is IEEE
+     128-bit floating point that can go in vector registers, which has VSX
+     memory addressing.  */
   if (FP_REGNO_P (regno))
-    reg_size = ((VECTOR_MEM_VSX_P (mode) && mode != TDmode && mode != TFmode)
+    reg_size = (VECTOR_MEM_VSX_P (mode)
 		? UNITS_PER_VSX_WORD
 		: UNITS_PER_FP_WORD);
 
@@ -1799,6 +1801,7 @@ rs6000_hard_regno_mode_ok (int regno, ma
      asked for it.  */
   if (TARGET_VSX && VSX_REGNO_P (regno)
       && (VECTOR_MEM_VSX_P (mode)
+	  || FLOAT128_VECTOR_P (mode)
 	  || reg_addr[mode].scalar_in_vmx_p
 	  || (TARGET_VSX_TIMODE && mode == TImode)
 	  || (TARGET_VADDUQM && mode == V1TImode)))
@@ -1824,6 +1827,9 @@ rs6000_hard_regno_mode_ok (int regno, ma
      modes and DImode.  */
   if (FP_REGNO_P (regno))
     {
+      if (FLOAT128_VECTOR_P (mode))
+	return false;
+
       if (SCALAR_FLOAT_MODE_P (mode)
 	  && (mode != TDmode || (regno % 2) == 0)
 	  && FP_REGNO_P (last_regno))
@@ -2999,9 +3005,9 @@ rs6000_init_hard_regno_mode_ok (bool glo
 	  machine_mode m2 = (machine_mode)m;
 	  int reg_size2 = reg_size;
 
-	  /* TFmode/TDmode always takes 2 registers, even in VSX.  */
-	  if (TARGET_VSX && VSX_REG_CLASS_P (c)
-	      && (m == TDmode || m == TFmode))
+	  /* TDmode & IBM 128-bit floating point always takes 2 registers, even
+	     in VSX.  */
+	  if (TARGET_VSX && VSX_REG_CLASS_P (c) && FLOAT128_2REG_P (m))
 	    reg_size2 = UNITS_PER_FP_WORD;
 
 	  rs6000_class_max_nregs[m][c]
@@ -6106,13 +6112,16 @@ invalid_e500_subreg (rtx op, machine_mod
 	      || mode == DDmode || mode == TDmode || mode == PTImode)
 	  && REG_P (SUBREG_REG (op))
 	  && (GET_MODE (SUBREG_REG (op)) == DFmode
-	      || GET_MODE (SUBREG_REG (op)) == TFmode))
+	      || GET_MODE (SUBREG_REG (op)) == TFmode
+	      || GET_MODE (SUBREG_REG (op)) == IFmode
+	      || GET_MODE (SUBREG_REG (op)) == KFmode))
 	return true;
 
       /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and
 	 reg:TI.  */
       if (GET_CODE (op) == SUBREG
-	  && (mode == DFmode || mode == TFmode)
+	  && (mode == DFmode || mode == TFmode || mode == IFmode
+	      || mode == KFmode)
 	  && REG_P (SUBREG_REG (op))
 	  && (GET_MODE (SUBREG_REG (op)) == DImode
 	      || GET_MODE (SUBREG_REG (op)) == TImode
@@ -6474,10 +6483,13 @@ reg_offset_addressing_ok_p (machine_mode
     case V2DImode:
     case V1TImode:
     case TImode:
+    case TFmode:
+    case KFmode:
       /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid.  While
 	 TImode is not a vector mode, if we want to use the VSX registers to
-	 move it around, we need to restrict ourselves to reg+reg
-	 addressing.  */
+	 move it around, we need to restrict ourselves to reg+reg addressing.
+	 Similarly for IEEE 128-bit floating point that is passed in a single
+	 vector register.  */
       if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
 	return false;
       break;
@@ -6743,6 +6755,8 @@ rs6000_legitimate_offset_address_p (mach
       break;
 
     case TFmode:
+    case IFmode:
+    case KFmode:
       if (TARGET_E500_DOUBLE)
 	return (SPE_CONST_OFFSET_OK (offset)
 		&& SPE_CONST_OFFSET_OK (offset + 8));
@@ -6936,6 +6950,8 @@ rs6000_legitimize_address (rtx x, rtx ol
     case TDmode:
     case TImode:
     case PTImode:
+    case IFmode:
+    case KFmode:
       /* As in legitimate_offset_address_p we do not assume
 	 worst-case.  The mode here is just a hint as to the registers
 	 used.  A TImode is usually in gprs, but may actually be in
@@ -7708,6 +7724,8 @@ rs6000_legitimize_reload_address (rtx x,
       && !reg_addr[mode].scalar_in_vmx_p
       && mode != TFmode
       && mode != TDmode
+      && mode != IFmode
+      && mode != KFmode
       && (mode != TImode || !TARGET_VSX_TIMODE)
       && mode != PTImode
       && (mode != DImode || TARGET_POWERPC64)
@@ -7861,8 +7879,7 @@ rs6000_legitimate_address_p (machine_mod
     return 1;
   if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict, false))
     return 1;
-  if (mode != TFmode
-      && mode != TDmode
+  if (!FLOAT128_2REG_P (mode)
       && ((TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT)
 	  || TARGET_POWERPC64
 	  || (mode != DFmode && mode != DDmode)
@@ -8530,9 +8547,8 @@ rs6000_emit_move (rtx dest, rtx source, 
   /* 128-bit constant floating-point values on Darwin should really be loaded
      as two parts.  However, this premature splitting is a problem when DFmode
      values can go into Altivec registers.  */
-  if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
-      && !reg_addr[DFmode].scalar_in_vmx_p
-      && mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
+  if (FLOAT128_IBM_P (mode) && !reg_addr[DFmode].scalar_in_vmx_p
+      && GET_CODE (operands[1]) == CONST_DOUBLE)
     {
       rs6000_emit_move (simplify_gen_subreg (DFmode, operands[0], mode, 0),
 			simplify_gen_subreg (DFmode, operands[1], mode, 0),
@@ -8724,7 +8740,10 @@ rs6000_emit_move (rtx dest, rtx source, 
 
     case TFmode:
     case TDmode:
-      rs6000_eliminate_indexed_memrefs (operands);
+    case IFmode:
+    case KFmode:
+      if (FLOAT128_2REG_P (mode))
+	rs6000_eliminate_indexed_memrefs (operands);
       /* fall through */
 
     case DFmode:
@@ -8948,7 +8967,7 @@ rs6000_member_type_forces_blk (const_tre
 \f
 /* Nonzero if we can use a floating-point register to pass this arg.  */
 #define USE_FP_FOR_ARG_P(CUM,MODE)		\
-  (SCALAR_FLOAT_MODE_P (MODE)			\
+  (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE)		\
    && (CUM)->fregno <= FP_ARG_MAX_REG		\
    && TARGET_HARD_FLOAT && TARGET_FPRS)
 
@@ -9149,7 +9168,7 @@ rs6000_discover_homogeneous_aggregate (m
 
       if (field_count > 0)
 	{
-	  int n_regs = (SCALAR_FLOAT_MODE_P (field_mode)?
+	  int n_regs = (SCALAR_FLOAT_MODE_P (field_mode) ?
 			(GET_MODE_SIZE (field_mode) + 7) >> 3 : 1);
 
 	  /* The ELFv2 ABI allows homogeneous aggregates to occupy
@@ -9259,7 +9278,8 @@ rs6000_return_in_memory (const_tree type
       return true;
     }
 
-  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && TYPE_MODE (type) == TFmode)
+  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
+      && FLOAT128_IEEE_P (TYPE_MODE (type)))
     return true;
 
   return false;
@@ -9389,7 +9409,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      <= 8))
 		rs6000_returns_struct = true;
 	    }
-	  if (SCALAR_FLOAT_MODE_P (return_mode))
+	  if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (return_mode))
 	    rs6000_passes_float = true;
 	  else if (ALTIVEC_OR_VSX_VECTOR_MODE (return_mode)
 		   || SPE_VECTOR_MODE (return_mode))
@@ -9527,8 +9547,10 @@ rs6000_function_arg_boundary (machine_mo
       && (GET_MODE_SIZE (mode) == 8
 	  || (TARGET_HARD_FLOAT
 	      && TARGET_FPRS
-	      && (mode == TFmode || mode == TDmode))))
+	      && FLOAT128_2REG_P (mode))))
     return 64;
+  else if (FLOAT128_VECTOR_P (mode))
+    return 128;
   else if (SPE_VECTOR_MODE (mode)
 	   || (type && TREE_CODE (type) == VECTOR_TYPE
 	       && int_size_in_bytes (type) >= 8
@@ -9800,7 +9822,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
   if (DEFAULT_ABI == ABI_V4
       && cum->escapes)
     {
-      if (SCALAR_FLOAT_MODE_P (mode))
+      if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode))
 	rs6000_passes_float = true;
       else if (named && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
 	rs6000_passes_vector = true;
@@ -9907,21 +9929,21 @@ rs6000_function_arg_advance_1 (CUMULATIV
       if (TARGET_HARD_FLOAT && TARGET_FPRS
 	  && ((TARGET_SINGLE_FLOAT && mode == SFmode)
 	      || (TARGET_DOUBLE_FLOAT && mode == DFmode)
-	      || (mode == TFmode && !TARGET_IEEEQUAD)
-	      || mode == SDmode || mode == DDmode || mode == TDmode))
+	      || FLOAT128_2REG_P (mode)
+	      || DECIMAL_FLOAT_MODE_P (mode)))
 	{
 	  /* _Decimal128 must use an even/odd register pair.  This assumes
 	     that the register number is odd when fregno is odd.  */
 	  if (mode == TDmode && (cum->fregno % 2) == 1)
 	    cum->fregno++;
 
-	  if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0)
+	  if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0)
 	      <= FP_ARG_V4_MAX_REG)
 	    cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
 	  else
 	    {
 	      cum->fregno = FP_ARG_V4_MAX_REG + 1;
-	      if (mode == DFmode || mode == TFmode
+	      if (mode == DFmode || FLOAT128_IBM_P (mode)
 		  || mode == DDmode || mode == TDmode)
 		cum->words += cum->words & 1;
 	      cum->words += rs6000_arg_size (mode, type);
@@ -9973,8 +9995,7 @@ rs6000_function_arg_advance_1 (CUMULATIV
 
       cum->words = align_words + n_words;
 
-      if (SCALAR_FLOAT_MODE_P (elt_mode)
-	  && TARGET_HARD_FLOAT && TARGET_FPRS)
+      if (SCALAR_FLOAT_MODE_P (elt_mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
 	{
 	  /* _Decimal128 must be passed in an even/odd float register pair.
 	     This assumes that the register number is odd when fregno is
@@ -10216,7 +10237,7 @@ rs6000_darwin64_record_arg_recurse (CUMU
 	      = gen_rtx_EXPR_LIST (VOIDmode,
 				   gen_rtx_REG (mode, cum->fregno++),
 				   GEN_INT (bitpos / BITS_PER_UNIT));
-	    if (mode == TFmode || mode == TDmode)
+	    if (FLOAT128_2REG_P (mode))
 	      cum->fregno++;
 	  }
 	else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, 1))
@@ -10567,15 +10588,15 @@ rs6000_function_arg (cumulative_args_t c
       if (TARGET_HARD_FLOAT && TARGET_FPRS
 	  && ((TARGET_SINGLE_FLOAT && mode == SFmode)
 	      || (TARGET_DOUBLE_FLOAT && mode == DFmode)
-	      || (mode == TFmode && !TARGET_IEEEQUAD)
-	      || mode == SDmode || mode == DDmode || mode == TDmode))
+	      || FLOAT128_2REG_P (mode)
+	      || DECIMAL_FLOAT_MODE_P (mode)))
 	{
 	  /* _Decimal128 must use an even/odd register pair.  This assumes
 	     that the register number is odd when fregno is odd.  */
 	  if (mode == TDmode && (cum->fregno % 2) == 1)
 	    cum->fregno++;
 
-	  if (cum->fregno + (mode == TFmode || mode == TDmode ? 1 : 0)
+	  if (cum->fregno + (FLOAT128_2REG_P (mode) ? 1 : 0)
 	      <= FP_ARG_V4_MAX_REG)
 	    return gen_rtx_REG (mode, cum->fregno);
 	  else
@@ -10637,7 +10658,7 @@ rs6000_function_arg (cumulative_args_t c
 	      machine_mode fmode = elt_mode;
 	      if (cum->fregno + (i + 1) * n_fpreg > FP_ARG_MAX_REG + 1)
 		{
-		  gcc_assert (fmode == TFmode || fmode == TDmode);
+		  gcc_assert (FLOAT128_2REG_P (fmode));
 		  fmode = DECIMAL_FLOAT_MODE_P (fmode) ? DDmode : DFmode;
 		}
 
@@ -10811,10 +10832,11 @@ rs6000_pass_by_reference (cumulative_arg
 			  machine_mode mode, const_tree type,
 			  bool named ATTRIBUTE_UNUSED)
 {
-  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode)
+  if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD
+      && FLOAT128_IEEE_P (TYPE_MODE (type)))
     {
       if (TARGET_DEBUG_ARG)
-	fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
+	fprintf (stderr, "function_arg_pass_by_reference: V4 IEEE 128-bit\n");
       return 1;
     }
 
@@ -11489,10 +11511,8 @@ rs6000_gimplify_va_arg (tree valist, tre
       && ((TARGET_SINGLE_FLOAT && TYPE_MODE (type) == SFmode)
           || (TARGET_DOUBLE_FLOAT 
               && (TYPE_MODE (type) == DFmode 
- 	          || TYPE_MODE (type) == TFmode
-	          || TYPE_MODE (type) == SDmode
-	          || TYPE_MODE (type) == DDmode
-	          || TYPE_MODE (type) == TDmode))))
+		  || FLOAT128_2REG_P (TYPE_MODE (type))
+		  || DECIMAL_FLOAT_MODE_P (TYPE_MODE (type))))))
     {
       /* FP args go in FP registers, if present.  */
       reg = fpr;
@@ -16755,7 +16775,7 @@ rs6000_secondary_reload_toc_costs (addr_
 static int
 rs6000_secondary_reload_memory (rtx addr,
 				enum reg_class rclass,
-				enum machine_mode mode)
+				machine_mode mode)
 {
   int extra_cost = 0;
   rtx reg, and_arg, plus_arg0, plus_arg1;
@@ -19053,7 +19073,7 @@ print_operand (FILE *file, rtx x, int co
 	/* Ugly hack because %y is overloaded.  */
 	if ((TARGET_SPE || TARGET_E500_DOUBLE)
 	    && (GET_MODE_SIZE (GET_MODE (x)) == 8
-		|| GET_MODE (x) == TFmode
+		|| FLOAT128_2REG_P (GET_MODE (x))
 		|| GET_MODE (x) == TImode
 		|| GET_MODE (x) == PTImode))
 	  {
@@ -21003,7 +21023,7 @@ rs6000_split_multireg_move (rtx dst, rtx
 	((TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT) ? DFmode : SFmode);
   else if (ALTIVEC_REGNO_P (reg))
     reg_mode = V16QImode;
-  else if (TARGET_E500_DOUBLE && mode == TFmode)
+  else if (TARGET_E500_DOUBLE && FLOAT128_2REG_P (mode))
     reg_mode = DFmode;
   else
     reg_mode = word_mode;
@@ -22080,7 +22100,8 @@ spe_func_has_64bit_regs_p (void)
 
 	      if (SPE_VECTOR_MODE (mode))
 		return true;
-	      if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode))
+	      if (TARGET_E500_DOUBLE
+		  && (mode == DFmode || FLOAT128_2REG_P (mode)))
 		return true;
 	    }
 	}
@@ -25843,6 +25864,8 @@ rs6000_output_function_epilogue (FILE *f
 			case DDmode:
 			case TFmode:
 			case TDmode:
+			case IFmode:
+			case KFmode:
 			  bits = 0x3;
 			  break;
 
@@ -26516,7 +26539,8 @@ output_toc (FILE *file, rtx x, int label
      TOC, things we put here aren't actually in the TOC, so we can allow
      FP constants.  */
   if (GET_CODE (x) == CONST_DOUBLE &&
-      (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode))
+      (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode
+       || GET_MODE (x) == IFmode || GET_MODE (x) == KFmode))
     {
       REAL_VALUE_TYPE rv;
       long k[4];
@@ -31040,7 +31064,7 @@ rs6000_register_move_cost (machine_mode 
 
   /* Moving between two similar registers is just one instruction.  */
   else if (reg_classes_intersect_p (to, from))
-    ret = (mode == TFmode || mode == TDmode) ? 4 : 2;
+    ret = (FLOAT128_2REG_P (mode)) ? 4 : 2;
 
   /* Everything else has to go through GENERAL_REGS.  */
   else
@@ -32107,7 +32131,7 @@ rs6000_function_value (const_tree valtyp
     {
       int first_reg, n_regs;
 
-      if (SCALAR_FLOAT_MODE_P (elt_mode))
+      if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (elt_mode))
 	{
 	  /* _Decimal128 must use even/odd register pairs.  */
 	  first_reg = (elt_mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
@@ -32144,7 +32168,7 @@ rs6000_function_value (const_tree valtyp
   if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
     /* _Decimal128 must use an even/odd register pair.  */
     regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
-  else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS
+  else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS
 	   && ((TARGET_SINGLE_FLOAT && (mode == SFmode)) || TARGET_DOUBLE_FLOAT))
     regno = FP_ARG_RETURN;
   else if (TREE_CODE (valtype) == COMPLEX_TYPE
@@ -32153,13 +32177,13 @@ rs6000_function_value (const_tree valtyp
   /* VSX is a superset of Altivec and adds V2DImode/V2DFmode.  Since the same
      return register is used in both cases, and we won't see V2DImode/V2DFmode
      for pure altivec, combine the two cases.  */
-  else if (TREE_CODE (valtype) == VECTOR_TYPE
+  else if ((TREE_CODE (valtype) == VECTOR_TYPE || FLOAT128_VECTOR_P (mode))
 	   && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
 	   && ALTIVEC_OR_VSX_VECTOR_MODE (mode))
     regno = ALTIVEC_ARG_RETURN;
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
 	   && (mode == DFmode || mode == DCmode
-	       || mode == TFmode || mode == TCmode))
+	       || FLOAT128_IBM_P (mode) || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -32181,7 +32205,7 @@ rs6000_libcall_value (machine_mode mode)
   if (DECIMAL_FLOAT_MODE_P (mode) && TARGET_HARD_FLOAT && TARGET_FPRS)
     /* _Decimal128 must use an even/odd register pair.  */
     regno = (mode == TDmode) ? FP_ARG_RETURN + 1 : FP_ARG_RETURN;
-  else if (SCALAR_FLOAT_MODE_P (mode)
+  else if (SCALAR_FLOAT_MODE_NOT_VECTOR_P (mode)
 	   && TARGET_HARD_FLOAT && TARGET_FPRS
            && ((TARGET_SINGLE_FLOAT && mode == SFmode) || TARGET_DOUBLE_FLOAT))
     regno = FP_ARG_RETURN;
@@ -32195,7 +32219,7 @@ rs6000_libcall_value (machine_mode mode)
     return rs6000_complex_function_value (mode);
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
 	   && (mode == DFmode || mode == DCmode
-	       || mode == TFmode || mode == TCmode))
+	       || FLOAT128_IBM_P (mode) || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -32421,6 +32445,8 @@ rs6000_scalar_mode_supported_p (machine_
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
+  else if (mode == KFmode)
+    return TARGET_FLOAT128;
   else
     return default_scalar_mode_supported_p (mode);
 }
@@ -32436,7 +32462,10 @@ rs6000_vector_mode_supported_p (machine_
   if (TARGET_SPE && SPE_VECTOR_MODE (mode))
     return true;
 
-  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+  /* There is no vector form for IEEE 128-bit.  If we return true for IEEE
+     128-bit, the compiler might try to widen IEEE 128-bit to IBM
+     double-double.  */
+  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) && !FLOAT128_IEEE_P (mode))
     return true;
 
   else
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 225574)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -402,6 +402,33 @@ extern const char *host_detect_local_cpu
 #define TARGET_DEBUG_TARGET	(rs6000_debug & MASK_DEBUG_TARGET)
 #define TARGET_DEBUG_BUILTIN	(rs6000_debug & MASK_DEBUG_BUILTIN)
 
+/* Helper macros for TFmode.  Quad floating point (TFmode) can be either IBM
+   long double format that uses a pair of doubles, or IEEE 128-bit floating
+   point.  KFmode was added as a way to represent IEEE 128-bit floating point,
+   even if the default for long double is the IBM long double format.
+   Similarly IFmode is the IBM long double format even if the default is IEEE
+   128-bit.  */
+#define FLOAT128_IEEE_P(MODE)						\
+  (((MODE) == TFmode && TARGET_IEEEQUAD)				\
+   || ((MODE) == KFmode))
+
+#define FLOAT128_IBM_P(MODE)						\
+  (((MODE) == TFmode && !TARGET_IEEEQUAD)				\
+   || ((MODE) == IFmode))
+
+/* Helper macros to say whether a 128-bit floating point type can go in a
+   single vector register, or whether it needs paired scalar values.  */
+#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE))
+
+#define FLOAT128_2REG_P(MODE)						\
+  (FLOAT128_IBM_P (MODE)						\
+   || ((MODE) == TDmode)						\
+   || (!TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE)))
+
+/* Return true for floating point that does not use a vector register.  */
+#define SCALAR_FLOAT_MODE_NOT_VECTOR_P(MODE)				\
+  (SCALAR_FLOAT_MODE_P (MODE) && !FLOAT128_VECTOR_P (MODE))
+
 /* Describe the vector unit used for arithmetic operations.  */
 extern enum rs6000_vector rs6000_vector_unit[];
 
@@ -888,11 +915,10 @@ enum data_align { align_abi, align_opt, 
    aligned to 4 or 8 bytes.  */
 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN)				\
   (STRICT_ALIGNMENT							\
-   || (((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode	\
-	|| (MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)	\
-       && (ALIGN) < 32)							\
+   || (SCALAR_FLOAT_MODE_NOT_VECTOR_P (MODE) && (ALIGN) < 32)		\
    || (!TARGET_EFFICIENT_UNALIGNED_VSX                                  \
-       && (VECTOR_MODE_P ((MODE)) && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))))
+       && ((VECTOR_MODE_P (MODE) || FLOAT128_VECTOR_P (MODE))		\
+	   && (((int)(ALIGN)) < VECTOR_ALIGN (MODE)))))
 
 \f
 /* Standard register usage.  */
@@ -1174,7 +1200,7 @@ enum data_align { align_abi, align_opt, 
    ? V2DFmode								\
    : TARGET_E500_DOUBLE && ((MODE) == VOIDmode || (MODE) == DFmode)	\
    ? DFmode								\
-   : !TARGET_E500_DOUBLE && (MODE) == TFmode && FP_REGNO_P (REGNO)	\
+   : !TARGET_E500_DOUBLE && FLOAT128_IBM_P (MODE) && FP_REGNO_P (REGNO)	\
    ? DFmode								\
    : !TARGET_E500_DOUBLE && (MODE) == TDmode && FP_REGNO_P (REGNO)	\
    ? DImode								\
@@ -1185,8 +1211,7 @@ enum data_align { align_abi, align_opt, 
      && (GET_MODE_SIZE (MODE) > 4)					\
      && INT_REGNO_P (REGNO)) ? 1 : 0)					\
    || (TARGET_VSX && FP_REGNO_P (REGNO)					\
-       && GET_MODE_SIZE (MODE) > 8 && ((MODE) != TDmode) 		\
-       && ((MODE) != TFmode)))
+       && GET_MODE_SIZE (MODE) > 8 && !FLOAT128_2REG_P (MODE)))
 
 #define VSX_VECTOR_MODE(MODE)		\
 	 ((MODE) == V4SFmode		\

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

* Re: [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b
  2015-07-09  0:02     ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b Michael Meissner
@ 2015-07-09  0:21       ` David Edelsohn
  0 siblings, 0 replies; 13+ messages in thread
From: David Edelsohn @ 2015-07-09  0:21 UTC (permalink / raw)
  To: Michael Meissner, GCC Patches

On Wed, Jul 8, 2015 at 8:01 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> David asked me to change the definition of FLOAT128_IBM_P and FLOAT128_IEEE_P
> so that they were more consistant.  In doing so, I realized that I didn't need
> to test TARGET_LONG_DOUBLE_128 in those macros, since the mode would never be
> TFmode, IFmode, or KFmode unless TARGET_LONG_DOUBLE_128 was true.
>
> He also asked for better verification that the existing calling sequence with
> long double (which needs the subsequent patches to test), and I will write such
> tests and test them, putting them in the final patches.
>
> It bootstraps fine with no regressions.  Is this patch ok to install?
>
> 2015-07-08  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         * config/rs6000/rs6000-protos.h (rs6000_secondary_reload_memory):
>         Use machine mode, not enum machine_mode in the prototype.
>
>         * config/rs6000/rs6000.h (FLOAT128_IEEE_P): New helper macros to
>         classify 128-bit floating point support.
>         (FLOAT128_IBM_P): Likewise.
>         (FLOAT128_VECTOR_P): Likewise.
>         (FLOAT128_2REG_P): Likewise.
>         (SCALAR_FLOAT_MODE_NOT_VECTOR_P): Likewise.
>         (SLOW_UNALIGNED_ACCESS): Add IEEE 128-bit floating point support.
>         (HARD_REGNO_CALLER_SAVE_MODE): Likewise.
>         (HARD_REGNO_CALL_PART_CLOBBERED): Likewise.
>
>         * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Drop
>         tests against TFmode/TDmode, since those modes do not use VSX
>         addresses.
>         (rs6000_hard_regno_mode_ok): Add IEEE 128-bit floating point
>         support.
>         (rs6000_init_hard_regno_mode_ok): Use new helper macros instead of
>         tests against TFmode, etc.
>         (invalid_e500_subreg): Add tests against IFmode/KFmode.
>         (reg_offset_addressing_ok_p): Likewise.
>         (rs6000_legitimate_offset_address_p): Likewise.
>         (rs6000_legitimize_address): Likewise.
>         (rs6000_legitimize_reload_address): Likewise.
>         (rs6000_legitimate_address_p): Clean up tests against TFmode and
>         TDmode to use the new helper macros, which will include IFmode and
>         KFmode.
>         (rs6000_emit_move): Likewise.
>         (rs6000_darwin64_record_arg_recurse): Likewise.
>         (print_operand): Likewise.
>         (rs6000_member_type_forces_blk): Treat IEEE 128-bit floating point
>         that uses a single vector register as a vector and not as a
>         floating point register in terms of the calling sequence.
>         (rs6000_discover_homogeneous_aggregate): Likewise.
>         (rs6000_return_in_memory): Likewise.
>         (init_cumulative_args): Likewise.
>         (rs6000_function_arg_boundary): Likewise.
>         (rs6000_function_arg_advance_1): Likewise.
>         (rs6000_function_arg): Likewise.
>         (rs6000_pass_by_reference): Likewise.
>         (rs6000_gimplify_va_arg): Likewise.
>         (rs6000_secondary_reload_memory): Use machine_mode not enum
>         machine mode.
>         (rs6000_split_multireg_move): Use new helper macros.
>         (spe_func_has_64bit_regs_p): Likewise.
>         (rs6000_output_function_epilogue): Add IFmode/KFmode support.
>         (output_toc): Use new helper macros.
>         (rs6000_register_move_cost): Likewise.
>         (rs6000_function_value): Add IEEE 128-bit floating point calling
>         sequence support.
>         (rs6000_libcall_value): Likewise.
>         (rs6000_scalar_mode_supported_p): Add support for IEEE 128-bit
>         floating point support.
>         (rs6000_vector_mode_supported_p): Likewise.

Okay.

Thanks, David

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

end of thread, other threads:[~2015-07-09  0:21 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-22 21:47 [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Michael Meissner
2015-06-02 17:51 ` David Edelsohn
2015-06-02 18:33   ` Michael Meissner
2015-06-02 19:32     ` David Edelsohn
2015-06-16 22:33   ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2 Michael Meissner
2015-07-09  0:02     ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #2b Michael Meissner
2015-07-09  0:21       ` David Edelsohn
2015-06-02 17:57 ` [PATCH], Add IEEE 128-bit floating point to PowerPC, patch #1 Joseph Myers
2015-06-02 18:40   ` Michael Meissner
2015-06-02 20:25     ` Joseph Myers
2015-06-02 20:50       ` David Edelsohn
2015-06-02 20:56       ` Michael Meissner
2015-06-02 21:18         ` Joseph Myers

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