diff mbox

, PowerPC IEEE 128-bit fp, #11-rev2 (enable libgcc conversions)

Message ID 20160106224754.GA1627@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner Jan. 6, 2016, 10:47 p.m. UTC
I have reworked the libgcc library interface that was in my original patch
#11.  There are 2 attachments, the first attachment is for patches in the gcc
space, and the second attachment is for the libgcc changes.

I added the conversions between IBM extended double and IEEE 128-bit floating
point to the code that is built for emulation support (using the KF functions)
and code that enables ISA 3.0 (power9) support using direct instructions.
Unfortunately, I discovered some problems with the builtins to pack and unpack
IBM extended double that only show up with -mcpu=power9.  So, I fixed the code
generation problem (involving & constraints and multi-register data types on
little endian systems) to generate correct code.  While I was modifying the
pack and unpack routines, I added support to allow pack to read values from
memory and use the upper registers.  I tightened up the iterators to not allow
TFmode if long double is IEEE 128-bit floating point.  In looking towards the
day when long double is IEEE 128-bit floating point, I also added builtins to
take/return explict __ibm128 instead of long double.

In terms of the libgcc library functions:

    1)	I removed the extra clean rule, modifying Makefile.in.  Now the only
	changes are to the toplevel configuration files and within the
	config/rs6000 subdirectory.

    2)	I removed creating ifunc descriptors for the 4 functions that convert
	between signed/unsigned __int128 and __float128 since at present we
	don't have specific ISA 3.0 code for these conversions (suggestion from
	Joseph Myers).

    3)	I modified the ISA 3.0 version of the comparison functions, to simplify
	the code somewhat based on suggestions from Joseph Myers.

    4)	I used __getauxval instead of getauxval in ifunc module.  Ideally, we
	will soon have __builtin_cpu_supports to directly test if the machine
	has hardware IEEE 128-bit floating point.

    5)	I put the exception handling code under #ifndef _SOFT_FLOAT control so
	that the 32-bit PowerPC machines that don't have hardware floating
	point will not use this code (the exception handling uses hardware
	instructions to cause a particular fault).

    6)	In looking at the exception handling, I tweaked the asm code somewhat
	to have an explicit target.

    7)	As I mentioned above, I made the conversion between IFmode and KFmode
	have IEEE 128-bit emulation and IEEE 128-bit hardware support
	versions.  I modified it to use __builtin_unpack_ibm128 and
	__builtin_pack_ibm128.

I have done bootstrap builds on a big endian Power7 and a little endian Power8
machine with no regressions.  Are these patches ok to install in the trunk?

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

	* config/rs6000/rs6000-builtin.def (BU_FLOAT128_2): Add support
	for pack/unpack functions for __ibm128.
	(PACK_IF): Likewise.
	(UNPACK_IF): Likewise.

	* config/rs6000/rs6000.c (rs6000_builtin_mask_calculate): Add
	support for __ibm128 pack/unpack functions.
	(rs6000_invalid_builtin): Likewise.
	(rs6000_init_builtins): Likewise.
	(rs6000_opt_masks): Likewise.

	* config/rs6000/rs6000.h (MASK_FLOAT128): Add short name.
	(RS6000_BTM_FLOAT128): Add support for __ibm128 pack/unpack
	functions
	(RS6000_BTM_COMMON): Likewise.

	* config/rs6000/rs6000.md (f128_vsx): New mode attribute.
	(unpack<mode>): Use FMOVE128_FPR iterator instead of FMOVE128, to
	disallow __builtin_{pack,unpack}_longdouble if long double is IEEE
	128-bit floating point.  Add support for the double values to be
	in Altivec registers for TF/IF packing and unpacking, but restrict
	TD packing sub-fields to be FPR registers.  Don't allow overlapped
	register support for packing.  Allow pack inputs to be memory
	locations.  Don't build generator functions for unpack<mode>_dm
	and unpack<mode>_nodm.
	(unpack<mode>_dm): Likewise.
	(unpack<mode>_nodm): Likewise.
	(pack<mode>): Likewise.

	* config/rs6000/rs6000-builtin.def (__builtin_pack_ibm128): Add
	built-in functions to pack/unpack explicit __ibm128 values.
	(__builtin_unpack_ibm128): Likewise.

	* doc/extend.texi (PowerPC Built-in Functions): Document
	__builtin_pack_ibm128 and __builtin_unpack_ibm128.

[libgcc]
2016-01-06  Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Steven Munroe (munroesj@linux.vnet.ibm.com)
	    Tulio Magno Quites Machado Filho <tulioqm@br.ibm.com>

	* config/rs6000/floattikf.c: New files for IEEE 128-bit floating
	point conversions.
	* config/rs6000/floatuntikf.c: Likewise.
	* config/rs6000/fixkfti.c: Likewise.
	* config/rs6000/fixunskfti.c: Likewise.
	* config/rs6000/extendkftf2-sw.c: Likewise.
	* config/rs6000/trunctfkf2-sw.c: Likewise.

	* config/rs6000/float128-hw.c: New file for ISA 3.0 IEEE 128-bit
	floating point hardware support.

	* config/rs6000/float128-ifunc.c: New file to pick either IEEE
	128-bit floating point software emulation or use ISA 3.0 hardware
	support if it is available.

	* config/rs6000/t-float128: New Makefile fragments to enable
	building __float128 emulation support.
	* config/rs6000/t-float128-hw: Likewise.

	* config/rs6000/sfp-exceptions.c: New file to provide exception
	support for IEEE 128-bit floating point.

	* config/rs6000/quad-float128.h: New file to support IEEE 128-bit
	floating point.

	* config/rs6000/float128-sed: New file to convert TF names to KF
	names for PowerPC IEEE 128-bit floating point support.

	* config/rs6000/sfp-machine.h (_FP_W_TYPE_SIZE): Use 64-bit types
	when building on 64-bit systems, or when VSX is enabled.
	(_FP_W_TYPE): Likewise.
	(_FP_WS_TYPE): Likewise.
	(_FP_I_TYPE): Likewise.
	(TItype): Define on 64-bit systems.
	(UTItype): Likewise.
	(TI_BITS): Likewise.
	(_FP_MUL_MEAT_D): Add support for using 64-bit types.
	(_FP_MUL_MEAT_Q): Likewise.
	(_FP_DIV_MEAT_D): Likewise.
	(_FP_DIV_MEAT_Q): Likewise.
	(_FP_NANFRAC_D): Likewise.
	(_FP_NANFRAC_Q): Likewise.
	(ISA_BIT): Add exception support if we are being compiled on a
	machine with hardware floating point support to build the IEEE
	128-bit emulation functions.
	(FP_EX_INVALID): Likewise.
	(FP_EX_OVERFLOW): Likewise.
	(FP_EX_UNDERFLOW): Likewise.
	(FP_EX_DIVZERO): Likewise.
	(FP_EX_INEXACT): Likewise.
	(FP_EX_ALL): Likewise.
	(__sfp_handle_exceptions): Likewise.
	(FP_HANDLE_EXCEPTIONS): Likewise.
	(FP_RND_NEAREST): Likewise.
	(FP_RND_ZERO): Likewise.
	(FP_RND_PINF): Likewise.
	(FP_RND_MINF): Likewise.
	(FP_RND_MASK): Likewise.
	(_FP_DECL_EX): Likewise.
	(FP_INIT_ROUNDMODE): Likewise.
	(FP_ROUNDMODE): Likewise.

	* libgcc/config.host (powerpc*-*-linux*): If compiler can compile
	VSX code, enable IEEE 128-bit floating point.

	* configure.ac (powerpc*-*-linux*): Check whether the PowerPC
	compiler can do __float128.
	* configure: Regenerate.

Comments

Joseph Myers Jan. 7, 2016, 9:54 p.m. UTC | #1
On Wed, 6 Jan 2016, Michael Meissner wrote:

>     5)	I put the exception handling code under #ifndef _SOFT_FLOAT control so
> 	that the 32-bit PowerPC machines that don't have hardware floating
> 	point will not use this code (the exception handling uses hardware
> 	instructions to cause a particular fault).

I think this needs to be __NO_FPRS__ instead of _SOFT_FLOAT (since soft-fp 
is also built for e500).

Other than that my only comments on this version are some formatting / 
coding style comments:

> Index: libgcc/config/rs6000/sfp-exceptions.c
> ===================================================================
> --- libgcc/config/rs6000/sfp-exceptions.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/libgcc)	(revision 0)
> +++ libgcc/config/rs6000/sfp-exceptions.c	(.../libgcc)	(revision 232096)
> @@ -0,0 +1,74 @@
> +/*
> + * Copyright (C) 2016 Free Software Foundation, Inc.
> + *

Normally we don't use the '*' at the start of each comment line.

> +TFtype
> +__floatsikf_hw (SItype_ppc a)
> +{
> +  return (TFtype)a;

Casts should have a space, "(TFtype) a".  Many more cases in this file.

> +/* __unordkf2 returns 1 if Nan or 0 otherwise.  */

NaN.

> +      __low = (double) (__value - (__float128)__high);			\

Again, space in cast.

> +      /* now renormalized move the high/low into canonical IBM long	\
> +	 double form.  */						\

Comments start with a capital letter.

> +  /* Handle the special cases of NAN and inifinity.  */			\

"infinity".

> +    RESULT = ((__float128)__high) + ((__float128)__low);		\

Spaces in casts.
diff mbox

Patch

Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000-builtin.def	(.../gcc/config/rs6000)	(working copy)
@@ -647,6 +647,15 @@ 
 		     | RS6000_BTC_BINARY),				\
 		    CODE_FOR_ ## ICODE)			/* ICODE */
 
+/* __float128 floating point builtins.  */
+#define BU_FLOAT128_2(ENUM, NAME, ATTR, ICODE)				\
+  RS6000_BUILTIN_2 (MISC_BUILTIN_ ## ENUM,		/* ENUM */	\
+		    "__builtin_" NAME,			/* NAME */	\
+		    RS6000_BTM_FLOAT128,		/* MASK */	\
+		    (RS6000_BTC_ ## ATTR		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_ ## ICODE)			/* ICODE */
+
 #endif
 
 /* Insure 0 is not a legitimate index.  */
@@ -1642,6 +1651,9 @@  BU_DFP_MISC_2 (UNPACK_TD,	"unpack_dec128
 BU_LDBL128_2 (PACK_TF,		"pack_longdouble",	CONST,	packtf)
 BU_LDBL128_2 (UNPACK_TF,	"unpack_longdouble",	CONST,	unpacktf)
 
+BU_FLOAT128_2 (PACK_IF,		"pack_ibm128",		CONST,	packif)
+BU_FLOAT128_2 (UNPACK_IF,	"unpack_ibm128",	CONST,	unpackif)
+
 BU_P7_MISC_2 (PACK_V1TI,	"pack_vector_int128",	CONST,	packv1ti)
 BU_P7_MISC_2 (UNPACK_V1TI,	"unpack_vector_int128",	CONST,	unpackv1ti)
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000.c	(.../gcc/config/rs6000)	(working copy)
@@ -3521,7 +3521,8 @@  rs6000_builtin_mask_calculate (void)
 	  | ((TARGET_HTM)		    ? RS6000_BTM_HTM	   : 0)
 	  | ((TARGET_DFP)		    ? RS6000_BTM_DFP	   : 0)
 	  | ((TARGET_HARD_FLOAT)	    ? RS6000_BTM_HARD_FLOAT : 0)
-	  | ((TARGET_LONG_DOUBLE_128)	    ? RS6000_BTM_LDBL128 : 0));
+	  | ((TARGET_LONG_DOUBLE_128)	    ? RS6000_BTM_LDBL128   : 0)
+	  | ((TARGET_FLOAT128)		    ? RS6000_BTM_FLOAT128  : 0));
 }
 
 /* Implement TARGET_MD_ASM_ADJUST.  All asm statements are considered
@@ -14605,6 +14606,8 @@  rs6000_invalid_builtin (enum rs6000_buil
 	   " -mlong-double-128 options", name);
   else if ((fnmask & RS6000_BTM_HARD_FLOAT) != 0)
     error ("Builtin function %s requires the -mhard-float option", name);
+  else if ((fnmask & RS6000_BTM_FLOAT128) != 0)
+    error ("Builtin function %s requires the -mfloat128 options", name);
   else
     error ("Builtin function %s is not supported with the current options",
 	   name);
@@ -14894,19 +14897,21 @@  rs6000_init_builtins (void)
      IFmode is the IBM extended 128-bit format that is a pair of doubles.
      TFmode will be either IEEE 128-bit floating point or the IBM double-double
      format that uses a pair of doubles, depending on the switches and
-     defaults.  */
+     defaults.  Always create the types even if we don't register the keywords
+     to allow built-in functions using these types to be created.  */
+
+  ibm128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ibm128_float_type_node) = 128;
+  layout_type (ibm128_float_type_node);
+  SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+
+  ieee128_float_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (ieee128_float_type_node) = 128;
+  layout_type (ieee128_float_type_node);
+  SET_TYPE_MODE (ieee128_float_type_node, KFmode);
+
   if (TARGET_FLOAT128)
     {
-      ibm128_float_type_node = make_node (REAL_TYPE);
-      TYPE_PRECISION (ibm128_float_type_node) = 128;
-      layout_type (ibm128_float_type_node);
-      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
-
-      ieee128_float_type_node = make_node (REAL_TYPE);
-      TYPE_PRECISION (ieee128_float_type_node) = 128;
-      layout_type (ieee128_float_type_node);
-      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
-
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
 					      "__float128");
 
@@ -34223,6 +34228,7 @@  static struct rs6000_opt_mask const rs60
   { "hard-dfp",		 RS6000_BTM_DFP,	false, false },
   { "hard-float",	 RS6000_BTM_HARD_FLOAT,	false, false },
   { "long-double-128",	 RS6000_BTM_LDBL128,	false, false },
+  { "float128",		 RS6000_BTM_FLOAT128,	false, false },
 };
 
 /* Option variables that we want to support inside attribute((target)) and
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000.h	(.../gcc/config/rs6000)	(working copy)
@@ -605,6 +605,7 @@  extern int rs6000_vector_align[];
 #define MASK_DLMZB			OPTION_MASK_DLMZB
 #define MASK_EABI			OPTION_MASK_EABI
 #define MASK_FPRND			OPTION_MASK_FPRND
+#define MASK_FLOAT128			OPTION_MASK_FLOAT128
 #define MASK_P8_FUSION			OPTION_MASK_P8_FUSION
 #define MASK_HARD_FLOAT			OPTION_MASK_HARD_FLOAT
 #define MASK_HTM			OPTION_MASK_HTM
@@ -2670,6 +2671,7 @@  extern int frame_pointer_needed;
 #define RS6000_BTM_DFP		MASK_DFP	/* Decimal floating point.  */
 #define RS6000_BTM_HARD_FLOAT	MASK_SOFT_FLOAT	/* Hardware floating point.  */
 #define RS6000_BTM_LDBL128	MASK_MULTIPLE	/* 128-bit long double.  */
+#define RS6000_BTM_FLOAT128	MASK_FLOAT128	/* IEEE 128-bit fp.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
@@ -2684,7 +2686,8 @@  extern int frame_pointer_needed;
 				 | RS6000_BTM_CELL			\
 				 | RS6000_BTM_DFP			\
 				 | RS6000_BTM_HARD_FLOAT		\
-				 | RS6000_BTM_LDBL128)
+				 | RS6000_BTM_LDBL128			\
+				 | RS6000_BTM_FLOAT128)
 
 /* Define builtin enum index.  */
 
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000)	(revision 232093)
+++ gcc/config/rs6000/rs6000.md	(.../gcc/config/rs6000)	(working copy)
@@ -469,6 +469,9 @@  (define_mode_attr f64_av  [(DF "wv") (DD
 ; Definitions for 64-bit access to ISA 3.0 (power9) vector
 (define_mode_attr f64_p9  [(DF "wb") (DD "wn")])
 
+; Definitions for 128-bit IBM extended double word pack/unpack
+(define_mode_attr f128_vsx [(TF "ws") (IF "ws") (TD "d")])
+
 ; These modes do not fit in integer registers in 32-bit mode.
 ; but on e500v2, the gpr are 64 bit registers
 (define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD])
@@ -13109,16 +13112,16 @@  (define_mode_attr FP128_64 [(TF "DF")
 (define_expand "unpack<mode>"
   [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "")
 	(unspec:<FP128_64>
-	 [(match_operand:FMOVE128 1 "register_operand" "")
+	 [(match_operand:FMOVE128_FPR 1 "register_operand" "")
 	  (match_operand:QI 2 "const_0_to_1_operand" "")]
 	 UNSPEC_UNPACK_128BIT))]
   "FLOAT128_2REG_P (<MODE>mode)"
   "")
 
-(define_insn_and_split "unpack<mode>_dm"
-  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m,d,r,m")
+(define_insn_and_split "*unpack<mode>_dm"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=<f128_vsx>,m,<f128_vsx>,r,m")
 	(unspec:<FP128_64>
-	 [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r")
+	 [(match_operand:FMOVE128_FPR 1 "register_operand" "d,d,r,d,r")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")]
 	 UNSPEC_UNPACK_128BIT))]
   "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)"
@@ -13139,10 +13142,10 @@  (define_insn_and_split "unpack<mode>_dm"
   [(set_attr "type" "fp,fpstore,mffgpr,mftgpr,store")
    (set_attr "length" "4")])
 
-(define_insn_and_split "unpack<mode>_nodm"
-  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=d,m")
+(define_insn_and_split "*unpack<mode>_nodm"
+  [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "=<f128_vsx>,m")
 	(unspec:<FP128_64>
-	 [(match_operand:FMOVE128 1 "register_operand" "d,d")
+	 [(match_operand:FMOVE128_FPR 1 "register_operand" "d,d")
 	  (match_operand:QI 2 "const_0_to_1_operand" "i,i")]
 	 UNSPEC_UNPACK_128BIT))]
   "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)"
@@ -13164,30 +13167,31 @@  (define_insn_and_split "unpack<mode>_nod
    (set_attr "length" "4")])
 
 (define_insn_and_split "pack<mode>"
-  [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d")
-	(unspec:FMOVE128
-	 [(match_operand:<FP128_64> 1 "register_operand" "0,d")
-	  (match_operand:<FP128_64> 2 "register_operand" "d,d")]
+  [(set (match_operand:FMOVE128_FPR 0 "register_operand" "=&d,&d,&d,&d")
+	(unspec:FMOVE128_FPR
+	 [(match_operand:<FP128_64> 1 "input_operand" "<f128_vsx>,<f128_vsx>,m,m")
+	  (match_operand:<FP128_64> 2 "input_operand" "<f128_vsx>,m,<f128_vsx>,m")]
 	 UNSPEC_PACK_128BIT))]
   "FLOAT128_2REG_P (<MODE>mode)"
-  "@
-   fmr %L0,%2
-   #"
-  "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])"
+  "#"
+  "&& reload_completed"
   [(set (match_dup 3) (match_dup 1))
    (set (match_dup 4) (match_dup 2))]
 {
-  unsigned dest_hi = REGNO (operands[0]);
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+  rtx op2 = operands[2];
+  unsigned dest_hi = REGNO (op0);
   unsigned dest_lo = dest_hi + 1;
 
-  gcc_assert (!IN_RANGE (REGNO (operands[1]), dest_hi, dest_lo));
-  gcc_assert (!IN_RANGE (REGNO (operands[2]), dest_hi, dest_lo));
+  gcc_assert (!REG_P (op1) || !IN_RANGE (REGNO (op1), dest_hi, dest_lo));
+  gcc_assert (!REG_P (op2) || !IN_RANGE (REGNO (op2), dest_hi, dest_lo));
 
   operands[3] = gen_rtx_REG (<FP128_64>mode, dest_hi);
   operands[4] = gen_rtx_REG (<FP128_64>mode, dest_lo);
 }
-  [(set_attr "type" "fp,fp")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "fp,fpload,fpload,fpload")
+   (set_attr "length" "8")])
 
 (define_insn "unpack<mode>"
   [(set (match_operand:DI 0 "register_operand" "=d,d")
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk/gcc/doc)	(revision 232093)
+++ gcc/doc/extend.texi	(.../gcc/doc)	(working copy)
@@ -13512,6 +13512,8 @@  uint64_t __builtin_ppc_get_timebase ();
 unsigned long __builtin_ppc_mftb ();
 double __builtin_unpack_longdouble (long double, int);
 long double __builtin_pack_longdouble (double, double);
+double __builtin_unpack_ibm128 (__ibm128, int);
+__ibm128 __builtin_pack_ibm128 (double, double);
 @end smallexample
 
 The @code{vec_rsqrt}, @code{__builtin_rsqrt}, and