public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
@ 2016-06-22 20:14 Bill Schmidt
  2016-06-22 20:26 ` Joseph Myers
  0 siblings, 1 reply; 9+ messages in thread
From: Bill Schmidt @ 2016-06-22 20:14 UTC (permalink / raw)
  To: GCC Patches; +Cc: Segher Boessenkool, David Edelsohn

Hi,

This patch implements built-ins to support __float128 on 64-bit PowerPC.
This is a minimum set of built-ins required for use by glibc.  The following
six built-ins are supported:

  __builtin_absf128
  __builtin_copysignf128
  __builtin_huge_valf128
  __builtin_inff128
  __builtin_nanf128
  __builtin_nansf128

For the NaNs, I borrowed heavily from a similar patch posted recently for
the ia64 target, which allows the constants to be generated early on.  The
absf128 and copysignf128 built-ins rely on some existing patterns, although
I had to write a soft-float version for the latter.  For inff128, I've used a four-
instruction sequence to generate the bit pattern directly in the vector
register rather than requiring a load from the constant pool, although I've
included that alternative in commentary should it prove to be better in
practice.

New tests are provided to exercise the built-ins.

Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions.  All new tests pass except for the test for vspltish in
the infinity test; this relies on a patch in progress to fix things so we
generate that instead of an inferior sequence.  Is this ok for trunk,
and for 6.2 after an appropriate burn-in period?

Thanks!

Bill


[gcc]

2016-06-22  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	* config/rs6000/altivec.md (*altivec_vrl<VI_char>): Remove
	asterisk from name.
	(altivec_vslo_kf_v8hi): New define_insn.
	* config/rs6000/rs6000-builtin.def (BU_FLOAT128_2): New #define.
	(BU_FLOAT128_1): Likewise.
	(BU_FLOAT128_0): Likewise.
	(INFF128): New builtin.
	(HUGE_VALF128): Likewise.
	(FABSF128): Likewise.
	(COPYSIGNF128): Likewise.
	(RS6000_BUILTIN_NANF128): Likewise.
	(RS6000_BUILTIN_NANSF128): Likewise.
	* config/rs6000/rs6000.c (rs6000_fold_builtin): New prototype.
	(TARGET_FOLD_BUILTIN): New #define.
	(rs6000_builtin_mask_calculate): Add TARGET_FLOAT128 entry.
	(rs6000_invalid_builtin): Add handling for RS6000_BTM_FLOAT128.
	(rs6000_fold_builtin): New target hook implementation, handling
	folding of 128-bit NaNs.
	(rs6000_init_builtins): Initialize const_str_type_node; ensure all
	entries are filled in to avoid problems during bootstrap
	self-test; define builtins for 128-bit NaNs.
	(rs6000_opt_mask): Add entry for float128.
	* config/rs6000/rs6000.h (RS6000_BTM_FLOAT128): New #define.
	(RS6000_BTM_COMMON): Include RS6000_BTM_FLOAT128.
	(rs6000_builtin_type_index): Add RS6000_BTI_const_str.
	(const_str_type_node): New #define.
	* config/rs6000/vsx.md (infkf1): New define_expand.

[gcc/testsuite]

2016-06-22  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

	* gcc.target/powerpc/abs128-1.c: New.
	* gcc.target/powerpc/copysign128-1.c: New.
	* gcc.target/powerpc/inf128-1.c: New.
	* gcc.target/powerpc/inf128-2.c: New.
	* gcc.target/powerpc/nan128-1.c: New.


Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 237619)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -1608,7 +1608,7 @@
   }"
   [(set_attr "type" "vecperm")])
 
-(define_insn "*altivec_vrl<VI_char>"
+(define_insn "altivec_vrl<VI_char>"
   [(set (match_operand:VI2 0 "register_operand" "=v")
         (rotate:VI2 (match_operand:VI2 1 "register_operand" "v")
 		    (match_operand:VI2 2 "register_operand" "v")))]
@@ -1634,6 +1634,15 @@
   "vslo %0,%1,%2"
   [(set_attr "type" "vecperm")])
 
+(define_insn "altivec_vslo_kf_v8hi"
+  [(set (match_operand:KF 0 "register_operand" "=v")
+        (unspec:KF [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")]
+		     UNSPEC_VSLO))]
+  "TARGET_ALTIVEC"
+  "vslo %0,%1,%2"
+  [(set_attr "type" "vecperm")])
+
 (define_insn "vslv"
   [(set (match_operand:V16QI 0 "register_operand" "=v")
 	(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
Index: gcc/config/rs6000/rs6000-builtin.def
===================================================================
--- gcc/config/rs6000/rs6000-builtin.def	(revision 237619)
+++ gcc/config/rs6000/rs6000-builtin.def	(working copy)
@@ -652,7 +652,30 @@
 		     | RS6000_BTC_BINARY),				\
 		    CODE_FOR_ ## ICODE)			/* ICODE */
 
+/* IEEE 128-bit 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 */
 
+#define BU_FLOAT128_1(ENUM, NAME, ATTR, ICODE)                          \
+  RS6000_BUILTIN_1 (MISC_BUILTIN_ ## ENUM,              /* ENUM */      \
+                    "__builtin_" NAME,                  /* NAME */      \
+		    RS6000_BTM_FLOAT128,                /* MASK */      \
+		    (RS6000_BTC_ ## ATTR                /* ATTR */      \
+		     | RS6000_BTC_UNARY),                               \
+		    CODE_FOR_ ## ICODE)                 /* ICODE */
+
+#define BU_FLOAT128_0(ENUM, NAME, ATTR, ICODE)                          \
+  RS6000_BUILTIN_0 (MISC_BUILTIN_ ## ENUM,              /* ENUM */      \
+                    "__builtin_" NAME,                  /* NAME */      \
+		    RS6000_BTM_FLOAT128,                /* MASK */      \
+		    RS6000_BTC_ ## ATTR,                /* ATTR */      \
+		    CODE_FOR_ ## ICODE)                 /* ICODE */
+
 /* Miscellaneous builtins for instructions added in ISA 3.0.  These
    instructions don't require either the DFP or VSX options, just the basic
    ISA 3.0 enablement since they operate on general purpose registers.  */
@@ -1788,6 +1811,10 @@ BU_P9_MISC_0 (DARN_32,		"darn_32", 		MISC, darn_32
 BU_P9_64BIT_MISC_0 (DARN_RAW,	"darn_raw", 		MISC, darn_raw)
 BU_P9_64BIT_MISC_0 (DARN,	"darn",			MISC, darn)
 
+/* 0 argument IEEE 128-bit floating-point functions.  */
+BU_FLOAT128_0 (INFF128,	        "inff128",              CONST,  infkf1)
+BU_FLOAT128_0 (HUGE_VALF128,	"huge_valf128",		CONST,	infkf1)
+
 BU_LDBL128_2 (PACK_TF,		"pack_longdouble",	CONST,	packtf)
 BU_LDBL128_2 (UNPACK_TF,	"unpack_longdouble",	CONST,	unpacktf)
 
@@ -1814,6 +1841,11 @@ BU_P9V_OVERLOAD_1 (VPRTYBD,	"vprtybd")
 BU_P9V_OVERLOAD_1 (VPRTYBQ,	"vprtybq")
 BU_P9V_OVERLOAD_1 (VPRTYBW,	"vprtybw")
 
+/* 1 argument IEEE 128-bit floating-point functions.  */
+BU_FLOAT128_1 (FABSF128,	"fabsf128",       CONST, abskf2)
+
+/* 2 argument IEEE 128-bit floating-point functions.  */
+BU_FLOAT128_2 (COPYSIGNF128,	"copysignf128",   CONST, copysignkf3)
 \f
 /* 1 argument crypto functions.  */
 BU_CRYPTO_1 (VSBOX,		"vsbox",	  CONST, crypto_vsbox)
@@ -2191,6 +2223,12 @@ BU_SPECIAL_X (RS6000_BUILTIN_CPU_IS, "__builtin_cp
 BU_SPECIAL_X (RS6000_BUILTIN_CPU_SUPPORTS, "__builtin_cpu_supports",
 	      RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
 
+BU_SPECIAL_X (RS6000_BUILTIN_NANF128, "__builtin_nanf128",
+	      RS6000_BTM_FLOAT128, RS6000_BTC_CONST)
+
+BU_SPECIAL_X (RS6000_BUILTIN_NANSF128, "__builtin_nansf128",
+	      RS6000_BTM_FLOAT128, RS6000_BTC_CONST)
+
 /* Darwin CfString builtin.  */
 BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
 	      RS6000_BTC_MISC)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 237619)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -1328,6 +1328,7 @@ static bool rs6000_secondary_reload_move (enum rs6
 					  bool);
 rtl_opt_pass *make_pass_analyze_swaps (gcc::context*);
 static bool rs6000_keep_leaf_when_profiled () __attribute__ ((unused));
+static tree rs6000_fold_builtin (tree, int, tree *, bool);
 
 /* Hash table stuff for keeping track of TOC entries.  */
 
@@ -1602,6 +1603,9 @@ static const struct attribute_spec rs6000_attribut
 #undef TARGET_BUILTIN_DECL
 #define TARGET_BUILTIN_DECL rs6000_builtin_decl
 
+#undef TARGET_FOLD_BUILTIN
+#define TARGET_FOLD_BUILTIN rs6000_fold_builtin
+
 #undef TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
 
@@ -3682,7 +3686,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
@@ -15510,11 +15515,48 @@ rs6000_invalid_builtin (enum rs6000_builtins fncod
 	   " -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 option", name);
   else
     error ("Builtin function %s is not supported with the current options",
 	   name);
 }
 
+/* Target hook for early folding of built-ins, shamelessly stolen
+   from ia64.c.  */
+
+static tree
+rs6000_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
+		     tree *args, bool ignore ATTRIBUTE_UNUSED)
+{
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+    {
+      enum rs6000_builtins fn_code
+	= (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
+      switch (fn_code)
+	{
+	case RS6000_BUILTIN_NANF128:
+	case RS6000_BUILTIN_NANSF128:
+	  {
+	    const char *str = c_getstr (*args);
+	    int quiet = fn_code == RS6000_BUILTIN_NANF128;
+	    REAL_VALUE_TYPE real;
+
+	    if (str && real_nan (&real, str, quiet, KFmode))
+	      return build_real (TREE_TYPE (TREE_TYPE (fndecl)), real);
+	    return NULL_TREE;
+	  }
+	default:
+	  break;
+	}
+    }
+#ifdef SUBTARGET_FOLD_BUILTIN
+  return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore);
+#else
+  return NULL_TREE;
+#endif
+}
+
 /* Expand an expression EXP that calls a built-in function,
    with result going to TARGET if that's convenient
    (and in mode MODE if that's convenient).
@@ -15769,6 +15811,10 @@ rs6000_init_builtins (void)
   opaque_p_V2SI_type_node = build_pointer_type (opaque_V2SI_type_node);
   opaque_V4SI_type_node = build_opaque_vector_type (intSI_type_node, 4);
 
+  const_str_type_node
+    = build_pointer_type (build_qualified_type (char_type_node,
+						TYPE_QUAL_CONST));
+
   /* We use V1TI mode as a special container to hold __int128_t items that
      must live in VSX registers.  */
   if (intTI_type_node)
@@ -15831,6 +15877,12 @@ rs6000_init_builtins (void)
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
 					      "__ibm128");
     }
+  else
+    {
+      /* All types must be nonzero, or self-test barfs during bootstrap.  */
+      ieee128_float_type_node = long_double_type_node;
+      ibm128_float_type_node = long_double_type_node;
+    }
 
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
@@ -15972,6 +16024,11 @@ rs6000_init_builtins (void)
   if (TARGET_EXTRA_BUILTINS || TARGET_SPE || TARGET_PAIRED_FLOAT)
     rs6000_common_init_builtins ();
 
+  ftype = build_function_type_list (ieee128_float_type_node,
+				    const_str_type_node, NULL_TREE);
+  def_builtin ("__builtin_nanf128", ftype, RS6000_BUILTIN_NANF128);
+  def_builtin ("__builtin_nansf128", ftype, RS6000_BUILTIN_NANSF128);
+
   ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
 				 RS6000_BUILTIN_RECIP, "__builtin_recipdiv");
   def_builtin ("__builtin_recipdiv", ftype, RS6000_BUILTIN_RECIP);
@@ -35569,6 +35626,7 @@ static struct rs6000_opt_mask const rs6000_builtin
   { "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	(revision 237619)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -2689,6 +2689,8 @@ extern int frame_pointer_needed;
 #define RS6000_BTM_HARD_FLOAT	MASK_SOFT_FLOAT	/* Hardware floating point.  */
 #define RS6000_BTM_LDBL128	MASK_MULTIPLE	/* 128-bit long double.  */
 #define RS6000_BTM_64BIT	MASK_64BIT	/* 64-bit addressing.  */
+/* FIXME: Do we need a separate mask bit?  */
+#define RS6000_BTM_FLOAT128     MASK_P9_VECTOR  /* IEEE 128-bit float.  */
 
 #define RS6000_BTM_COMMON	(RS6000_BTM_ALTIVEC			\
 				 | RS6000_BTM_VSX			\
@@ -2705,7 +2707,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.  */
 
@@ -2809,6 +2812,7 @@ enum rs6000_builtin_type_index
   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_const_str,          /* pointer to const char * */
   RS6000_BTI_MAX
 };
 
@@ -2865,6 +2869,7 @@ enum rs6000_builtin_type_index
 #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])
+#define const_str_type_node	         (rs6000_builtin_types[RS6000_BTI_const_str])
 
 extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
 extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 237619)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -13326,7 +13326,25 @@
    "xssqrtqp %0,%1"
   [(set_attr "type" "vecdiv")])
 
-(define_insn "copysign<mode>3"
+(define_expand "copysign<mode>3"
+  [(use (match_operand:IEEE128 0 "altivec_register_operand" ""))
+   (use (match_operand:IEEE128 1 "altivec_register_operand" ""))
+   (use (match_operand:IEEE128 2 "altivec_register_operand" ""))]
+  "FLOAT128_IEEE_P (<MODE>mode)"
+{
+  if (TARGET_FLOAT128_HW)
+    emit_insn (gen_copysign<mode>3_hard (operands[0], operands[1],
+    	                                 operands[2]));
+  else
+    {
+      rtx tmp = gen_reg_rtx (<MODE>mode);
+      emit_insn (gen_copysign<mode>3_soft (operands[0], operands[1],
+      		                           operands[2], tmp));
+    }
+  DONE;
+})
+
+(define_insn "copysign<mode>3_hard"
   [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
 	(unspec:IEEE128
 	 [(match_operand:IEEE128 1 "altivec_register_operand" "v")
@@ -13336,6 +13354,18 @@
    "xscpsgnqp %0,%2,%1"
   [(set_attr "type" "vecsimple")])
 
+(define_insn "copysign<mode>3_soft"
+  [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
+	(unspec:IEEE128
+	 [(match_operand:IEEE128 1 "altivec_register_operand" "v")
+	  (match_operand:IEEE128 2 "altivec_register_operand" "v")
+	  (match_operand:IEEE128 3 "altivec_register_operand" "+v")]
+	 UNSPEC_COPYSIGN))]
+  "!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+   "xscpsgndp %x3,%x2,%x1\n\txxpermdi %x0,%x3,%x1,1"
+  [(set_attr "type" "veccomplex")
+   (set_attr "length" "8")])
+
 (define_insn "neg<mode>2_hw"
   [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v")
 	(neg:IEEE128
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(revision 237619)
+++ gcc/config/rs6000/vsx.md	(working copy)
@@ -2721,3 +2721,38 @@
   "TARGET_P9_VECTOR"
   "vextsw2d %0,%1"
   [(set_attr "type" "vecsimple")])
+
+;; IEEE-128 floating-point built-in support.
+;; These are in vsx.md since IEEE-128 support is in the VSX chapter.
+
+;; Infinity.
+;; tmp1 = 0x FFF7 FFF7 FFF7 FFF7 FFF7 FFF7 FFF7 FFF7
+;; tmp2 = 0x 000C 000C 000C 000C 000C 000C 000C 000C
+;; tmp3 = 0x 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF
+;; out  = 0x 7FFF 0000 0000 0000 0000 0000 0000 0000 = +INF
+;; (Note that -9 has 14 in bits 1:4, so can be reused for the shift count.)
+
+;; Alternate method:  Load from constant pool.
+;; REAL_VALUE_TYPE inf;
+;; rtx tmp;
+;; real_inf (&inf);
+;; tmp = const_double_from_real_value (inf, KFmode);
+;; tmp = validize_mem (force_const_mem (KFmode, tmp));
+;; emit_move_insn (operands[0], tmp);
+
+(define_expand "infkf1"
+ [(set (match_operand:KF 0 "register_operand" "")
+       (const_int 0))]
+  "TARGET_FLOAT128"
+  "
+{
+  rtx tmp1 = gen_reg_rtx (V8HImode);
+  rtx tmp2 = gen_reg_rtx (V8HImode);
+  rtx tmp3 = gen_reg_rtx (V8HImode);
+  emit_insn (gen_altivec_vspltish (tmp1, GEN_INT (-9)));
+  emit_insn (gen_altivec_vspltish (tmp2, GEN_INT (12)));
+  emit_insn (gen_altivec_vrlh (tmp3, tmp1, tmp2));
+  emit_insn (gen_altivec_vslo_kf_v8hi (operands[0], tmp3, tmp1));
+  DONE;
+}")
+
Index: gcc/testsuite/gcc.target/powerpc/abs128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/abs128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/abs128-1.c	(working copy)
@@ -0,0 +1,61 @@
+/* { dg-do run { target { powerpc64*-*-* && vmx_hw } } } */
+/* { dg-options "-mfloat128" } */
+
+void abort ();
+
+typedef unsigned long long int uint64_t;
+
+typedef union
+{
+  __float128 value;
+
+  struct
+  {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+    unsigned negative:1;
+    unsigned exponent:15;
+    unsigned quiet_nan:1;
+    uint64_t mant_high:47;
+    uint64_t mant_low:64;
+#else
+    uint64_t mant_low:64;
+    uint64_t mant_high:47;
+    unsigned quiet_nan:1;
+    unsigned exponent:15;
+    unsigned negative:1;
+#endif
+  } nan;
+
+} ieee854_float128;
+
+int
+main (int argc, int *argv[])
+{
+  ieee854_float128 x, z;
+
+  x.nan.negative = 1;
+  x.nan.exponent = 0x22;
+  x.nan.quiet_nan = 0;
+  x.nan.mant_high = 0x1234;
+  x.nan.mant_low = 0xabcdef;
+
+  z.value = __builtin_fabsf128 (x.value);
+
+  if (z.nan.negative != 0
+      || z.nan.exponent != 0x22
+      || z.nan.quiet_nan != 0
+      || z.nan.mant_high != 0x1234
+      || z.nan.mant_low != 0xabcdef)
+    abort ();
+
+  z.value = __builtin_fabsf128 (z.value);
+
+  if (z.nan.negative != 0
+      || z.nan.exponent != 0x22
+      || z.nan.quiet_nan != 0
+      || z.nan.mant_high != 0x1234
+      || z.nan.mant_low != 0xabcdef)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/copysign128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/copysign128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/copysign128-1.c	(working copy)
@@ -0,0 +1,58 @@
+/* { dg-do run { target { powerpc64*-*-* && vmx_hw } } } */
+/* { dg-options "-mfloat128" } */
+
+void abort ();
+
+typedef unsigned long long int uint64_t;
+
+typedef union
+{
+  __float128 value;
+
+  struct
+  {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+    unsigned negative:1;
+    unsigned exponent:15;
+    unsigned quiet_nan:1;
+    uint64_t mant_high:47;
+    uint64_t mant_low:64;
+#else
+    uint64_t mant_low:64;
+    uint64_t mant_high:47;
+    unsigned quiet_nan:1;
+    unsigned exponent:15;
+    unsigned negative:1;
+#endif
+  } nan;
+
+} ieee854_float128;
+
+int
+main (int argc, int *argv[])
+{
+  ieee854_float128 x, y, z;
+
+  x.nan.negative = 0;
+  x.nan.exponent = 0x22;
+  x.nan.quiet_nan = 0;
+  x.nan.mant_high = 0x1234;
+  x.nan.mant_low = 0xabcdef;
+
+  y.nan.negative = 1;
+  y.nan.exponent = 0;
+  y.nan.quiet_nan = 0;
+  y.nan.mant_high = 0;
+  y.nan.mant_low = 0;
+
+  z.value = __builtin_copysignf128 (x.value, y.value);
+
+  if (z.nan.negative != 1
+      || z.nan.exponent != 0x22
+      || z.nan.quiet_nan != 0
+      || z.nan.mant_high != 0x1234
+      || z.nan.mant_low != 0xabcdef)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/inf128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/inf128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/inf128-1.c	(working copy)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu-*" } { "-mcpu=power9" } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-mcpu=power9" } */
+/* { dg-final { scan-assembler-times "vspltish" 4 } } */
+/* { dg-final { scan-assembler-times "vrlh" 2 } } */
+/* { dg-final { scan-assembler-times "vslo" 2 } } */
+
+__float128
+foo ()
+{
+  __float128 x = __builtin_inff128 ();
+  return x;
+}
+
+__float128
+bar ()
+{
+  __float128 x = __builtin_huge_valf128 ();
+  return x;
+}
Index: gcc/testsuite/gcc.target/powerpc/inf128-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/inf128-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/inf128-2.c	(working copy)
@@ -0,0 +1,55 @@
+/* { dg-do run { target { powerpc64*-*-* && vmx_hw } } } */
+/* { dg-options "-mfloat128" } */
+
+void abort ();
+
+typedef unsigned long long int uint64_t;
+
+typedef union
+{
+  __float128 value;
+
+  struct
+  {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+    unsigned negative:1;
+    unsigned exponent:15;
+    unsigned quiet_nan:1;
+    uint64_t mant_high:47;
+    uint64_t mant_low:64;
+#else
+    uint64_t mant_low:64;
+    uint64_t mant_high:47;
+    unsigned quiet_nan:1;
+    unsigned exponent:15;
+    unsigned negative:1;
+#endif
+  } nan;
+
+} ieee854_float128;
+
+int
+main (int argc, int *argv[])
+{
+  ieee854_float128 y;
+
+  y.value = __builtin_inff128 ();
+
+  if (y.nan.negative != 0
+      || y.nan.exponent != 0x7fff
+      || y.nan.quiet_nan != 0
+      || y.nan.mant_high != 0
+      || y.nan.mant_low != 0)
+    abort ();
+
+  y.value = __builtin_huge_valf128 ();
+
+  if (y.nan.negative != 0
+      || y.nan.exponent != 0x7fff
+      || y.nan.quiet_nan != 0
+      || y.nan.mant_high != 0
+      || y.nan.mant_low != 0)
+    abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.target/powerpc/nan128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/nan128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/nan128-1.c	(working copy)
@@ -0,0 +1,77 @@
+/* { dg-do run { target { powerpc64*-*-* && vmx_hw } } } */
+/* { dg-options "-mfloat128" } */
+
+#include <stdio.h>
+
+void abort ();
+
+typedef unsigned long long int uint64_t;
+
+typedef union
+{
+  __float128 value;
+
+  struct
+  {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+    unsigned negative:1;
+    unsigned exponent:15;
+    unsigned quiet_nan:1;
+    uint64_t mant_high:47;
+    uint64_t mant_low:64;
+#else
+    uint64_t mant_low:64;
+    uint64_t mant_high:47;
+    unsigned quiet_nan:1;
+    unsigned exponent:15;
+    unsigned negative:1;
+#endif
+  } nan;
+
+} ieee854_float128;
+
+int
+main (int argc, int *argv[])
+{
+  ieee854_float128 y;
+
+  y.value = __builtin_nanf128 ("1");
+
+  if (y.nan.negative != 0
+      || y.nan.exponent != 0x7fff
+      || y.nan.quiet_nan != 1
+      || y.nan.mant_high != 0
+      || y.nan.mant_low != 1)
+    abort ();
+
+  y.value = __builtin_nanf128 ("0x2ab3c");
+
+  if (y.nan.negative != 0
+      || y.nan.exponent != 0x7fff
+      || y.nan.quiet_nan != 1
+      || y.nan.mant_high != 0
+      || y.nan.mant_low != 0x2ab3c)
+    abort ();
+
+  y.value = __builtin_nansf128 ("1");
+
+  if (
+      y.nan.negative != 0
+      || y.nan.exponent != 0x7fff
+      || y.nan.quiet_nan != 0
+      || y.nan.mant_high != 0
+      || y.nan.mant_low != 1
+      )
+    abort ();
+
+  y.value = __builtin_nansf128 ("0x2ab3c");
+
+  if (y.nan.negative != 0
+      || y.nan.exponent != 0x7fff
+      || y.nan.quiet_nan != 0
+      || y.nan.mant_high != 0
+      || y.nan.mant_low != 0x2ab3c)
+    abort ();
+
+  return 0;
+}

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-22 20:14 [PATCH, rs6000] Add minimum __float128 built-in support required for glibc Bill Schmidt
@ 2016-06-22 20:26 ` Joseph Myers
  2016-06-22 20:34   ` Bill Schmidt
  0 siblings, 1 reply; 9+ messages in thread
From: Joseph Myers @ 2016-06-22 20:26 UTC (permalink / raw)
  To: Bill Schmidt; +Cc: GCC Patches, Segher Boessenkool, David Edelsohn

On Wed, 22 Jun 2016, Bill Schmidt wrote:

> Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
> regressions.  All new tests pass except for the test for vspltish in
> the infinity test; this relies on a patch in progress to fix things so we
> generate that instead of an inferior sequence.  Is this ok for trunk,
> and for 6.2 after an appropriate burn-in period?

Depending on how long it takes my _FloatN / _FloatNx patch to get 
reviewed, it might be better to avoid adding the built-in functions as 
target-specific on trunk.  Adding them as architecture-independent would 
be extremely straightforward once the support for the types is there, and 
then the architecture-specific versions would only be needed for GCC 6.  
(The insn patterns and tests would still be relevant for trunk.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-22 20:26 ` Joseph Myers
@ 2016-06-22 20:34   ` Bill Schmidt
  2016-06-22 23:28     ` Joseph Myers
  0 siblings, 1 reply; 9+ messages in thread
From: Bill Schmidt @ 2016-06-22 20:34 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Segher Boessenkool, David Edelsohn

Hi Joseph,

That's indeed preferable for the long term -- given how close we are to the 
cutoff for 6.2, though, I'm worried about adding any new dependencies for 
getting this upstream.  I'd suggest that we go ahead with reviewing this 
patch in the short term, and I'll be happy to work with you later on getting
the impedance matching right when they become arch-neutral.

Thanks!
Bill

> On Jun 22, 2016, at 3:26 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> 
> On Wed, 22 Jun 2016, Bill Schmidt wrote:
> 
>> Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
>> regressions.  All new tests pass except for the test for vspltish in
>> the infinity test; this relies on a patch in progress to fix things so we
>> generate that instead of an inferior sequence.  Is this ok for trunk,
>> and for 6.2 after an appropriate burn-in period?
> 
> Depending on how long it takes my _FloatN / _FloatNx patch to get 
> reviewed, it might be better to avoid adding the built-in functions as 
> target-specific on trunk.  Adding them as architecture-independent would 
> be extremely straightforward once the support for the types is there, and 
> then the architecture-specific versions would only be needed for GCC 6.  
> (The insn patterns and tests would still be relevant for trunk.)
> 
> -- 
> Joseph S. Myers
> joseph@codesourcery.com
> 

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-22 20:34   ` Bill Schmidt
@ 2016-06-22 23:28     ` Joseph Myers
  2016-06-23  1:11       ` Bill Schmidt
  0 siblings, 1 reply; 9+ messages in thread
From: Joseph Myers @ 2016-06-22 23:28 UTC (permalink / raw)
  To: Bill Schmidt; +Cc: GCC Patches, Segher Boessenkool, David Edelsohn

On Wed, 22 Jun 2016, Bill Schmidt wrote:

> Hi Joseph,
> 
> That's indeed preferable for the long term -- given how close we are to the 
> cutoff for 6.2, though, I'm worried about adding any new dependencies for 
> getting this upstream.  I'd suggest that we go ahead with reviewing this 
> patch in the short term, and I'll be happy to work with you later on getting
> the impedance matching right when they become arch-neutral.

The architecture-independent built-in functions really aren't hard.  See 
this patch, on top of my main _FloatN / _FloatNx patch.  (Not written up 
or fully regression-tested, and I want to add more test coverage, but it 
seems to work.)  To keep this patch minimal I didn't include updates to a 
few case statements only needed for optimization, e.g. in 
tree_call_nonnegative_warnv_p, but when those are changed you get 
optimizations automatically for these functions that would be harder to 
get with anything architecture-specific.

Regarding your patch:

(a) for GCC 6 (supposing my patch is used for trunk), it's missing 
documentation for the new functions (this patch has documentation for the 
architecture-independent functions);

(b) for trunk, having an insn pattern infkf1 for a built-in function that 
loads a constant is not appropriate (other insn patterns to optimize the 
architecture-independent built-in functions may well be appropriate).  
Rather, if there is a particularly efficient way of generating code to 
load a certain constant, the back end should be set up to use that way 
whenever that constant occurs (more generally, whenever any constant to 
which that efficient way applies occurs) - including for example when it 
occurs from folding arithmetic, say (__float128) __builtin_inff (), not 
just from __builtin_inff128 ().

diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 7fab9f8..468313c4 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -76,6 +76,27 @@ DEF_PRIMITIVE_TYPE (BT_UNWINDWORD, (*lang_hooks.types.type_for_mode)
 DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node)
 DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE, long_double_type_node)
+DEF_PRIMITIVE_TYPE (BT_FLOAT16, (float16_type_node
+				 ? float16_type_node
+				 : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT32, (float32_type_node
+				 ? float32_type_node
+				 : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT64, (float64_type_node
+				 ? float64_type_node
+				 : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT128, (float128_type_node
+				  ? float128_type_node
+				  : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT32X, (float32x_type_node
+				  ? float32x_type_node
+				  : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT64X, (float64x_type_node
+				  ? float64x_type_node
+				  : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT128X, (float128x_type_node
+				   ? float128x_type_node
+				   : error_mark_node))
 DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT, complex_float_type_node)
 DEF_PRIMITIVE_TYPE (BT_COMPLEX_DOUBLE, complex_double_type_node)
 DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONGDOUBLE, complex_long_double_type_node)
@@ -146,6 +167,13 @@ DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE)
    distinguish it from two types in sequence, "long" followed by
    "double".  */
 DEF_FUNCTION_TYPE_0 (BT_FN_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT128X, BT_FLOAT128X)
 DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT32, BT_DFLOAT32)
 DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT64, BT_DFLOAT64)
 DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT128, BT_DFLOAT128)
@@ -157,6 +185,13 @@ DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_FLOAT, BT_FLOAT, BT_FLOAT)
 DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_DOUBLE, BT_DOUBLE, BT_DOUBLE)
 DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_LONGDOUBLE,
 		     BT_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT16_FLOAT16, BT_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32_FLOAT32, BT_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64_FLOAT64, BT_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128_FLOAT128, BT_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32X_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64X_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128X_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X)
 DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT,
 		     BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT)
 DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
@@ -208,6 +243,13 @@ DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_CONST_STRING,
 		     BT_LONGDOUBLE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT16_CONST_STRING, BT_FLOAT16, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32_CONST_STRING, BT_FLOAT32, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64_CONST_STRING, BT_FLOAT64, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128_CONST_STRING, BT_FLOAT128, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32X_CONST_STRING, BT_FLOAT32X, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64X_CONST_STRING, BT_FLOAT64X, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128X_CONST_STRING, BT_FLOAT128X, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_CONST_STRING, BT_DFLOAT32, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_CONST_STRING, BT_DFLOAT64, BT_CONST_STRING)
 DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING,
@@ -271,6 +313,20 @@ DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLE,
 		     BT_DOUBLE, BT_DOUBLE, BT_DOUBLE)
 DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE,
 		     BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_FLOAT16,
+		     BT_FLOAT16, BT_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32_FLOAT32_FLOAT32,
+		     BT_FLOAT32, BT_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64_FLOAT64_FLOAT64,
+		     BT_FLOAT64, BT_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128_FLOAT128_FLOAT128,
+		     BT_FLOAT128, BT_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32X_FLOAT32X_FLOAT32X,
+		     BT_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_FLOAT64X,
+		     BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_FLOAT128X,
+		     BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X)
 DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_FLOATPTR,
 		     BT_FLOAT, BT_FLOAT, BT_FLOAT_PTR)
 DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLEPTR,
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 5d234a5..f8ec9cf 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5761,6 +5761,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
   switch (fcode)
     {
     CASE_FLT_FN (BUILT_IN_FABS):
+    CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
     case BUILT_IN_FABSD32:
     case BUILT_IN_FABSD64:
     case BUILT_IN_FABSD128:
@@ -5770,6 +5771,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,
       break;
 
     CASE_FLT_FN (BUILT_IN_COPYSIGN):
+    CASE_FLT_FN_FLOATN_NX (BUILT_IN_COPYSIGN):
       target = expand_builtin_copysign (exp, target, subtarget);
       if (target)
 	return target;
@@ -8094,12 +8096,14 @@ fold_builtin_0 (location_t loc, tree fndecl)
       return fold_builtin_LINE (loc, type);
 
     CASE_FLT_FN (BUILT_IN_INF):
+    CASE_FLT_FN_FLOATN_NX (BUILT_IN_INF):
     case BUILT_IN_INFD32:
     case BUILT_IN_INFD64:
     case BUILT_IN_INFD128:
       return fold_builtin_inf (loc, type, true);
 
     CASE_FLT_FN (BUILT_IN_HUGE_VAL):
+    CASE_FLT_FN_FLOATN_NX (BUILT_IN_HUGE_VAL):
       return fold_builtin_inf (loc, type, false);
 
     case BUILT_IN_CLASSIFY_TYPE:
@@ -8148,6 +8152,7 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
       return fold_builtin_strlen (loc, type, arg0);
 
     CASE_FLT_FN (BUILT_IN_FABS):
+    CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
     case BUILT_IN_FABSD32:
     case BUILT_IN_FABSD64:
     case BUILT_IN_FABSD128:
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 33a7626..814ca15 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -87,6 +87,19 @@ along with GCC; see the file COPYING3.  If not see
   DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, BT_LAST,	\
 	       false, false, false, ATTRS, true, true)
 
+/* A set of GCC builtins for _FloatN and _FloatNx types.  TYPE_MACRO
+   is called with an argument such as FLOAT32 to produce the enum
+   value for the type.  */
+#undef DEF_GCC_FLOATN_NX_BUILTINS
+#define DEF_GCC_FLOATN_NX_BUILTINS(ENUM, NAME, TYPE_MACRO, ATTRS)	\
+  DEF_GCC_BUILTIN (ENUM ## F16, NAME "f16", TYPE_MACRO (FLOAT16), ATTRS) \
+  DEF_GCC_BUILTIN (ENUM ## F32, NAME "f32", TYPE_MACRO (FLOAT32), ATTRS) \
+  DEF_GCC_BUILTIN (ENUM ## F64, NAME "f64", TYPE_MACRO (FLOAT64), ATTRS) \
+  DEF_GCC_BUILTIN (ENUM ## F128, NAME "f128", TYPE_MACRO (FLOAT128), ATTRS) \
+  DEF_GCC_BUILTIN (ENUM ## F32X, NAME "f32x", TYPE_MACRO (FLOAT32X), ATTRS) \
+  DEF_GCC_BUILTIN (ENUM ## F64X, NAME "f64x", TYPE_MACRO (FLOAT64X), ATTRS) \
+  DEF_GCC_BUILTIN (ENUM ## F128X, NAME "f128x", TYPE_MACRO (FLOAT128X), ATTRS)
+
 /* A library builtin (like __builtin_strchr) is a builtin equivalent
    of an ANSI/ISO standard library function.  In addition to the
    `__builtin' version, we will create an ordinary version (e.g,
@@ -296,6 +309,9 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILL, "ceill", BT_FN_LONGDOUBLE_LONGDOUBLE, AT
 DEF_C99_BUILTIN        (BUILT_IN_COPYSIGN, "copysign", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_COPYSIGNF, "copysignf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_COPYSIGNL, "copysignl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define COPYSIGN_TYPE(F) BT_FN_##F##_##F##_##F
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_COPYSIGN, "copysign", COPYSIGN_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef COPYSIGN_TYPE
 DEF_LIB_BUILTIN        (BUILT_IN_COS, "cos", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_COSF, "cosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
 DEF_LIB_BUILTIN        (BUILT_IN_COSH, "cosh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -326,6 +342,9 @@ DEF_C99_BUILTIN        (BUILT_IN_EXPM1L, "expm1l", BT_FN_LONGDOUBLE_LONGDOUBLE,
 DEF_LIB_BUILTIN        (BUILT_IN_FABS, "fabs", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSF, "fabsf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSL, "fabsl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define FABS_TYPE(F) BT_FN_##F##_##F
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_FABS, "fabs", FABS_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef FABS_TYPE
 DEF_GCC_BUILTIN        (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -359,6 +378,8 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_GAMMAL_R, "gammal_r", BT_FN_LONGDOUBLE_LONGDOUB
 DEF_GCC_BUILTIN        (BUILT_IN_HUGE_VAL, "huge_val", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_HUGE_VALF, "huge_valf", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_HUGE_VALL, "huge_vall", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define INF_TYPE(F) BT_FN_##F
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_HUGE_VAL, "huge_val", INF_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_HYPOT, "hypot", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_HYPOTF, "hypotf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_HYPOTL, "hypotl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -374,6 +395,8 @@ DEF_C99_BUILTIN        (BUILT_IN_ILOGBL, "ilogbl", BT_FN_INT_LONGDOUBLE, ATTR_MA
 DEF_GCC_BUILTIN        (BUILT_IN_INF, "inf", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INFF, "inff", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INFL, "infl", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_INF, "inf", INF_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef INF_TYPE
 DEF_GCC_BUILTIN	       (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INFD64, "infd64", BT_FN_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INFD128, "infd128", BT_FN_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -446,12 +469,16 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFL, "modfl", BT_FN_LONGDOUBLE_LONGDOUBLE_LON
 DEF_C99_BUILTIN        (BUILT_IN_NAN, "nan", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_C99_BUILTIN        (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_C99_BUILTIN        (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+#define NAN_TYPE(F) BT_FN_##F##_CONST_STRING
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_NAN, "nan", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
 DEF_GCC_BUILTIN        (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_GCC_BUILTIN        (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_GCC_BUILTIN        (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_GCC_BUILTIN        (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_GCC_BUILTIN        (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
 DEF_GCC_BUILTIN        (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_NANS, "nans", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
+#undef NAN_TYPE
 DEF_C99_BUILTIN        (BUILT_IN_NEARBYINT, "nearbyint", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_NEARBYINTF, "nearbyintf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_NEARBYINTL, "nearbyintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index c61ece9..0cd7b1e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -10811,6 +10811,13 @@ that are recognized in any mode since ISO C90 reserves these names for
 the purpose to which ISO C99 puts them.  All these functions have
 corresponding versions prefixed with @code{__builtin_}.
 
+There are also built-in functions @code{__builtin_fabsf@var{n}},
+@code{__builtin_fabsf@var{n}x}, @code{__builtin_copysignf@var{n}} and
+@code{__builtin_copysignf@var{n}x}, corresponding to the TS 18661-3
+functions @code{fabsf@var{n}}, @code{fabsf@var{n}x},
+@code{copysignf@var{n}} and @code{copysignf@var{n}x}, for supported
+types @code{_Float@var{n}} and @code{_Float@var{n}x}.
+
 There are also GNU extension functions @code{clog10}, @code{clog10f} and
 @code{clog10l} which names are reserved by ISO C99 for future use.
 All these functions have versions prefixed with @code{__builtin_}.
@@ -11349,6 +11356,16 @@ Similar to @code{__builtin_huge_val}, except the return
 type is @code{long double}.
 @end deftypefn
 
+@deftypefn {Built-in Function} _Float@var{n} __builtin_huge_valf@var{n} (void)
+Similar to @code{__builtin_huge_val}, except the return type is
+@code{_Float@var{n}}.
+@end deftypefn
+
+@deftypefn {Built-in Function} _Float@var{n}x __builtin_huge_valf@var{n}x (void)
+Similar to @code{__builtin_huge_val}, except the return type is
+@code{_Float@var{n}x}.
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_fpclassify (int, int, int, int, int, ...)
 This built-in implements the C99 fpclassify functionality.  The first
 five int arguments should be the target library's notion of the
@@ -11387,6 +11404,16 @@ Similar to @code{__builtin_inf}, except the return
 type is @code{long double}.
 @end deftypefn
 
+@deftypefn {Built-in Function} _Float@var{n} __builtin_inff@var{n} (void)
+Similar to @code{__builtin_inf}, except the return
+type is @code{_Float@var{n}}.
+@end deftypefn
+
+@deftypefn {Built-in Function} _Float@var{n} __builtin_inff@var{n}x (void)
+Similar to @code{__builtin_inf}, except the return
+type is @code{_Float@var{n}x}.
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_isinf_sign (...)
 Similar to @code{isinf}, except the return value is -1 for
 an argument of @code{-Inf} and 1 for an argument of @code{+Inf}.
@@ -11433,6 +11460,16 @@ Similar to @code{__builtin_nan}, except the return type is @code{float}.
 Similar to @code{__builtin_nan}, except the return type is @code{long double}.
 @end deftypefn
 
+@deftypefn {Built-in Function} _Float@var{n} __builtin_nanf@var{n} (const char *str)
+Similar to @code{__builtin_nan}, except the return type is
+@code{_Float@var{n}}.
+@end deftypefn
+
+@deftypefn {Built-in Function} _Float@var{n}x __builtin_nanf@var{n}x (const char *str)
+Similar to @code{__builtin_nan}, except the return type is
+@code{_Float@var{n}x}.
+@end deftypefn
+
 @deftypefn {Built-in Function} double __builtin_nans (const char *str)
 Similar to @code{__builtin_nan}, except the significand is forced
 to be a signaling NaN@.  The @code{nans} function is proposed by
@@ -11447,6 +11484,16 @@ Similar to @code{__builtin_nans}, except the return type is @code{float}.
 Similar to @code{__builtin_nans}, except the return type is @code{long double}.
 @end deftypefn
 
+@deftypefn {Built-in Function} _Float@var{n} __builtin_nansf@var{n} (const char *str)
+Similar to @code{__builtin_nans}, except the return type is
+@code{_Float@var{n}}.
+@end deftypefn
+
+@deftypefn {Built-in Function} _Float@var{n}x __builtin_nansf@var{n}x (const char *str)
+Similar to @code{__builtin_nans}, except the return type is
+@code{_Float@var{n}x}.
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_ffs (int x)
 Returns one plus the index of the least significant 1-bit of @var{x}, or
 if @var{x} is zero, returns zero.
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 923a5d4..2bbc887 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -1131,12 +1131,14 @@ fold_const_call (combined_fn fn, tree type, tree arg)
       return NULL_TREE;
 
     CASE_CFN_NAN:
+    CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NAN):
     case CFN_BUILT_IN_NAND32:
     case CFN_BUILT_IN_NAND64:
     case CFN_BUILT_IN_NAND128:
       return fold_const_builtin_nan (type, arg, true);
 
     CASE_CFN_NANS:
+    CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
       return fold_const_builtin_nan (type, arg, false);
 
     default:
diff --git a/gcc/testsuite/gcc.dg/torture/float128-builtin.c b/gcc/testsuite/gcc.dg/torture/float128-builtin.c
new file mode 100644
index 0000000..2f4936f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float128 built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float128 } */
+/* { dg-options "" } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128x-builtin.c b/gcc/testsuite/gcc.dg/torture/float128x-builtin.c
new file mode 100644
index 0000000..33ceeec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128x-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float128x built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float128x } */
+/* { dg-options "" } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float16-builtin.c b/gcc/testsuite/gcc.dg/torture/float16-builtin.c
new file mode 100644
index 0000000..2a043fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float16-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float16 built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float16 } */
+/* { dg-options "" } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32-builtin.c b/gcc/testsuite/gcc.dg/torture/float32-builtin.c
new file mode 100644
index 0000000..25c7072
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float32 built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float32 } */
+/* { dg-options "" } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-builtin.c b/gcc/testsuite/gcc.dg/torture/float32x-builtin.c
new file mode 100644
index 0000000..63f23e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32x-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float32x built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float32x } */
+/* { dg-options "" } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64-builtin.c b/gcc/testsuite/gcc.dg/torture/float64-builtin.c
new file mode 100644
index 0000000..8e8c123
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float64 built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float64 } */
+/* { dg-options "" } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-builtin.c b/gcc/testsuite/gcc.dg/torture/float64x-builtin.c
new file mode 100644
index 0000000..4d91c4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64x-builtin.c
@@ -0,0 +1,8 @@
+/* Test _Float64x built-in functions.  */
+/* { dg-do run } */
+/* { dg-require-effective-target float64x } */
+/* { dg-options "" } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-builtin.h"
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-builtin.h b/gcc/testsuite/gcc.dg/torture/floatn-builtin.h
new file mode 100644
index 0000000..c562812
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-builtin.h
@@ -0,0 +1,64 @@
+/* Tests for _FloatN / _FloatNx types: compile and execution tests for
+   built-in functions.  Before including this file, define WIDTH as
+   the value N; define EXT to 1 for _FloatNx and 0 for _FloatN.  */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define FN(F) CONCAT4 (F, f, WIDTH, x)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define FN(F) CONCAT3 (F, f, WIDTH)
+#endif
+
+extern void exit (int);
+extern void abort (void);
+
+extern TYPE test_type;
+extern __typeof (FN (__builtin_inf) ()) test_type;
+extern __typeof (FN (__builtin_huge_val) ()) test_type;
+extern __typeof (FN (__builtin_nan) ("")) test_type;
+extern __typeof (FN (__builtin_nans) ("")) test_type;
+extern __typeof (FN (__builtin_fabs) (0)) test_type;
+extern __typeof (FN (__builtin_copysign) (0, 0)) test_type;
+
+volatile TYPE inf_cst = FN (__builtin_inf) ();
+volatile TYPE huge_val_cst = FN (__builtin_huge_val) ();
+volatile TYPE nan_cst = FN (__builtin_nan) ("");
+volatile TYPE nans_cst = FN (__builtin_nans) ("");
+volatile TYPE neg0 = -CST (0.0), neg1 = -CST (1.0), one = 1.0;
+
+int
+main (void)
+{
+  volatile TYPE r;
+  if (!__builtin_isinf (inf_cst))
+    abort ();
+  if (!__builtin_isinf (huge_val_cst))
+    abort ();
+  if (inf_cst != huge_val_cst)
+    abort ();
+  if (!__builtin_isnan (nan_cst))
+    abort ();
+  if (!__builtin_isnan (nans_cst))
+    abort ();
+  r = FN (__builtin_fabs) (neg1);
+  if (r != CST (1.0))
+    abort ();
+  r = FN (__builtin_copysign) (one, neg0);
+  if (r != neg1)
+    abort ();
+  r = FN (__builtin_copysign) (inf_cst, neg1);
+  if (r != -huge_val_cst)
+    abort ();
+  r = FN (__builtin_copysign) (-inf_cst, one);
+  if (r != huge_val_cst)
+    abort ();
+  exit (0);
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index acb8bf1..db6fbcf 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -234,6 +234,9 @@ as_internal_fn (combined_fn code)
 /* Helper macros for math builtins.  */
 
 #define CASE_FLT_FN(FN) case FN: case FN##F: case FN##L
+#define CASE_FLT_FN_FLOATN_NX(FN)			   \
+  case FN##F16: case FN##F32: case FN##F64: case FN##F128: \
+  case FN##F32X: case FN##F64X: case FN##F128X
 #define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
 #define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL: case FN##IMAX
 
@@ -3617,11 +3620,16 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
 #define FLOATN_NX_TYPE_NODE(IDX)	global_trees[TI_FLOATN_NX_TYPE_FIRST + (IDX)]
 #define FLOATNX_TYPE_NODE(IDX)		global_trees[TI_FLOATNX_TYPE_FIRST + (IDX)]
 
-/* Names for individual types, where required by back ends
-   (architecture-independent code should always iterate over all such
-   types).  */
+/* Names for individual types (code should normally iterate over all
+   such types; these are only for back-end use, or in contexts such as
+   *.def where iteration if not possible).  */
+#define float16_type_node		global_trees[TI_FLOAT16_TYPE]
+#define float32_type_node		global_trees[TI_FLOAT32_TYPE]
+#define float64_type_node		global_trees[TI_FLOAT64_TYPE]
 #define float128_type_node		global_trees[TI_FLOAT128_TYPE]
+#define float32x_type_node		global_trees[TI_FLOAT32X_TYPE]
 #define float64x_type_node		global_trees[TI_FLOAT64X_TYPE]
+#define float128x_type_node		global_trees[TI_FLOAT128X_TYPE]
 
 #define float_ptr_type_node		global_trees[TI_FLOAT_PTR_TYPE]
 #define double_ptr_type_node		global_trees[TI_DOUBLE_PTR_TYPE]

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-22 23:28     ` Joseph Myers
@ 2016-06-23  1:11       ` Bill Schmidt
  2016-06-23 11:44         ` Joseph Myers
  2016-06-23 12:49         ` Bill Schmidt
  0 siblings, 2 replies; 9+ messages in thread
From: Bill Schmidt @ 2016-06-23  1:11 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Segher Boessenkool, David Edelsohn



> On Jun 22, 2016, at 6:27 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> 
> On Wed, 22 Jun 2016, Bill Schmidt wrote:
> 
>> Hi Joseph,
>> 
>> That's indeed preferable for the long term -- given how close we are to the 
>> cutoff for 6.2, though, I'm worried about adding any new dependencies for 
>> getting this upstream.  I'd suggest that we go ahead with reviewing this 
>> patch in the short term, and I'll be happy to work with you later on getting
>> the impedance matching right when they become arch-neutral.
> 
> The architecture-independent built-in functions really aren't hard.  See 
> this patch, on top of my main _FloatN / _FloatNx patch.  (Not written up 
> or fully regression-tested, and I want to add more test coverage, but it 
> seems to work.)  To keep this patch minimal I didn't include updates to a 
> few case statements only needed for optimization, e.g. in 
> tree_call_nonnegative_warnv_p, but when those are changed you get 
> optimizations automatically for these functions that would be harder to 
> get with anything architecture-specific.

I understand that this is what we want for GCC 7.  My current concern is to
get my patch included in GCC 6.2, where I can't be polluting common code.
To get it accepted there, I first need this code approved in mainline.  So I
am quite willing to move to the architecture-independent ones later, but
for now I don't see that I have any choice but to seek approval for the
purely arch-dependent one.

> 
> Regarding your patch:
> 
> (a) for GCC 6 (supposing my patch is used for trunk), it's missing 
> documentation for the new functions (this patch has documentation for the 
> architecture-independent functions);

A very good point -- I totally forgot about this, and will have to add it.

> 
> (b) for trunk, having an insn pattern infkf1 for a built-in function that 
> loads a constant is not appropriate (other insn patterns to optimize the 
> architecture-independent built-in functions may well be appropriate).  
> Rather, if there is a particularly efficient way of generating code to 
> load a certain constant, the back end should be set up to use that way 
> whenever that constant occurs (more generally, whenever any constant to 
> which that efficient way applies occurs) - including for example when it 
> occurs from folding arithmetic, say (__float128) __builtin_inff (), not 
> just from __builtin_inff128 ().

The fact that I hook this built-in directly to a pattern named infkf1
doesn't seem to preclude anything you suggest.  I named it this way
on the off-chance that inf<m>1 becomes a standard pattern in the
future, in which case I want to generate this constant.  We can 
always use gen_infkf1 to reuse this code in any other context.  I'm
not understanding your objection.

Thanks,
Bill

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-23  1:11       ` Bill Schmidt
@ 2016-06-23 11:44         ` Joseph Myers
  2016-06-27 17:43           ` Richard Sandiford
  2016-06-23 12:49         ` Bill Schmidt
  1 sibling, 1 reply; 9+ messages in thread
From: Joseph Myers @ 2016-06-23 11:44 UTC (permalink / raw)
  To: Bill Schmidt; +Cc: GCC Patches, Segher Boessenkool, David Edelsohn

On Wed, 22 Jun 2016, Bill Schmidt wrote:

> I understand that this is what we want for GCC 7.  My current concern is to
> get my patch included in GCC 6.2, where I can't be polluting common code.
> To get it accepted there, I first need this code approved in mainline.  So I
> am quite willing to move to the architecture-independent ones later, but
> for now I don't see that I have any choice but to seek approval for the
> purely arch-dependent one.

I don't think it's sensible to choose implementation approaches on 
mainline based on possible backports.

It seems clear to me that the architecture-independent approach is the 
right one for mainline.  This may mean the backport has some 
architecture-specific code that's not on mainline (along with code, to 
optimize copysign/fabs expansion, that may be relevant in both places), 
but that shouldn't influence the choice of how to do things on mainline.

It looks rather like this proposed code would not in fact result in 
__builtin_inff128 or __builtin_huge_valf128 suitable for glibc use - 
there's no folding support for them so they wouldn't be usable in static 
initializers.  (This can be worked around, as would be necessary anyway 
for __float128 support in glibc for x86_64 with existing GCC releases - 
some internal header would define __builtin_inff128() to ((__float128) 
__builtin_inf ()) for older compilers.)

Until the glibc support is actually tested, reviewed and fully functional, 
it would not surprise me at all if there are other back-end bugs in GCC 6 
that need fixing for it to be usable to build or use such support in 
glibc, or other features needed that we haven't realised are needed.

> The fact that I hook this built-in directly to a pattern named infkf1
> doesn't seem to preclude anything you suggest.  I named it this way
> on the off-chance that inf<m>1 becomes a standard pattern in the
> future, in which case I want to generate this constant.  We can 
> always use gen_infkf1 to reuse this code in any other context.  I'm
> not understanding your objection.

That expander pattern is not useful given a target-independent built-in 
__builtin_inff128, since it will never be used except by a built-in 
function specifically associated with it.

I don't know what code will be generated for a use of _Float128 infinity, 
from the target-independent code - or, right now, for a use of 
(__float128) __builtin_inf ().  But if it's not the code you want, any 
reasonable fix would not be restricted to the case where __builtin_inff128 
() is used - it would work equally well for any case where that constant 
bit-pattern is wanted in VSX registers.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-23  1:11       ` Bill Schmidt
  2016-06-23 11:44         ` Joseph Myers
@ 2016-06-23 12:49         ` Bill Schmidt
  1 sibling, 0 replies; 9+ messages in thread
From: Bill Schmidt @ 2016-06-23 12:49 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Segher Boessenkool, David Edelsohn


> On Jun 22, 2016, at 8:10 PM, Bill Schmidt <wschmidt@linux.vnet.ibm.com> wrote:
> 
>> On Jun 22, 2016, at 6:27 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>> 
>> (b) for trunk, having an insn pattern infkf1 for a built-in function that 
>> loads a constant is not appropriate (other insn patterns to optimize the 
>> architecture-independent built-in functions may well be appropriate).  
>> Rather, if there is a particularly efficient way of generating code to 
>> load a certain constant, the back end should be set up to use that way 
>> whenever that constant occurs (more generally, whenever any constant to 
>> which that efficient way applies occurs) - including for example when it 
>> occurs from folding arithmetic, say (__float128) __builtin_inff (), not 
>> just from __builtin_inff128 ().
> 
> The fact that I hook this built-in directly to a pattern named infkf1
> doesn't seem to preclude anything you suggest.  I named it this way
> on the off-chance that inf<m>1 becomes a standard pattern in the
> future, in which case I want to generate this constant.  We can 
> always use gen_infkf1 to reuse this code in any other context.  I'm
> not understanding your objection.

Though perhaps your point is the specific use of KF here, which is
inconsistent and should be fixed.  The mode should be "whichever of
TF and KF is IEEE-128" as elsewhere.  I'll fix that.  Probably this
pattern should be moved over to rs6000.md also, where the fabs and
copysign support are.

Bill

> 
> Thanks,
> Bill

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-23 11:44         ` Joseph Myers
@ 2016-06-27 17:43           ` Richard Sandiford
  2016-06-27 17:48             ` Bill Schmidt
  0 siblings, 1 reply; 9+ messages in thread
From: Richard Sandiford @ 2016-06-27 17:43 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Bill Schmidt, GCC Patches, Segher Boessenkool, David Edelsohn

Joseph Myers <joseph@codesourcery.com> writes:
> On Wed, 22 Jun 2016, Bill Schmidt wrote:
>> The fact that I hook this built-in directly to a pattern named infkf1
>> doesn't seem to preclude anything you suggest.  I named it this way
>> on the off-chance that inf<m>1 becomes a standard pattern in the
>> future, in which case I want to generate this constant.  We can 
>> always use gen_infkf1 to reuse this code in any other context.  I'm
>> not understanding your objection.
>
> That expander pattern is not useful given a target-independent built-in 
> __builtin_inff128, since it will never be used except by a built-in 
> function specifically associated with it.
>
> I don't know what code will be generated for a use of _Float128 infinity, 
> from the target-independent code - or, right now, for a use of 
> (__float128) __builtin_inf ().  But if it's not the code you want, any 
> reasonable fix would not be restricted to the case where __builtin_inff128 
> () is used - it would work equally well for any case where that constant 
> bit-pattern is wanted in VSX registers.

Yeah, I don't think we should have named patterns to generate constants.
We should send the constant through the normal move patterns and make
the expander or move define_insns handle them appropriately.

Thanks,
Richard

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

* Re: [PATCH, rs6000] Add minimum __float128 built-in support required for glibc
  2016-06-27 17:43           ` Richard Sandiford
@ 2016-06-27 17:48             ` Bill Schmidt
  0 siblings, 0 replies; 9+ messages in thread
From: Bill Schmidt @ 2016-06-27 17:48 UTC (permalink / raw)
  To: Richard Sandiford
  Cc: Joseph Myers, GCC Patches, Segher Boessenkool, David Edelsohn


> On Jun 27, 2016, at 12:41 PM, Richard Sandiford <rdsandiford@googlemail.com> wrote:
> 
> Joseph Myers <joseph@codesourcery.com> writes:
>> On Wed, 22 Jun 2016, Bill Schmidt wrote:
>>> The fact that I hook this built-in directly to a pattern named infkf1
>>> doesn't seem to preclude anything you suggest.  I named it this way
>>> on the off-chance that inf<m>1 becomes a standard pattern in the
>>> future, in which case I want to generate this constant.  We can 
>>> always use gen_infkf1 to reuse this code in any other context.  I'm
>>> not understanding your objection.
>> 
>> That expander pattern is not useful given a target-independent built-in 
>> __builtin_inff128, since it will never be used except by a built-in 
>> function specifically associated with it.
>> 
>> I don't know what code will be generated for a use of _Float128 infinity, 
>> from the target-independent code - or, right now, for a use of 
>> (__float128) __builtin_inf ().  But if it's not the code you want, any 
>> reasonable fix would not be restricted to the case where __builtin_inff128 
>> () is used - it would work equally well for any case where that constant 
>> bit-pattern is wanted in VSX registers.
> 
> Yeah, I don't think we should have named patterns to generate constants.
> We should send the constant through the normal move patterns and make
> the expander or move define_insns handle them appropriately.

Agreed.  We'll plan on working the various interesting constants into the handling of the move insns.

Bill

> 
> Thanks,
> Richard
> 

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

end of thread, other threads:[~2016-06-27 17:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22 20:14 [PATCH, rs6000] Add minimum __float128 built-in support required for glibc Bill Schmidt
2016-06-22 20:26 ` Joseph Myers
2016-06-22 20:34   ` Bill Schmidt
2016-06-22 23:28     ` Joseph Myers
2016-06-23  1:11       ` Bill Schmidt
2016-06-23 11:44         ` Joseph Myers
2016-06-27 17:43           ` Richard Sandiford
2016-06-27 17:48             ` Bill Schmidt
2016-06-23 12:49         ` Bill Schmidt

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