[PATCH, rs6000] Add minimum __float128 built-in support required for glibc

Bill Schmidt wschmidt@linux.vnet.ibm.com
Wed Jun 22 20:14:00 GMT 2016


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)
 
 /* 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;
+}



More information about the Gcc-patches mailing list