+2016-06-24 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-builtin.def (BU_FLOAT128_2): New #define.
+ (BU_FLOAT128_1): Likewise.
+ (FABSQ): Likewise.
+ (COPYSIGNQ): Likewise.
+ (RS6000_BUILTIN_NANQ): Likewise.
+ (RS6000_BUILTIN_NANSQ): Likewise.
+ (RS6000_BUILTIN_INFQ): Likewise.
+ (RS6000_BUILTIN_HUGE_VALQ): 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 and infinities.
+ (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 and infinities.
+ (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/rs6000.md (copysign<mode>3 for IEEE128): Convert
+ to a define_expand that dispatches to either copysign<mode>3_soft
+ or copysign<mode>3_hard.
+ (copysign<mode>3_hard): Rename from copysign<mode>3.
+ (copysign<mode>3_soft): New define_insn.
+ * doc/extend.texi: Document new builtins.
+
2016-06-24 Jakub Jelinek <jakub@redhat.com>
* cfgloop.c (flow_loop_dump): Cast nit to uint64_t and print it using
| 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 */
/* Miscellaneous builtins for instructions added in ISA 3.0. These
instructions don't require either the DFP or VSX options, just the basic
BU_P9V_OVERLOAD_1 (VPRTYBQ, "vprtybq")
BU_P9V_OVERLOAD_1 (VPRTYBW, "vprtybw")
+/* 1 argument IEEE 128-bit floating-point functions. */
+BU_FLOAT128_1 (FABSQ, "fabsq", CONST, abskf2)
+
+/* 2 argument IEEE 128-bit floating-point functions. */
+BU_FLOAT128_2 (COPYSIGNQ, "copysignq", CONST, copysignkf3)
\f
/* 1 argument crypto functions. */
BU_CRYPTO_1 (VSBOX, "vsbox", CONST, crypto_vsbox)
BU_SPECIAL_X (RS6000_BUILTIN_CPU_SUPPORTS, "__builtin_cpu_supports",
RS6000_BTM_ALWAYS, RS6000_BTC_MISC)
+BU_SPECIAL_X (RS6000_BUILTIN_NANQ, "__builtin_nanq",
+ RS6000_BTM_FLOAT128, RS6000_BTC_CONST)
+
+BU_SPECIAL_X (RS6000_BUILTIN_NANSQ, "__builtin_nansq",
+ RS6000_BTM_FLOAT128, RS6000_BTC_CONST)
+
+BU_SPECIAL_X (RS6000_BUILTIN_INFQ, "__builtin_infq",
+ RS6000_BTM_FLOAT128, RS6000_BTC_CONST)
+
+BU_SPECIAL_X (RS6000_BUILTIN_HUGE_VALQ, "__builtin_huge_valq",
+ RS6000_BTM_FLOAT128, RS6000_BTC_CONST)
+
/* Darwin CfString builtin. */
BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS,
RS6000_BTC_MISC)
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. */
#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
| ((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
" -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_NANQ:
+ case RS6000_BUILTIN_NANSQ:
+ {
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ const char *str = c_getstr (*args);
+ int quiet = fn_code == RS6000_BUILTIN_NANQ;
+ REAL_VALUE_TYPE real;
+
+ if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
+ return build_real (type, real);
+ return NULL_TREE;
+ }
+ case RS6000_BUILTIN_INFQ:
+ case RS6000_BUILTIN_HUGE_VALQ:
+ {
+ tree type = TREE_TYPE (TREE_TYPE (fndecl));
+ REAL_VALUE_TYPE inf;
+ real_inf (&inf);
+ return build_real (type, inf);
+ }
+ 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).
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)
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. */
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_nanq", ftype, RS6000_BUILTIN_NANQ);
+ def_builtin ("__builtin_nansq", ftype, RS6000_BUILTIN_NANSQ);
+
+ ftype = build_function_type_list (ieee128_float_type_node, NULL_TREE);
+ def_builtin ("__builtin_infq", ftype, RS6000_BUILTIN_INFQ);
+ def_builtin ("__builtin_huge_valq", ftype, RS6000_BUILTIN_HUGE_VALQ);
+
ftype = builtin_function_type (DFmode, DFmode, DFmode, VOIDmode,
RS6000_BUILTIN_RECIP, "__builtin_recipdiv");
def_builtin ("__builtin_recipdiv", ftype, RS6000_BUILTIN_RECIP);
{ "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
#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. */
+#define RS6000_BTM_FLOAT128 MASK_P9_VECTOR /* IEEE 128-bit float. */
#define RS6000_BTM_COMMON (RS6000_BTM_ALTIVEC \
| RS6000_BTM_VSX \
| RS6000_BTM_CELL \
| RS6000_BTM_DFP \
| RS6000_BTM_HARD_FLOAT \
- | RS6000_BTM_LDBL128)
+ | RS6000_BTM_LDBL128 \
+ | RS6000_BTM_FLOAT128)
/* Define builtin enum 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
};
#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];
"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")
"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\;xxpermdi %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
returns the Time Base Register value as an unsigned long, throwing away
the most significant word on 32-bit environments.
+Additional built-in functions are available for the 64-bit PowerPC
+family of processors, for efficient use of 128-bit floating point
+(@code{__float128}) values.
+
+The following floating-point built-in functions are available with
+@code{-mfloat128} and Altivec support. All of them implement the
+function that is part of the name.
+
+@smallexample
+__float128 __builtin_fabsq (__float128)
+__float128 __builtin_copysignq (__float128, __float128)
+@end smallexample
+
+The following built-in functions are available with @code{-mfloat128}
+and Altivec support.
+
+@table @code
+@item __float128 __builtin_infq (void)
+Similar to @code{__builtin_inf}, except the return type is @code{__float128}.
+@findex __builtin_infq
+
+@item __float128 __builtin_huge_valq (void)
+Similar to @code{__builtin_huge_val}, except the return type is @code{__float128}.
+@findex __builtin_huge_valq
+
+@item __float128 __builtin_nanq (void)
+Similar to @code{__builtin_nan}, except the return type is @code{__float128}.
+@findex __builtin_nanq
+
+@item __float128 __builtin_nansq (void)
+Similar to @code{__builtin_nans}, except the return type is @code{__float128}.
+@findex __builtin_nansq
+@end table
+
The following built-in functions are available for the PowerPC family
of processors, starting with ISA 2.06 or later (@option{-mcpu=power7}
or @option{-mpopcntd}):
+2016-06-24 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/nan128-1.c: New.
+
2016-06-24 Eric Botcazou <ebotcazou@adacore.com>
* gfortran.dg/pr71642.f90: New test.
--- /dev/null
+/* { 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_fabsq (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_fabsq (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;
+}
--- /dev/null
+/* { 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_copysignq (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;
+}
--- /dev/null
+/* { 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_infq ();
+
+ 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_valq ();
+
+ 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;
+}
--- /dev/null
+/* { 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_nanq ("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_nanq ("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_nansq ("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_nansq ("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;
+}