summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-10-14 09:37:01 +0200
committerJakub Jelinek <jakub@redhat.com>2022-10-14 09:37:01 +0200
commitc2565a31c1622ab0926aeef4a6579413e121b9f9 (patch)
tree0182fba3c78ebcdc1d59f6c1ca9605ee62da6fd2
parent16ec267063c8ce60769888d4097bcd158410adc8 (diff)
downloadgcc-c2565a31c1622ab0926aeef4a6579413e121b9f9.tar.gz
middle-end, c++, i386, libgcc: std::bfloat16_t and __bf16 arithmetic support
Here is a complete patch to add std::bfloat16_t support on x86 (AArch64 and ARM left for later). Almost no BFmode optabs are added by the patch, so for binops/unops it extends to SFmode first and then truncates back to BFmode. For {HF,SF,DF,XF,TF}mode -> BFmode conversions libgcc has implementations of all those conversions so that we avoid double rounding, for BFmode -> {DF,XF,TF}mode conversions to avoid growing libgcc too much it emits BFmode -> SFmode conversion first and then converts to the even wider mode, neither step should be imprecise. For BFmode -> HFmode, it first emits a precise BFmode -> SFmode conversion and then SFmode -> HFmode, because neither format is subset or superset of the other, while SFmode is superset of both. expr.cc then contains a -ffast-math optimization of the BF -> SF and SF -> BF conversions if we don't optimize for space (and for the latter if -frounding-math isn't enabled either). For x86, perhaps truncsfbf2 optab could be defined for TARGET_AVX512BF16 but IMNSHO should FAIL if !flag_finite_math || flag_rounding_math || !flag_unsafe_math_optimizations, because I think the insn doesn't raise on sNaNs, hardcodes round to nearest and flushes denormals to zero. By default (unless x86 -fexcess-precision=16) we use float excess precision for BFmode, so truncate only on explicit casts and assignments. The patch introduces a single __bf16 builtin - __builtin_nansf16b, because (__bf16) __builtin_nansf ("") will drop the sNaN into qNaN, and uses f16b suffix instead of bf16 because there would be ambiguity on log vs. logb - __builtin_logbf16 could be either log with bf16 suffix or logb with f16 suffix. In other cases libstdc++ should mostly use __builtin_*f for std::bfloat16_t overloads (we have a problem with std::nextafter though but that one we have also for std::float16_t). 2022-10-14 Jakub Jelinek <jakub@redhat.com> gcc/ * tree-core.h (enum tree_index): Add TI_BFLOAT16_TYPE. * tree.h (bfloat16_type_node): Define. * tree.cc (excess_precision_type): Promote bfloat16_type_mode like float16_type_mode. (build_common_tree_nodes): Initialize bfloat16_type_node if BFmode is supported. * expmed.h (maybe_expand_shift): Declare. * expmed.cc (maybe_expand_shift): No longer static. * expr.cc (convert_mode_scalar): Don't ICE on BF -> HF or HF -> BF conversions. If there is no optab, handle BF -> {DF,XF,TF,HF} conversions as separate BF -> SF -> {DF,XF,TF,HF} conversions, add -ffast-math generic implementation for BF -> SF and SF -> BF conversions. * builtin-types.def (BT_BFLOAT16, BT_FN_BFLOAT16_CONST_STRING): New. * builtins.def (BUILT_IN_NANSF16B): New builtin. * fold-const-call.cc (fold_const_call): Handle CFN_BUILT_IN_NANSF16B. * config/i386/i386.cc (classify_argument): Handle E_BCmode. (ix86_libgcc_floating_mode_supported_p): Also return true for BFmode for -msse2. (ix86_mangle_type): Mangle BFmode as DF16b. (ix86_invalid_conversion, ix86_invalid_unary_op, ix86_invalid_binary_op): Remove. (TARGET_INVALID_CONVERSION, TARGET_INVALID_UNARY_OP, TARGET_INVALID_BINARY_OP): Don't redefine. * config/i386/i386-builtins.cc (ix86_bf16_type_node): Remove. (ix86_register_bf16_builtin_type): Use bfloat16_type_node rather than ix86_bf16_type_node, only create it if still NULL. * config/i386/i386-builtin-types.def (BFLOAT16): Likewise. * config/i386/i386.md (cbranchbf4, cstorebf4): New expanders. gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): If bfloat16_type_node, predefine __BFLT16_*__ macros and for C++23 also __STDCPP_BFLOAT16_T__. Predefine bfloat16_type_node related macros for -fbuilding-libgcc. * c-lex.cc (interpret_float): Handle CPP_N_BFLOAT16. gcc/c/ * c-typeck.cc (convert_arguments): Don't promote __bf16 to double. gcc/cp/ * cp-tree.h (extended_float_type_p): Return true for bfloat16_type_node. * typeck.cc (cp_compare_floating_point_conversion_ranks): Set extended{1,2} if mv{1,2} is bfloat16_type_node. Adjust comment. gcc/testsuite/ * lib/target-supports.exp (check_effective_target_bfloat16, check_effective_target_bfloat16_runtime, add_options_for_bfloat16): New. * gcc.dg/torture/bfloat16-basic.c: New test. * gcc.dg/torture/bfloat16-builtin.c: New test. * gcc.dg/torture/bfloat16-builtin-issignaling-1.c: New test. * gcc.dg/torture/bfloat16-complex.c: New test. * gcc.dg/torture/builtin-issignaling-1.c: Allow to be includable from bfloat16-builtin-issignaling-1.c. * gcc.dg/torture/floatn-basic.h: Allow to be includable from bfloat16-basic.c. * gcc.target/i386/vect-bfloat16-typecheck_2.c: Adjust expected diagnostics. * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Likewise. * gcc.target/i386/vect-bfloat16-typecheck_1.c: Likewise. * g++.target/i386/bfloat_cpp_typecheck.C: Likewise. libcpp/ * include/cpplib.h (CPP_N_BFLOAT16): Define. * expr.cc (interpret_float_suffix): Handle bf16 and BF16 suffixes for C++. libgcc/ * config/i386/t-softfp (softfp_extensions): Add bfsf. (softfp_truncations): Add tfbf xfbf dfbf sfbf hfbf. (CFLAGS-extendbfsf2.c, CFLAGS-truncsfbf2.c, CFLAGS-truncdfbf2.c, CFLAGS-truncxfbf2.c, CFLAGS-trunctfbf2.c, CFLAGS-trunchfbf2.c): Add -msse2. * config/i386/libgcc-glibc.ver (GCC_13.0.0): Export __extendbfsf2 and __trunc{s,d,x,t,h}fbf2. * config/i386/sfp-machine.h (_FP_NANSIGN_B): Define. * config/i386/64/sfp-machine.h (_FP_NANFRAC_B): Define. * config/i386/32/sfp-machine.h (_FP_NANFRAC_B): Define. * soft-fp/brain.h: New file. * soft-fp/truncsfbf2.c: New file. * soft-fp/truncdfbf2.c: New file. * soft-fp/truncxfbf2.c: New file. * soft-fp/trunctfbf2.c: New file. * soft-fp/trunchfbf2.c: New file. * soft-fp/truncbfhf2.c: New file. * soft-fp/extendbfsf2.c: New file. libiberty/ * cp-demangle.h (D_BUILTIN_TYPE_COUNT): Increment. * cp-demangle.c (cplus_demangle_builtin_types): Add std::bfloat16_t entry. (cplus_demangle_type): Demangle DF16b. * testsuite/demangle-expected (_Z3xxxDF16b): New test.
-rw-r--r--gcc/builtin-types.def4
-rw-r--r--gcc/builtins.def1
-rw-r--r--gcc/c-family/c-cppbuiltin.cc21
-rw-r--r--gcc/c-family/c-lex.cc16
-rw-r--r--gcc/c/c-typeck.cc3
-rw-r--r--gcc/config/i386/i386-builtin-types.def2
-rw-r--r--gcc/config/i386/i386-builtins.cc17
-rw-r--r--gcc/config/i386/i386.cc63
-rw-r--r--gcc/config/i386/i386.md81
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/typeck.cc8
-rw-r--r--gcc/expmed.cc2
-rw-r--r--gcc/expmed.h2
-rw-r--r--gcc/expr.cc150
-rw-r--r--gcc/fold-const-call.cc1
-rw-r--r--gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C4
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-basic.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c47
-rw-r--r--gcc/testsuite/gcc.dg/torture/bfloat16-complex.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c47
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-basic.h18
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c196
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c100
-rw-r--r--gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c98
-rw-r--r--gcc/testsuite/lib/target-supports.exp16
-rw-r--r--gcc/tree-core.h3
-rw-r--r--gcc/tree.cc26
-rw-r--r--gcc/tree.h1
-rw-r--r--libcpp/expr.cc23
-rw-r--r--libcpp/include/cpplib.h1
-rw-r--r--libgcc/config/i386/32/sfp-machine.h1
-rw-r--r--libgcc/config/i386/64/sfp-machine.h1
-rw-r--r--libgcc/config/i386/libgcc-glibc.ver10
-rw-r--r--libgcc/config/i386/sfp-machine.h1
-rw-r--r--libgcc/config/i386/t-softfp11
-rw-r--r--libgcc/soft-fp/brain.h172
-rw-r--r--libgcc/soft-fp/extendbfsf2.c49
-rw-r--r--libgcc/soft-fp/truncbfhf2.c75
-rw-r--r--libgcc/soft-fp/truncdfbf2.c52
-rw-r--r--libgcc/soft-fp/trunchfbf2.c58
-rw-r--r--libgcc/soft-fp/truncsfbf2.c48
-rw-r--r--libgcc/soft-fp/trunctfbf2.c52
-rw-r--r--libgcc/soft-fp/truncxfbf2.c52
-rw-r--r--libiberty/cp-demangle.c14
-rw-r--r--libiberty/cp-demangle.h2
-rw-r--r--libiberty/testsuite/demangle-expected4
47 files changed, 1339 insertions, 309 deletions
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 3a7cecdf087..df3a88f2cf3 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -82,6 +82,9 @@ 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_BFLOAT16, (bfloat16_type_node
+ ? bfloat16_type_node
+ : error_mark_node))
DEF_PRIMITIVE_TYPE (BT_FLOAT16, (float16_type_node
? float16_type_node
: error_mark_node))
@@ -264,6 +267,7 @@ 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_BFLOAT16_CONST_STRING, BT_BFLOAT16, 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)
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 109b3879220..5f2e627d68b 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -514,6 +514,7 @@ DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_
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_GCC_BUILTIN (BUILT_IN_NANSF16B, "nansf16b", BT_FN_BFLOAT16_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSD32, "nansd32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSD64, "nansd64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
DEF_GCC_BUILTIN (BUILT_IN_NANSD128, "nansd128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 2e39acb9239..cdb658f6ac9 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1260,6 +1260,13 @@ c_cpp_builtins (cpp_reader *pfile)
builtin_define_float_constants (prefix, ggc_strdup (csuffix), "%s",
csuffix, FLOATN_NX_TYPE_NODE (i));
}
+ if (bfloat16_type_node)
+ {
+ if (c_dialect_cxx () && cxx_dialect > cxx20)
+ cpp_define (pfile, "__STDCPP_BFLOAT16_T__=1");
+ builtin_define_float_constants ("BFLT16", "BF16", "%s",
+ "BF16", bfloat16_type_node);
+ }
/* For float.h. */
if (targetm.decimal_float_supported_p ())
@@ -1370,6 +1377,12 @@ c_cpp_builtins (cpp_reader *pfile)
suffix[0] = 'l';
memcpy (float_h_prefix, "LDBL", 5);
}
+ else if (bfloat16_type_node
+ && mode == TYPE_MODE (bfloat16_type_node))
+ {
+ memcpy (suffix, "bf16", 5);
+ memcpy (float_h_prefix, "BFLT16", 7);
+ }
else
{
bool found_suffix = false;
@@ -1396,22 +1409,28 @@ c_cpp_builtins (cpp_reader *pfile)
machine_mode float16_type_mode = (float16_type_node
? TYPE_MODE (float16_type_node)
: VOIDmode);
+ machine_mode bfloat16_type_mode = (bfloat16_type_node
+ ? TYPE_MODE (bfloat16_type_node)
+ : VOIDmode);
switch (targetm.c.excess_precision
(EXCESS_PRECISION_TYPE_IMPLICIT))
{
case FLT_EVAL_METHOD_UNPREDICTABLE:
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
excess_precision = (mode == float16_type_mode
+ || mode == bfloat16_type_mode
|| mode == TYPE_MODE (float_type_node)
|| mode == TYPE_MODE (double_type_node));
break;
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
excess_precision = (mode == float16_type_mode
+ || mode == bfloat16_type_mode
|| mode == TYPE_MODE (float_type_node));
break;
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
- excess_precision = mode == float16_type_mode;
+ excess_precision = (mode == float16_type_mode
+ || mode == bfloat16_type_mode);
break;
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
excess_precision = false;
diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
index 11f2b784738..89c65aca28a 100644
--- a/gcc/c-family/c-lex.cc
+++ b/gcc/c-family/c-lex.cc
@@ -1000,6 +1000,22 @@ interpret_float (const cpp_token *token, unsigned int flags,
pedwarn (input_location, OPT_Wpedantic,
"non-standard suffix on floating constant");
}
+ else if ((flags & CPP_N_BFLOAT16) != 0)
+ {
+ type = bfloat16_type_node;
+ if (type == NULL_TREE)
+ {
+ error ("unsupported non-standard suffix on floating constant");
+ return error_mark_node;
+ }
+ if (!c_dialect_cxx ())
+ pedwarn (input_location, OPT_Wpedantic,
+ "non-standard suffix on floating constant");
+ else if (cxx_dialect < cxx23)
+ pedwarn (input_location, OPT_Wpedantic,
+ "%<bf16%> or %<BF16%> suffix on floating constant only "
+ "available with %<-std=c++2b%> or %<-std=gnu++2b%>");
+ }
else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
type = long_double_type_node;
else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 017658070f4..fdb96c28c51 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -3678,6 +3678,9 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
promote_float_arg = false;
break;
}
+ /* Don't promote __bf16 either. */
+ if (TYPE_MAIN_VARIANT (valtype) == bfloat16_type_node)
+ promote_float_arg = false;
}
if (type != NULL_TREE)
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 63a360b0f8b..2c27a4e67b6 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -69,7 +69,7 @@ DEF_PRIMITIVE_TYPE (UINT16, short_unsigned_type_node)
DEF_PRIMITIVE_TYPE (INT64, long_long_integer_type_node)
DEF_PRIMITIVE_TYPE (UINT64, long_long_unsigned_type_node)
DEF_PRIMITIVE_TYPE (FLOAT16, ix86_float16_type_node)
-DEF_PRIMITIVE_TYPE (BFLOAT16, ix86_bf16_type_node)
+DEF_PRIMITIVE_TYPE (BFLOAT16, bfloat16_type_node)
DEF_PRIMITIVE_TYPE (FLOAT, float_type_node)
DEF_PRIMITIVE_TYPE (DOUBLE, double_type_node)
DEF_PRIMITIVE_TYPE (FLOAT80, float80_type_node)
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc
index b91aba18221..b5c651a1cab 100644
--- a/gcc/config/i386/i386-builtins.cc
+++ b/gcc/config/i386/i386-builtins.cc
@@ -126,7 +126,6 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX,
static GTY(()) tree ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1];
tree ix86_float16_type_node = NULL_TREE;
-tree ix86_bf16_type_node = NULL_TREE;
tree ix86_bf16_ptr_type_node = NULL_TREE;
/* Retrieve an element from the above table, building some of
@@ -1372,16 +1371,18 @@ ix86_register_float16_builtin_type (void)
static void
ix86_register_bf16_builtin_type (void)
{
- ix86_bf16_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (ix86_bf16_type_node) = 16;
- SET_TYPE_MODE (ix86_bf16_type_node, BFmode);
- layout_type (ix86_bf16_type_node);
+ if (bfloat16_type_node == NULL_TREE)
+ {
+ bfloat16_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (bfloat16_type_node) = 16;
+ SET_TYPE_MODE (bfloat16_type_node, BFmode);
+ layout_type (bfloat16_type_node);
+ }
if (!maybe_get_identifier ("__bf16") && TARGET_SSE2)
{
- lang_hooks.types.register_builtin_type (ix86_bf16_type_node,
- "__bf16");
- ix86_bf16_ptr_type_node = build_pointer_type (ix86_bf16_type_node);
+ lang_hooks.types.register_builtin_type (bfloat16_type_node, "__bf16");
+ ix86_bf16_ptr_type_node = build_pointer_type (bfloat16_type_node);
}
}
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index ff4de2d6dd5..480db35f6cd 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -2423,6 +2423,7 @@ classify_argument (machine_mode mode, const_tree type,
classes[1] = X86_64_SSEUP_CLASS;
return 2;
case E_HCmode:
+ case E_BCmode:
classes[0] = X86_64_SSE_CLASS;
if (!(bit_offset % 64))
return 1;
@@ -22428,7 +22429,7 @@ ix86_libgcc_floating_mode_supported_p (scalar_float_mode mode)
be defined by the C front-end for AVX512FP16 intrinsics. We will
issue an error in ix86_expand_move for HFmode if AVX512FP16 isn't
enabled. */
- return ((mode == HFmode && TARGET_SSE2)
+ return (((mode == HFmode || mode == BFmode) && TARGET_SSE2)
? true
: default_libgcc_floating_mode_supported_p (mode));
}
@@ -22731,7 +22732,7 @@ ix86_mangle_type (const_tree type)
switch (TYPE_MODE (type))
{
case E_BFmode:
- return "u6__bf16";
+ return "DF16b";
case E_HFmode:
/* _Float16 is "DF16_".
Align with clang's decision in https://reviews.llvm.org/D33719. */
@@ -22747,55 +22748,6 @@ ix86_mangle_type (const_tree type)
}
}
-/* Return the diagnostic message string if conversion from FROMTYPE to
- TOTYPE is not allowed, NULL otherwise. */
-
-static const char *
-ix86_invalid_conversion (const_tree fromtype, const_tree totype)
-{
- if (element_mode (fromtype) != element_mode (totype))
- {
- /* Do no allow conversions to/from BFmode scalar types. */
- if (TYPE_MODE (fromtype) == BFmode)
- return N_("invalid conversion from type %<__bf16%>");
- if (TYPE_MODE (totype) == BFmode)
- return N_("invalid conversion to type %<__bf16%>");
- }
-
- /* Conversion allowed. */
- return NULL;
-}
-
-/* Return the diagnostic message string if the unary operation OP is
- not permitted on TYPE, NULL otherwise. */
-
-static const char *
-ix86_invalid_unary_op (int op, const_tree type)
-{
- /* Reject all single-operand operations on BFmode except for &. */
- if (element_mode (type) == BFmode && op != ADDR_EXPR)
- return N_("operation not permitted on type %<__bf16%>");
-
- /* Operation allowed. */
- return NULL;
-}
-
-/* Return the diagnostic message string if the binary operation OP is
- not permitted on TYPE1 and TYPE2, NULL otherwise. */
-
-static const char *
-ix86_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
- const_tree type2)
-{
- /* Reject all 2-operand operations on BFmode. */
- if (element_mode (type1) == BFmode
- || element_mode (type2) == BFmode)
- return N_("operation not permitted on type %<__bf16%>");
-
- /* Operation allowed. */
- return NULL;
-}
-
static GTY(()) tree ix86_tls_stack_chk_guard_decl;
static tree
@@ -24853,15 +24805,6 @@ ix86_libgcc_floating_mode_supported_p
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE ix86_mangle_type
-#undef TARGET_INVALID_CONVERSION
-#define TARGET_INVALID_CONVERSION ix86_invalid_conversion
-
-#undef TARGET_INVALID_UNARY_OP
-#define TARGET_INVALID_UNARY_OP ix86_invalid_unary_op
-
-#undef TARGET_INVALID_BINARY_OP
-#define TARGET_INVALID_BINARY_OP ix86_invalid_binary_op
-
#undef TARGET_STACK_PROTECT_GUARD
#define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 8e847520491..6688d92b63c 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1644,6 +1644,48 @@
DONE;
})
+(define_expand "cbranchbf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:BF 1 "cmp_fp_expander_operand")
+ (match_operand:BF 2 "cmp_fp_expander_operand")))
+ (set (pc) (if_then_else
+ (match_operator 0 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)])
+ (label_ref (match_operand 3))
+ (pc)))]
+ ""
+{
+ rtx op1 = gen_lowpart (HImode, operands[1]);
+ if (CONST_INT_P (op1))
+ op1 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[1], BFmode);
+ else
+ {
+ rtx t1 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t1, op1));
+ emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
+ op1 = gen_lowpart (SFmode, t1);
+ }
+ rtx op2 = gen_lowpart (HImode, operands[2]);
+ if (CONST_INT_P (op2))
+ op2 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[2], BFmode);
+ else
+ {
+ rtx t2 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t2, op2));
+ emit_insn (gen_ashlsi3 (t2, t2, GEN_INT (16)));
+ op2 = gen_lowpart (SFmode, t2);
+ }
+ do_compare_rtx_and_jump (op1, op2, GET_CODE (operands[0]), 0,
+ SFmode, NULL_RTX, NULL,
+ as_a <rtx_code_label *> (operands[3]),
+ /* Unfortunately this isn't propagated. */
+ profile_probability::even ());
+ DONE;
+})
+
(define_expand "cstorehf4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:HF 2 "cmp_fp_expander_operand")
@@ -1659,6 +1701,45 @@
DONE;
})
+(define_expand "cstorebf4"
+ [(set (reg:CC FLAGS_REG)
+ (compare:CC (match_operand:BF 2 "cmp_fp_expander_operand")
+ (match_operand:BF 3 "cmp_fp_expander_operand")))
+ (set (match_operand:QI 0 "register_operand")
+ (match_operator 1 "comparison_operator"
+ [(reg:CC FLAGS_REG)
+ (const_int 0)]))]
+ ""
+{
+ rtx op1 = gen_lowpart (HImode, operands[2]);
+ if (CONST_INT_P (op1))
+ op1 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[2], BFmode);
+ else
+ {
+ rtx t1 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t1, op1));
+ emit_insn (gen_ashlsi3 (t1, t1, GEN_INT (16)));
+ op1 = gen_lowpart (SFmode, t1);
+ }
+ rtx op2 = gen_lowpart (HImode, operands[3]);
+ if (CONST_INT_P (op2))
+ op2 = simplify_const_unary_operation (FLOAT_EXTEND, SFmode,
+ operands[3], BFmode);
+ else
+ {
+ rtx t2 = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (t2, op2));
+ emit_insn (gen_ashlsi3 (t2, t2, GEN_INT (16)));
+ op2 = gen_lowpart (SFmode, t2);
+ }
+ rtx res = emit_store_flag_force (operands[0], GET_CODE (operands[1]),
+ op1, op2, SFmode, 0, 1);
+ if (!rtx_equal_p (res, operands[0]))
+ emit_move_insn (operands[0], res);
+ DONE;
+})
+
(define_expand "cstore<mode>4"
[(set (reg:CC FLAGS_REG)
(compare:CC (match_operand:MODEF 2 "cmp_fp_expander_operand")
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1534c875693..e2607f09c19 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8741,6 +8741,8 @@ extended_float_type_p (tree type)
for (int i = 0; i < NUM_FLOATN_NX_TYPES; ++i)
if (type == FLOATN_TYPE_NODE (i))
return true;
+ if (type == bfloat16_type_node)
+ return true;
return false;
}
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 634f60c1a96..da0e1427b97 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -293,6 +293,10 @@ cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
if (mv2 == FLOATN_NX_TYPE_NODE (i))
extended2 = i + 1;
}
+ if (mv1 == bfloat16_type_node)
+ extended1 = true;
+ if (mv2 == bfloat16_type_node)
+ extended2 = true;
if (extended2 && !extended1)
{
int ret = cp_compare_floating_point_conversion_ranks (t2, t1);
@@ -390,7 +394,9 @@ cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
if (cnt > 1 && mv2 == long_double_type_node)
return -2;
/* Otherwise, they have equal rank, but extended types
- (other than std::bfloat16_t) have higher subrank. */
+ (other than std::bfloat16_t) have higher subrank.
+ std::bfloat16_t shouldn't have equal rank to any standard
+ floating point type. */
return 1;
}
diff --git a/gcc/expmed.cc b/gcc/expmed.cc
index 6f7f99ad514..323565fea34 100644
--- a/gcc/expmed.cc
+++ b/gcc/expmed.cc
@@ -2705,7 +2705,7 @@ expand_shift (enum tree_code code, machine_mode mode, rtx shifted,
/* Likewise, but return 0 if that cannot be done. */
-static rtx
+rtx
maybe_expand_shift (enum tree_code code, machine_mode mode, rtx shifted,
int amount, rtx target, int unsignedp)
{
diff --git a/gcc/expmed.h b/gcc/expmed.h
index 0b2538c4c6b..f50f3232ca0 100644
--- a/gcc/expmed.h
+++ b/gcc/expmed.h
@@ -707,6 +707,8 @@ extern rtx expand_variable_shift (enum tree_code, machine_mode,
rtx, tree, rtx, int);
extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
int);
+extern rtx maybe_expand_shift (enum tree_code, machine_mode, rtx, int, rtx,
+ int);
#ifdef GCC_OPTABS_H
extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
diff --git a/gcc/expr.cc b/gcc/expr.cc
index b897b6dc385..4c892d69249 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -344,7 +344,11 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
gcc_assert ((GET_MODE_PRECISION (from_mode)
!= GET_MODE_PRECISION (to_mode))
|| (DECIMAL_FLOAT_MODE_P (from_mode)
- != DECIMAL_FLOAT_MODE_P (to_mode)));
+ != DECIMAL_FLOAT_MODE_P (to_mode))
+ || (REAL_MODE_FORMAT (from_mode) == &arm_bfloat_half_format
+ && REAL_MODE_FORMAT (to_mode) == &ieee_half_format)
+ || (REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
+ && REAL_MODE_FORMAT (from_mode) == &ieee_half_format));
if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode))
/* Conversion between decimal float and binary float, same size. */
@@ -364,6 +368,150 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
return;
}
+#ifdef HAVE_SFmode
+ if (REAL_MODE_FORMAT (from_mode) == &arm_bfloat_half_format
+ && REAL_MODE_FORMAT (SFmode) == &ieee_single_format)
+ {
+ if (GET_MODE_PRECISION (to_mode) > GET_MODE_PRECISION (SFmode))
+ {
+ /* To cut down on libgcc size, implement
+ BFmode -> {DF,XF,TF}mode conversions by
+ BFmode -> SFmode -> {DF,XF,TF}mode conversions. */
+ rtx temp = gen_reg_rtx (SFmode);
+ convert_mode_scalar (temp, from, unsignedp);
+ convert_mode_scalar (to, temp, unsignedp);
+ return;
+ }
+ if (REAL_MODE_FORMAT (to_mode) == &ieee_half_format)
+ {
+ /* Similarly, implement BFmode -> HFmode as
+ BFmode -> SFmode -> HFmode conversion where SFmode
+ has superset of BFmode values. We don't need
+ to handle sNaNs by raising exception and turning
+ into into qNaN though, as that can be done in the
+ SFmode -> HFmode conversion too. */
+ rtx temp = gen_reg_rtx (SFmode);
+ int save_flag_finite_math_only = flag_finite_math_only;
+ flag_finite_math_only = true;
+ convert_mode_scalar (temp, from, unsignedp);
+ flag_finite_math_only = save_flag_finite_math_only;
+ convert_mode_scalar (to, temp, unsignedp);
+ return;
+ }
+ if (to_mode == SFmode
+ && !HONOR_NANS (from_mode)
+ && !HONOR_NANS (to_mode)
+ && optimize_insn_for_speed_p ())
+ {
+ /* If we don't expect sNaNs, for BFmode -> SFmode we can just
+ shift the bits up. */
+ machine_mode fromi_mode, toi_mode;
+ if (int_mode_for_size (GET_MODE_BITSIZE (from_mode),
+ 0).exists (&fromi_mode)
+ && int_mode_for_size (GET_MODE_BITSIZE (to_mode),
+ 0).exists (&toi_mode))
+ {
+ start_sequence ();
+ rtx fromi = lowpart_subreg (fromi_mode, from, from_mode);
+ rtx tof = NULL_RTX;
+ if (fromi)
+ {
+ rtx toi = gen_reg_rtx (toi_mode);
+ convert_mode_scalar (toi, fromi, 1);
+ toi
+ = maybe_expand_shift (LSHIFT_EXPR, toi_mode, toi,
+ GET_MODE_PRECISION (to_mode)
+ - GET_MODE_PRECISION (from_mode),
+ NULL_RTX, 1);
+ if (toi)
+ {
+ tof = lowpart_subreg (to_mode, toi, toi_mode);
+ if (tof)
+ emit_move_insn (to, tof);
+ }
+ }
+ insns = get_insns ();
+ end_sequence ();
+ if (tof)
+ {
+ emit_insn (insns);
+ return;
+ }
+ }
+ }
+ }
+ if (REAL_MODE_FORMAT (from_mode) == &ieee_single_format
+ && REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
+ && !HONOR_NANS (from_mode)
+ && !HONOR_NANS (to_mode)
+ && !flag_rounding_math
+ && optimize_insn_for_speed_p ())
+ {
+ /* If we don't expect qNaNs nor sNaNs and can assume rounding
+ to nearest, we can expand the conversion inline as
+ (fromi + 0x7fff + ((fromi >> 16) & 1)) >> 16. */
+ machine_mode fromi_mode, toi_mode;
+ if (int_mode_for_size (GET_MODE_BITSIZE (from_mode),
+ 0).exists (&fromi_mode)
+ && int_mode_for_size (GET_MODE_BITSIZE (to_mode),
+ 0).exists (&toi_mode))
+ {
+ start_sequence ();
+ rtx fromi = lowpart_subreg (fromi_mode, from, from_mode);
+ rtx tof = NULL_RTX;
+ do
+ {
+ if (!fromi)
+ break;
+ int shift = (GET_MODE_PRECISION (from_mode)
+ - GET_MODE_PRECISION (to_mode));
+ rtx temp1
+ = maybe_expand_shift (RSHIFT_EXPR, fromi_mode, fromi,
+ shift, NULL_RTX, 1);
+ if (!temp1)
+ break;
+ rtx temp2
+ = expand_binop (fromi_mode, and_optab, temp1, const1_rtx,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (!temp2)
+ break;
+ rtx temp3
+ = expand_binop (fromi_mode, add_optab, fromi,
+ gen_int_mode ((HOST_WIDE_INT_1U
+ << (shift - 1)) - 1,
+ fromi_mode), NULL_RTX,
+ 1, OPTAB_DIRECT);
+ if (!temp3)
+ break;
+ rtx temp4
+ = expand_binop (fromi_mode, add_optab, temp3, temp2,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ if (!temp4)
+ break;
+ rtx temp5 = maybe_expand_shift (RSHIFT_EXPR, fromi_mode,
+ temp4, shift, NULL_RTX, 1);
+ if (!temp5)
+ break;
+ rtx temp6 = lowpart_subreg (toi_mode, temp5, fromi_mode);
+ if (!temp6)
+ break;
+ tof = lowpart_subreg (to_mode, force_reg (toi_mode, temp6),
+ toi_mode);
+ if (tof)
+ emit_move_insn (to, tof);
+ }
+ while (0);
+ insns = get_insns ();
+ end_sequence ();
+ if (tof)
+ {
+ emit_insn (insns);
+ return;
+ }
+ }
+ }
+#endif
+
/* Otherwise use a libcall. */
libcall = convert_optab_libfunc (tab, to_mode, from_mode);
diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc
index 72953875414..7e0d6711ce2 100644
--- a/gcc/fold-const-call.cc
+++ b/gcc/fold-const-call.cc
@@ -1301,6 +1301,7 @@ fold_const_call (combined_fn fn, tree type, tree arg)
CASE_CFN_NANS:
CASE_FLT_FN_FLOATN_NX (CFN_BUILT_IN_NANS):
+ case CFN_BUILT_IN_NANSF16B:
case CFN_BUILT_IN_NANSD32:
case CFN_BUILT_IN_NANSD64:
case CFN_BUILT_IN_NANSD128:
diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
index b800a6d6680..256712937d4 100644
--- a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
+++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C
@@ -5,6 +5,6 @@ void foo (void)
{
__bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} } */
__bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type '__bf16'} } */
- __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } */
+ __bf16 (0x1234); /* { dg-bogus {invalid conversion to type '__bf16'} } */
+ __bf16 (0.1); /* { dg-bogus {invalid conversion to type '__bf16'} } */
}
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c b/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c
new file mode 100644
index 00000000000..09e54d4470a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-basic.c
@@ -0,0 +1,11 @@
+/* Test __bf16. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+#define TYPE __bf16
+#define CST(C) CONCAT (C, bf16)
+#define CSTU(C) CONCAT (C, BF16)
+
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c
new file mode 100644
index 00000000000..0e428db792b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin-issignaling-1.c
@@ -0,0 +1,21 @@
+/* Test __bf16 __builtin_issignaling. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target bfloat16_runtime } */
+/* { dg-additional-options "-fsignaling-nans" } */
+/* Workaround for PR57484 on ia32: */
+/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+
+#define TYPE __bf16
+#define CST(C) CONCAT (C, bf16)
+#define FN(F) CONCAT (F, f16b)
+#define NAN(x) ((__bf16) __builtin_nanf (x))
+#define INF ((__bf16) __builtin_inff ())
+#define EXT 0
+
+#include "builtin-issignaling-1.c"
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c
new file mode 100644
index 00000000000..ce02f6f8b5b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-builtin.c
@@ -0,0 +1,47 @@
+/* Test __bf16 built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-add-options ieee } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+extern void exit (int);
+extern void abort (void);
+
+extern __bf16 test_type;
+extern __typeof (__builtin_nansf16b ("")) test_type;
+
+volatile __bf16 inf_cst = (__bf16) __builtin_inff ();
+volatile __bf16 huge_val_cst = (__bf16) __builtin_huge_valf ();
+volatile __bf16 nan_cst = (__bf16) __builtin_nanf ("");
+volatile __bf16 nans_cst = __builtin_nansf16b ("");
+volatile __bf16 neg0 = -0.0bf16, neg1 = -1.0bf16, one = 1.0;
+
+int
+main (void)
+{
+ volatile __bf16 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 = __builtin_fabsf (neg1);
+ if (r != 1.0bf16)
+ abort ();
+ r = __builtin_copysignf (one, neg0);
+ if (r != neg1)
+ abort ();
+ r = __builtin_copysignf (inf_cst, neg1);
+ if (r != -huge_val_cst)
+ abort ();
+ r = __builtin_copysignf (-inf_cst, one);
+ if (r != huge_val_cst)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c
new file mode 100644
index 00000000000..fa27a774b62
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bfloat16-complex.c
@@ -0,0 +1,61 @@
+/* Test __bf16 complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+extern void exit (int);
+extern void abort (void);
+
+volatile __bf16 a = 1.0bf16;
+typedef _Complex float __cbf16 __attribute__((__mode__(__BC__)));
+volatile __cbf16 b = __builtin_complex (2.0bf16, 3.0bf16);
+volatile __cbf16 c = __builtin_complex (2.0bf16, 3.0bf16);
+volatile __cbf16 d = __builtin_complex (2.0bf16, 3.0bf16);
+
+__cbf16
+fn (__cbf16 arg)
+{
+ return arg / 4;
+}
+
+int
+main (void)
+{
+ volatile __cbf16 r;
+ if (b != c)
+ abort ();
+ if (b != d)
+ abort ();
+ r = a + b;
+ if (__real__ r != 3.0bf16 || __imag__ r != 3.0bf16)
+ abort ();
+ r += d;
+ if (__real__ r != 5.0bf16 || __imag__ r != 6.0bf16)
+ abort ();
+ r -= a;
+ if (__real__ r != 4.0bf16 || __imag__ r != 6.0bf16)
+ abort ();
+ r /= (a + a);
+ if (__real__ r != 2.0bf16 || __imag__ r != 3.0bf16)
+ abort ();
+ r *= (a + a);
+ if (__real__ r != 4.0bf16 || __imag__ r != 6.0bf16)
+ abort ();
+ r -= b;
+ if (__real__ r != 2.0bf16 || __imag__ r != 3.0bf16)
+ abort ();
+ r *= r;
+ if (__real__ r != -5.0bf16 || __imag__ r != 12.0bf16)
+ abort ();
+ /* Division may not be exact, so round result before comparing. */
+ r /= b;
+ r += __builtin_complex (100.0bf16, 100.0bf16);
+ r -= __builtin_complex (100.0bf16, 100.0bf16);
+ if (r != b)
+ abort ();
+ r = fn (r);
+ if (__real__ r != 0.5bf16 || __imag__ r != 0.75bf16)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c
index fddca6cdd21..60125b2b656 100644
--- a/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c
+++ b/gcc/testsuite/gcc.dg/torture/builtin-issignaling-1.c
@@ -4,7 +4,7 @@
/* Workaround for PR57484 on ia32: */
/* { dg-additional-options "-msse2 -mfpmath=sse" { target { ia32 && sse2_runtime } } } */
-#ifndef EXT
+#if !defined(EXT) && !defined(TYPE)
int
f1 (void)
{
@@ -41,31 +41,42 @@ f6 (long double x)
return __builtin_issignaling (x);
}
#else
-#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)
+#ifndef TYPE
+# 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)
+# 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
+#endif
+#ifndef NANS
+# define NANS(x) FN (__builtin_nans) (x)
+#endif
+#ifndef NAN
+# define NAN(x) FN (__builtin_nan) (x)
+#endif
+#ifndef INF
+# define INF FN (__builtin_inf) ()
#endif
int
f1 (void)
{
- return __builtin_issignaling (FN (__builtin_nans) (""));
+ return __builtin_issignaling (NANS (""));
}
int
f2 (void)
{
- return __builtin_issignaling (FN (__builtin_nan) (""));
+ return __builtin_issignaling (NAN (""));
}
int
@@ -118,10 +129,10 @@ main ()
if (!f6 (z))
__builtin_abort ();
#else
- if (f4 (w) || !f4 (FN (__builtin_nans) ("0x123")) || f4 (CST (42.0)) || f4 (FN (__builtin_nan) ("0x234"))
- || f4 (FN (__builtin_inf) ()) || f4 (-FN (__builtin_inf) ()) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0)))
+ if (f4 (w) || !f4 (NANS ("0x123")) || f4 (CST (42.0)) || f4 (NAN ("0x234"))
+ || f4 (INF) || f4 (-INF) || f4 (CST (-42.0)) || f4 (CST (-0.0)) || f4 (CST (0.0)))
__builtin_abort ();
- w = FN (__builtin_nans) ("");
+ w = NANS ("");
asm volatile ("" : : : "memory");
if (!f4 (w))
__builtin_abort ();
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-basic.h b/gcc/testsuite/gcc.dg/torture/floatn-basic.h
index 9131f46752c..6540b530994 100644
--- a/gcc/testsuite/gcc.dg/torture/floatn-basic.h
+++ b/gcc/testsuite/gcc.dg/torture/floatn-basic.h
@@ -9,14 +9,16 @@
#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 CSTU(C) CONCAT4 (C, F, WIDTH, x)
-#else
-# define TYPE CONCAT (_Float, WIDTH)
-# define CST(C) CONCAT3 (C, f, WIDTH)
-# define CSTU(C) CONCAT3 (C, F, WIDTH)
+#ifndef TYPE
+# if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define CSTU(C) CONCAT4 (C, F, WIDTH, x)
+# else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define CSTU(C) CONCAT3 (C, F, WIDTH)
+# endif
#endif
extern void exit (int);
diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
index 52b53b9ae85..d1a76db25e9 100644
--- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
+++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c
@@ -12,8 +12,8 @@ double is_a_double;
float *float_ptr;
-__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */
-__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */
+__bf16 foo1 (void) { return (__bf16) 0x1234; }
+__bf16 foo2 (void) { return (__bf16) (short) 0x1234; }
__bf16 footest (__bf16 scalar0)
{
@@ -22,87 +22,87 @@ __bf16 footest (__bf16 scalar0)
__bf16 scalar1_1;
__bf16 scalar1_2 = glob_bfloat;
- __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __bf16 scalar1_3 = 0;
+ __bf16 scalar1_4 = 0.1;
+ __bf16 scalar1_5 = is_a_float;
+ __bf16 scalar1_6 = is_an_int;
+ __bf16 scalar1_7 = is_a_float16;
+ __bf16 scalar1_8 = is_a_double;
+ __bf16 scalar1_9 = is_a_short_int;
+
+ int initi_1_1 = glob_bfloat;
+ float initi_1_2 = glob_bfloat;
+ _Float16 initi_1_3 = glob_bfloat;
+ short initi_1_4 = glob_bfloat;
+ double initi_1_5 = glob_bfloat;
__bf16 scalar2_1 = {};
__bf16 scalar2_2 = { glob_bfloat };
- __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __bf16 scalar2_3 = { 0 };
+ __bf16 scalar2_4 = { 0.1 };
+ __bf16 scalar2_5 = { is_a_float };
+ __bf16 scalar2_6 = { is_an_int };
+ __bf16 scalar2_7 = { is_a_float16 };
+ __bf16 scalar2_8 = { is_a_double };
+ __bf16 scalar2_9 = { is_a_short_int };
+
+ int initi_2_1 = { glob_bfloat };
+ float initi_2_2 = { glob_bfloat };
+ _Float16 initi_2_3 = { glob_bfloat };
+ short initi_2_4 = { glob_bfloat };
+ double initi_2_5 = { glob_bfloat };
/* Assignments. */
glob_bfloat = glob_bfloat;
- glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */
- glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
+ glob_bfloat = 0;
+ glob_bfloat = 0.1;
+ glob_bfloat = is_a_float;
+ glob_bfloat = is_an_int;
+ glob_bfloat = is_a_float16;
+ glob_bfloat = is_a_double;
+ glob_bfloat = is_a_short_int;
+
+ is_an_int = glob_bfloat;
+ is_a_float = glob_bfloat;
+ is_a_float16 = glob_bfloat;
+ is_a_double = glob_bfloat;
+ is_a_short_int = glob_bfloat;
/* Casting. */
(void) glob_bfloat;
(__bf16) glob_bfloat;
- (int) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (float) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (double) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
- (short) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */
+ (int) glob_bfloat;
+ (float) glob_bfloat;
+ (_Float16) glob_bfloat;
+ (double) glob_bfloat;
+ (short) glob_bfloat;
- (__bf16) is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
+ (__bf16) is_an_int;
+ (__bf16) is_a_float;
+ (__bf16) is_a_float16;
+ (__bf16) is_a_double;
+ (__bf16) is_a_short_int;
/* Compound literals. */
(__bf16) {};
(__bf16) { glob_bfloat };
- (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- (int) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (float) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (double) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- (short) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ (__bf16) { 0 };
+ (__bf16) { 0.1 };
+ (__bf16) { is_a_float };
+ (__bf16) { is_an_int };
+ (__bf16) { is_a_float16 };
+ (__bf16) { is_a_double };
+ (__bf16) { is_a_short_int };
+
+ (int) { glob_bfloat };
+ (float) { glob_bfloat };
+ (_Float16) { glob_bfloat };
+ (double) { glob_bfloat };
+ (short) { glob_bfloat };
/* Arrays and Structs. */
@@ -145,16 +145,16 @@ __bf16 footest (__bf16 scalar0)
bfloat_ptr = &bfloat_ptr3[1];
/* Simple comparison. */
- scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type '__bf16'} } */
- glob_bfloat == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_a_float == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0.1 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 > is_an_int; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_an_int == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ scalar0 > glob_bfloat;
+ glob_bfloat == scalar0;
+ scalar0 > is_a_float;
+ is_a_float == scalar0;
+ scalar0 > 0;
+ 0 == scalar0;
+ scalar0 > 0.1;
+ 0.1 == scalar0;
+ scalar0 > is_an_int;
+ is_an_int == scalar0;
/* Pointer comparison. */
@@ -174,41 +174,41 @@ __bf16 footest (__bf16 scalar0)
/* Conditional expressions. */
0 ? scalar0 : scalar0;
- 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type '__bf16'} } */
- 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */
- 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} } */
- 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */
- 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type '__bf16'} } */
+ 0 ? scalar0 : is_a_float;
+ 0 ? is_a_float : scalar0;
+ 0 ? scalar0 : 0;
+ 0 ? 0 : scalar0;
+ 0 ? 0.1 : scalar0;
+ 0 ? scalar0 : 0.1;
0 ? bfloat_ptr : bfloat_ptr2;
0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */
0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */
- scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
+ scalar0 ? scalar0 : scalar0;
+ scalar0 ? is_a_float : scalar0;
+ scalar0 ? scalar0 : is_a_float;
+ scalar0 ? is_a_float : is_a_float;
/* Unary operators. */
- +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- -scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ~scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- !scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ +scalar0;
+ -scalar0;
+ ~scalar0; /* { dg-error {wrong type argument to bit-complement} } */
+ !scalar0;
*scalar0; /* { dg-error {invalid type argument of unary '\*'} } */
- __real scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- __imag scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ++scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- --scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0--; /* { dg-error {operation not permitted on type '__bf16'} } */
+ __real scalar0;
+ __imag scalar0;
+ ++scalar0;
+ --scalar0;
+ scalar0++;
+ scalar0--;
/* Binary arithmetic operations. */
- scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */
+ scalar0 = glob_bfloat + *bfloat_ptr;
+ scalar0 = glob_bfloat + 0.1;
+ scalar0 = glob_bfloat + 0;
+ scalar0 = glob_bfloat + is_a_float;
return scalar0;
}
diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c
index 3804bac7220..8bc3f4a7b8f 100644
--- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c
+++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_1.c
@@ -48,20 +48,20 @@ __m128bf16 footest (__m128bf16 vector0)
__m128bf16 vector2_1 = {};
__m128bf16 vector2_2 = { glob_bfloat };
__m128bf16 vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
- __m128bf16 vector2_4 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m128bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
-
- __v8si initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256 initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m128h initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m128 initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __v4si initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __v4hi initi_2_6 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __m128bf16 vector2_4 = { 0 };
+ __m128bf16 vector2_5 = { 0.1 };
+ __m128bf16 vector2_6 = { is_a_float16 };
+ __m128bf16 vector2_7 = { is_a_float };
+ __m128bf16 vector2_8 = { is_an_int };
+ __m128bf16 vector2_9 = { is_a_short_int };
+ __m128bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float };
+
+ __v8si initi_2_1 = { glob_bfloat };
+ __m256 initi_2_2 = { glob_bfloat };
+ __m128h initi_2_3 = { glob_bfloat };
+ __m128 initi_2_4 = { glob_bfloat };
+ __v4si initi_2_5 = { glob_bfloat };
+ __v4hi initi_2_6 = { glob_bfloat };
/* Assignments to/from vectors. */
@@ -85,25 +85,25 @@ __m128bf16 footest (__m128bf16 vector0)
/* Assignments to/from elements. */
vector2_3[0] = glob_bfloat;
- vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
+ vector2_3[0] = is_an_int;
+ vector2_3[0] = is_a_short_int;
+ vector2_3[0] = is_a_float;
+ vector2_3[0] = is_a_float16;
+ vector2_3[0] = 0;
+ vector2_3[0] = 0.1;
glob_bfloat = vector2_3[0];
- is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
+ is_an_int = vector2_3[0];
+ is_a_short_int = vector2_3[0];
+ is_a_float = vector2_3[0];
+ is_a_float16 = vector2_3[0];
/* Compound literals. */
(__m128bf16) {};
- (__m128bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__m128bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
+ (__m128bf16) { 0 };
+ (__m128bf16) { 0.1 };
(__m128bf16) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256'} } */
(__m128bf16) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__v8si'} } */
(__m128bf16) { is_a_float_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m128'} } */
@@ -186,16 +186,16 @@ __m128bf16 footest (__m128bf16 vector0)
bfloat_ptr = &bfloat_ptr3[1];
/* Simple comparison. */
- vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_a_float_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0.1 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_an_int_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 > glob_bfloat_vec;
+ glob_bfloat_vec == vector0;
+ vector0 > is_a_float_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_a_float_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
+ vector0 > 0;
+ 0 == vector0;
+ vector0 > 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */
+ 0.1 == vector0; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */
+ vector0 > is_an_int_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_an_int_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
/* Pointer comparison. */
@@ -234,24 +234,24 @@ __m128bf16 footest (__m128bf16 vector0)
/* Unary operators. */
- +vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- -vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ~vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- !vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ +vector0;
+ -vector0;
+ ~vector0; /* { dg-error {wrong type argument to bit-complement} } */
+ !vector0; /* { dg-error {wrong type argument to unary exclamation mark} } */
*vector0; /* { dg-error {invalid type argument of unary '\*'} } */
- __real vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- __imag vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ++vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- --vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0++; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0--; /* { dg-error {operation not permitted on type '__bf16'} } */
+ __real vector0; /* { dg-error {wrong type argument to __real} } */
+ __imag vector0; /* { dg-error {wrong type argument to __imag} } */
+ ++vector0;
+ --vector0;
+ vector0++;
+ vector0--;
/* Binary arithmetic operations. */
- vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 = glob_bfloat_vec + *bfloat_ptr;
+ vector0 = glob_bfloat_vec + 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m128bf16'} } */
+ vector0 = glob_bfloat_vec + 0;
+ vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {invalid operands to binary \+} } */
return vector0;
}
diff --git a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c
index f63b41d832b..2a8a535daae 100644
--- a/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c
+++ b/gcc/testsuite/gcc.target/i386/vect-bfloat16-typecheck_2.c
@@ -45,19 +45,19 @@ __m256bf16 footest (__m256bf16 vector0)
__m256bf16 vector2_1 = {};
__m256bf16 vector2_2 = { glob_bfloat };
__m256bf16 vector2_3 = { glob_bfloat, glob_bfloat, glob_bfloat, glob_bfloat };
- __m256bf16 vector2_4 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_5 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_6 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_7 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_8 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */
- __m256bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float }; /* { dg-error "invalid conversion to type '__bf16'" } */
-
- __v8si initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256 initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256h initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __m256i initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
- __v16hi initi_2_6 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */
+ __m256bf16 vector2_4 = { 0 };
+ __m256bf16 vector2_5 = { 0.1 };
+ __m256bf16 vector2_6 = { is_a_float16 };
+ __m256bf16 vector2_7 = { is_a_float };
+ __m256bf16 vector2_8 = { is_an_int };
+ __m256bf16 vector2_9 = { is_a_short_int };
+ __m256bf16 vector2_10 = { 0.0, 0, is_a_short_int, is_a_float };
+
+ __v8si initi_2_1 = { glob_bfloat };
+ __m256 initi_2_2 = { glob_bfloat };
+ __m256h initi_2_3 = { glob_bfloat };
+ __m256i initi_2_5 = { glob_bfloat };
+ __v16hi initi_2_6 = { glob_bfloat };
/* Assignments to/from vectors. */
@@ -79,25 +79,25 @@ __m256bf16 footest (__m256bf16 vector0)
/* Assignments to/from elements. */
vector2_3[0] = glob_bfloat;
- vector2_3[0] = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0; /* { dg-error {invalid conversion to type '__bf16'} } */
- vector2_3[0] = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */
+ vector2_3[0] = is_an_int;
+ vector2_3[0] = is_a_short_int;
+ vector2_3[0] = is_a_float;
+ vector2_3[0] = is_a_float16;
+ vector2_3[0] = 0;
+ vector2_3[0] = 0.1;
glob_bfloat = vector2_3[0];
- is_an_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_short_int = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
- is_a_float16 = vector2_3[0]; /* { dg-error {invalid conversion from type '__bf16'} } */
+ is_an_int = vector2_3[0];
+ is_a_short_int = vector2_3[0];
+ is_a_float = vector2_3[0];
+ is_a_float16 = vector2_3[0];
/* Compound literals. */
(__m256bf16) {};
- (__m256bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */
- (__m256bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */
+ (__m256bf16) { 0 };
+ (__m256bf16) { 0.1 };
(__m256bf16) { is_a_float_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256'} } */
(__m256bf16) { is_an_int_vec }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__v8si'} } */
(__m256bf16) { is_a_long_int_pair }; /* { dg-error {incompatible types when initializing type '__bf16' using type '__m256i'} } */
@@ -176,16 +176,16 @@ __m256bf16 footest (__m256bf16 vector0)
bfloat_ptr = &bfloat_ptr3[1];
/* Simple comparison. */
- vector0 > glob_bfloat_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- glob_bfloat_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_a_float_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- 0.1 == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 > is_an_int_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
- is_an_int_vec == vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 > glob_bfloat_vec;
+ glob_bfloat_vec == vector0;
+ vector0 > is_a_float_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_a_float_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
+ vector0 > 0;
+ 0 == vector0;
+ vector0 > 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */
+ 0.1 == vector0; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */
+ vector0 > is_an_int_vec; /* { dg-error {comparing vectors with different element types} } */
+ is_an_int_vec == vector0; /* { dg-error {comparing vectors with different element types} } */
/* Pointer comparison. */
@@ -224,24 +224,24 @@ __m256bf16 footest (__m256bf16 vector0)
/* Unary operators. */
- +vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- -vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ~vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- !vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
+ +vector0;
+ -vector0;
+ ~vector0; /* { dg-error {wrong type argument to bit-complement} } */
+ !vector0; /* { dg-error {wrong type argument to unary exclamation mark} } */
*vector0; /* { dg-error {invalid type argument of unary '\*'} } */
- __real vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- __imag vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- ++vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- --vector0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0++; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0--; /* { dg-error {operation not permitted on type '__bf16'} } */
+ __real vector0; /* { dg-error {wrong type argument to __real} } */
+ __imag vector0; /* { dg-error {wrong type argument to __imag} } */
+ ++vector0;
+ --vector0;
+ vector0++;
+ vector0--;
/* Binary arithmetic operations. */
- vector0 = glob_bfloat_vec + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + 0; /* { dg-error {operation not permitted on type '__bf16'} } */
- vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {operation not permitted on type '__bf16'} } */
+ vector0 = glob_bfloat_vec + *bfloat_ptr;
+ vector0 = glob_bfloat_vec + 0.1; /* { dg-error {conversion of scalar 'double' to vector '__m256bf16'} } */
+ vector0 = glob_bfloat_vec + 0;
+ vector0 = glob_bfloat_vec + is_a_float_vec; /* { dg-error {invalid operands to binary \+} } */
return vector0;
}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index fdd88e6a516..8d45bc2427f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3416,6 +3416,22 @@ proc check_effective_target_base_quadfloat_support { } {
return 1
}
+# Return 1 if the target supports the __bf16 type, 0 otherwise.
+
+proc check_effective_target_bfloat16 {} {
+ return [check_no_compiler_messages_nocache bfloat16 object {
+ __bf16 foo (__bf16 x) { return x + x; }
+ } [add_options_for_bfloat16 ""]]
+}
+
+proc check_effective_target_bfloat16_runtime {} {
+ return [check_effective_target_bfloat16]
+}
+
+proc add_options_for_bfloat16 { flags } {
+ return "$flags"
+}
+
# Return 1 if the target supports all four forms of fused multiply-add
# (fma, fms, fnma, and fnms) for both float and double.
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index c4f2cea2352..80b886cc3e4 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -665,6 +665,9 @@ enum tree_index {
TI_DOUBLE_TYPE,
TI_LONG_DOUBLE_TYPE,
+ /* __bf16 type if supported (used in C++ as std::bfloat16_t). */
+ TI_BFLOAT16_TYPE,
+
/* The _FloatN and _FloatNx types must be consecutive, and in the
same sequence as the corresponding complex types, which must also
be consecutive; _FloatN must come before _FloatNx; the order must
diff --git a/gcc/tree.cc b/gcc/tree.cc
index c4ead94aa65..81a6ceaf181 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -7711,7 +7711,7 @@ excess_precision_type (tree type)
= (flag_excess_precision == EXCESS_PRECISION_FAST
? EXCESS_PRECISION_TYPE_FAST
: (flag_excess_precision == EXCESS_PRECISION_FLOAT16
- ? EXCESS_PRECISION_TYPE_FLOAT16 :EXCESS_PRECISION_TYPE_STANDARD));
+ ? EXCESS_PRECISION_TYPE_FLOAT16 : EXCESS_PRECISION_TYPE_STANDARD));
enum flt_eval_method target_flt_eval_method
= targetm.c.excess_precision (requested_type);
@@ -7736,6 +7736,9 @@ excess_precision_type (tree type)
machine_mode float16_type_mode = (float16_type_node
? TYPE_MODE (float16_type_node)
: VOIDmode);
+ machine_mode bfloat16_type_mode = (bfloat16_type_node
+ ? TYPE_MODE (bfloat16_type_node)
+ : VOIDmode);
machine_mode float_type_mode = TYPE_MODE (float_type_node);
machine_mode double_type_mode = TYPE_MODE (double_type_node);
@@ -7747,16 +7750,19 @@ excess_precision_type (tree type)
switch (target_flt_eval_method)
{
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
- if (type_mode == float16_type_mode)
+ if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode)
return float_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode)
return double_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode
|| type_mode == double_type_mode)
return long_double_type_node;
@@ -7774,16 +7780,19 @@ excess_precision_type (tree type)
switch (target_flt_eval_method)
{
case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
- if (type_mode == float16_type_mode)
+ if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode)
return complex_float_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode)
return complex_double_type_node;
break;
case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
if (type_mode == float16_type_mode
+ || type_mode == bfloat16_type_mode
|| type_mode == float_type_mode
|| type_mode == double_type_mode)
return complex_long_double_type_node;
@@ -9462,6 +9471,17 @@ build_common_tree_nodes (bool signed_char)
SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
}
float128t_type_node = float128_type_node;
+#ifdef HAVE_BFmode
+ if (REAL_MODE_FORMAT (BFmode) == &arm_bfloat_half_format
+ && targetm.scalar_mode_supported_p (BFmode)
+ && targetm.libgcc_floating_mode_supported_p (BFmode))
+ {
+ bfloat16_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (bfloat16_type_node) = GET_MODE_PRECISION (BFmode);
+ layout_type (bfloat16_type_node);
+ SET_TYPE_MODE (bfloat16_type_node, BFmode);
+ }
+#endif
float_ptr_type_node = build_pointer_type (float_type_node);
double_ptr_type_node = build_pointer_type (double_type_node);
diff --git a/gcc/tree.h b/gcc/tree.h
index 142e9c9d335..9af971cf401 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4291,6 +4291,7 @@ tree_strip_any_location_wrapper (tree exp)
#define float_type_node global_trees[TI_FLOAT_TYPE]
#define double_type_node global_trees[TI_DOUBLE_TYPE]
#define long_double_type_node global_trees[TI_LONG_DOUBLE_TYPE]
+#define bfloat16_type_node global_trees[TI_BFLOAT16_TYPE]
/* Nodes for particular _FloatN and _FloatNx types in sequence. */
#define FLOATN_TYPE_NODE(IDX) global_trees[TI_FLOATN_TYPE_FIRST + (IDX)]
diff --git a/libcpp/expr.cc b/libcpp/expr.cc
index 1d680643ad8..5ee28c4c853 100644
--- a/libcpp/expr.cc
+++ b/libcpp/expr.cc
@@ -91,10 +91,10 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
size_t orig_len = len;
const uchar *orig_s = s;
size_t flags;
- size_t f, d, l, w, q, i, fn, fnx, fn_bits;
+ size_t f, d, l, w, q, i, fn, fnx, fn_bits, bf16;
flags = 0;
- f = d = l = w = q = i = fn = fnx = fn_bits = 0;
+ f = d = l = w = q = i = fn = fnx = fn_bits = bf16 = 0;
/* The following decimal float suffixes, from TR 24732:2009, TS
18661-2:2015 and C2X, are supported:
@@ -131,7 +131,8 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
w, W - machine-specific type such as __float80 (GNU extension).
q, Q - machine-specific type such as __float128 (GNU extension).
fN, FN - _FloatN (TS 18661-3:2015).
- fNx, FNx - _FloatNx (TS 18661-3:2015). */
+ fNx, FNx - _FloatNx (TS 18661-3:2015).
+ bf16, BF16 - std::bfloat16_t (ISO C++23). */
/* Process decimal float suffixes, which are two letters starting
with d or D. Order and case are significant. */
@@ -239,6 +240,19 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
fn++;
}
break;
+ case 'b': case 'B':
+ if (len > 2
+ /* Except for bf16 / BF16 where case is significant. */
+ && s[1] == (s[0] == 'b' ? 'f' : 'F')
+ && s[2] == '1'
+ && s[3] == '6')
+ {
+ bf16++;
+ len -= 3;
+ s += 3;
+ break;
+ }
+ return 0;
case 'd': case 'D': d++; break;
case 'l': case 'L': l++; break;
case 'w': case 'W': w++; break;
@@ -257,7 +271,7 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
of N larger than can be represented in the return value. The
caller is responsible for rejecting _FloatN suffixes where
_FloatN is not supported on the chosen target. */
- if (f + d + l + w + q + fn + fnx > 1 || i > 1)
+ if (f + d + l + w + q + fn + fnx + bf16 > 1 || i > 1)
return 0;
if (fn_bits > CPP_FLOATN_MAX)
return 0;
@@ -295,6 +309,7 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
q ? CPP_N_MD_Q :
fn ? CPP_N_FLOATN | (fn_bits << CPP_FLOATN_SHIFT) :
fnx ? CPP_N_FLOATNX | (fn_bits << CPP_FLOATN_SHIFT) :
+ bf16 ? CPP_N_BFLOAT16 :
CPP_N_DEFAULT));
}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 2db1e9cbdfb..e97993e04bc 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -1275,6 +1275,7 @@ struct cpp_num
#define CPP_N_USERDEF 0x1000000 /* C++11 user-defined literal. */
#define CPP_N_SIZE_T 0x2000000 /* C++23 size_t literal. */
+#define CPP_N_BFLOAT16 0x4000000 /* std::bfloat16_t type. */
#define CPP_N_WIDTH_FLOATN_NX 0xF0000000 /* _FloatN / _FloatNx value
of N, divided by 16. */
diff --git a/libgcc/config/i386/32/sfp-machine.h b/libgcc/config/i386/32/sfp-machine.h
index e24cbc8d180..7b59ff5b909 100644
--- a/libgcc/config/i386/32/sfp-machine.h
+++ b/libgcc/config/i386/32/sfp-machine.h
@@ -87,6 +87,7 @@
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
#define _FP_NANFRAC_H _FP_QNANBIT_H
+#define _FP_NANFRAC_B _FP_QNANBIT_B
#define _FP_NANFRAC_S _FP_QNANBIT_S
#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
/* Even if XFmode is 12byte, we have to pad it to
diff --git a/libgcc/config/i386/64/sfp-machine.h b/libgcc/config/i386/64/sfp-machine.h
index e1c616699bb..1c8e8a50240 100644
--- a/libgcc/config/i386/64/sfp-machine.h
+++ b/libgcc/config/i386/64/sfp-machine.h
@@ -14,6 +14,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
#define _FP_NANFRAC_H _FP_QNANBIT_H
+#define _FP_NANFRAC_B _FP_QNANBIT_B
#define _FP_NANFRAC_S _FP_QNANBIT_S
#define _FP_NANFRAC_D _FP_QNANBIT_D
#define _FP_NANFRAC_E _FP_QNANBIT_E, 0
diff --git a/libgcc/config/i386/libgcc-glibc.ver b/libgcc/config/i386/libgcc-glibc.ver
index 08ce814bd7f..64c07d4f4c3 100644
--- a/libgcc/config/i386/libgcc-glibc.ver
+++ b/libgcc/config/i386/libgcc-glibc.ver
@@ -214,3 +214,13 @@ GCC_12.0.0 {
__trunctfhf2
__truncxfhf2
}
+
+%inherit GCC_13.0.0 GCC_12.0.0
+GCC_13.0.0 {
+ __extendbfsf2
+ __truncdfbf2
+ __truncsfbf2
+ __trunctfbf2
+ __truncxfbf2
+ __trunchfbf2
+}
diff --git a/libgcc/config/i386/sfp-machine.h b/libgcc/config/i386/sfp-machine.h
index c451ae71923..cc20c2c5f3e 100644
--- a/libgcc/config/i386/sfp-machine.h
+++ b/libgcc/config/i386/sfp-machine.h
@@ -18,6 +18,7 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
#define _FP_QNANNEGATEDP 0
#define _FP_NANSIGN_H 1
+#define _FP_NANSIGN_B 1
#define _FP_NANSIGN_S 1
#define _FP_NANSIGN_D 1
#define _FP_NANSIGN_E 1
diff --git a/libgcc/config/i386/t-softfp b/libgcc/config/i386/t-softfp
index fe2ad8a3c08..69d0f819822 100644
--- a/libgcc/config/i386/t-softfp
+++ b/libgcc/config/i386/t-softfp
@@ -6,8 +6,9 @@ LIB2FUNCS_EXCLUDE += $(libgcc2-hf-functions)
libgcc2-hf-extras = $(addsuffix .c, $(libgcc2-hf-functions))
LIB2ADD += $(addprefix $(srcdir)/config/i386/, $(libgcc2-hf-extras))
-softfp_extensions := hfsf hfdf hftf hfxf sfdf sftf dftf xftf
-softfp_truncations := tfhf xfhf dfhf sfhf tfsf dfsf tfdf tfxf
+softfp_extensions := hfsf hfdf hftf hfxf sfdf sftf dftf xftf bfsf
+softfp_truncations := tfhf xfhf dfhf sfhf tfsf dfsf tfdf tfxf \
+ tfbf xfbf dfbf sfbf hfbf
softfp_extras += eqhf2
@@ -15,11 +16,17 @@ CFLAGS-extendhfsf2.c += -msse2
CFLAGS-extendhfdf2.c += -msse2
CFLAGS-extendhftf2.c += -msse2
CFLAGS-extendhfxf2.c += -msse2
+CFLAGS-extendbfsf2.c += -msse2
CFLAGS-truncsfhf2.c += -msse2
CFLAGS-truncdfhf2.c += -msse2
CFLAGS-truncxfhf2.c += -msse2
CFLAGS-trunctfhf2.c += -msse2
+CFLAGS-truncsfbf2.c += -msse2
+CFLAGS-truncdfbf2.c += -msse2
+CFLAGS-truncxfbf2.c += -msse2
+CFLAGS-trunctfbf2.c += -msse2
+CFLAGS-trunchfbf2.c += -msse2
CFLAGS-eqhf2.c += -msse2
CFLAGS-_divhc3.c += -msse2
diff --git a/libgcc/soft-fp/brain.h b/libgcc/soft-fp/brain.h
new file mode 100644
index 00000000000..c8563ef8897
--- /dev/null
+++ b/libgcc/soft-fp/brain.h
@@ -0,0 +1,172 @@
+/* Software floating-point emulation.
+ Definitions for Brain Floating Point format (bfloat16).
+ Copyright (C) 1997-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef SOFT_FP_BRAIN_H
+#define SOFT_FP_BRAIN_H 1
+
+#if _FP_W_TYPE_SIZE < 32
+# error "Here's a nickel kid. Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACTBITS_B (_FP_W_TYPE_SIZE)
+
+#define _FP_FRACTBITS_DW_B (_FP_W_TYPE_SIZE)
+
+#define _FP_FRACBITS_B 8
+#define _FP_FRACXBITS_B (_FP_FRACTBITS_B - _FP_FRACBITS_B)
+#define _FP_WFRACBITS_B (_FP_WORKBITS + _FP_FRACBITS_B)
+#define _FP_WFRACXBITS_B (_FP_FRACTBITS_B - _FP_WFRACBITS_B)
+#define _FP_EXPBITS_B 8
+#define _FP_EXPBIAS_B 127
+#define _FP_EXPMAX_B 255
+
+#define _FP_QNANBIT_B ((_FP_W_TYPE) 1 << (_FP_FRACBITS_B-2))
+#define _FP_QNANBIT_SH_B ((_FP_W_TYPE) 1 << (_FP_FRACBITS_B-2+_FP_WORKBITS))
+#define _FP_IMPLBIT_B ((_FP_W_TYPE) 1 << (_FP_FRACBITS_B-1))
+#define _FP_IMPLBIT_SH_B ((_FP_W_TYPE) 1 << (_FP_FRACBITS_B-1+_FP_WORKBITS))
+#define _FP_OVERFLOW_B ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_B))
+
+#define _FP_WFRACBITS_DW_B (2 * _FP_WFRACBITS_B)
+#define _FP_WFRACXBITS_DW_B (_FP_FRACTBITS_DW_B - _FP_WFRACBITS_DW_B)
+#define _FP_HIGHBIT_DW_B \
+ ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_B - 1) % _FP_W_TYPE_SIZE)
+
+/* The implementation of _FP_MUL_MEAT_B and _FP_DIV_MEAT_B should be
+ chosen by the target machine. */
+
+typedef float BFtype __attribute__ ((mode (BF)));
+
+union _FP_UNION_B
+{
+ BFtype flt;
+ struct _FP_STRUCT_LAYOUT
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_B;
+ unsigned frac : _FP_FRACBITS_B - (_FP_IMPLBIT_B != 0);
+#else
+ unsigned frac : _FP_FRACBITS_B - (_FP_IMPLBIT_B != 0);
+ unsigned exp : _FP_EXPBITS_B;
+ unsigned sign : 1;
+#endif
+ } bits;
+};
+
+#define FP_DECL_B(X) _FP_DECL (1, X)
+#define FP_UNPACK_RAW_B(X, val) _FP_UNPACK_RAW_1 (B, X, (val))
+#define FP_UNPACK_RAW_BP(X, val) _FP_UNPACK_RAW_1_P (B, X, (val))
+#define FP_PACK_RAW_B(val, X) _FP_PACK_RAW_1 (B, (val), X)
+#define FP_PACK_RAW_BP(val, X) \
+ do \
+ { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (B, (val), X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_B(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1 (B, X, (val)); \
+ _FP_UNPACK_CANONICAL (B, 1, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_BP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1_P (B, X, (val)); \
+ _FP_UNPACK_CANONICAL (B, 1, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_SEMIRAW_B(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1 (B, X, (val)); \
+ _FP_UNPACK_SEMIRAW (B, 1, X); \
+ } \
+ while (0)
+
+#define FP_UNPACK_SEMIRAW_BP(X, val) \
+ do \
+ { \
+ _FP_UNPACK_RAW_1_P (B, X, (val)); \
+ _FP_UNPACK_SEMIRAW (B, 1, X); \
+ } \
+ while (0)
+
+#define FP_PACK_B(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (B, 1, X); \
+ _FP_PACK_RAW_1 (B, (val), X); \
+ } \
+ while (0)
+
+#define FP_PACK_BP(val, X) \
+ do \
+ { \
+ _FP_PACK_CANONICAL (B, 1, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (B, (val), X); \
+ } \
+ while (0)
+
+#define FP_PACK_SEMIRAW_B(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (B, 1, X); \
+ _FP_PACK_RAW_1 (B, (val), X); \
+ } \
+ while (0)
+
+#define FP_PACK_SEMIRAW_BP(val, X) \
+ do \
+ { \
+ _FP_PACK_SEMIRAW (B, 1, X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P (B, (val), X); \
+ } \
+ while (0)
+
+#define FP_TO_INT_B(r, X, rsz, rsg) _FP_TO_INT (B, 1, (r), X, (rsz), (rsg))
+#define FP_TO_INT_ROUND_B(r, X, rsz, rsg) \
+ _FP_TO_INT_ROUND (B, 1, (r), X, (rsz), (rsg))
+#define FP_FROM_INT_B(X, r, rs, rt) _FP_FROM_INT (B, 1, X, (r), (rs), rt)
+
+/* BFmode arithmetic is not implemented. */
+
+#define _FP_FRAC_HIGH_B(X) _FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_RAW_B(X) _FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_DW_B(X) _FP_FRAC_HIGH_1 (X)
+
+#define FP_CMP_EQ_B(r, X, Y, ex) _FP_CMP_EQ (B, 1, (r), X, Y, (ex))
+
+#endif /* !SOFT_FP_BRAIN_H */
diff --git a/libgcc/soft-fp/extendbfsf2.c b/libgcc/soft-fp/extendbfsf2.c
new file mode 100644
index 00000000000..c534a413ee6
--- /dev/null
+++ b/libgcc/soft-fp/extendbfsf2.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return an bfloat16 converted to IEEE single
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define FP_NO_EXACT_UNDERFLOW
+#include "soft-fp.h"
+#include "brain.h"
+#include "single.h"
+
+SFtype
+__extendbfsf2 (BFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_B (A);
+ FP_DECL_S (R);
+ SFtype r;
+
+ FP_INIT_EXCEPTIONS;
+ FP_UNPACK_RAW_B (A, a);
+ FP_EXTEND (S, B, 1, 1, R, A);
+ FP_PACK_RAW_S (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libgcc/soft-fp/truncbfhf2.c b/libgcc/soft-fp/truncbfhf2.c
new file mode 100644
index 00000000000..6b6e6b4fa65
--- /dev/null
+++ b/libgcc/soft-fp/truncbfhf2.c
@@ -0,0 +1,75 @@
+/* Software floating-point emulation.
+ Truncate bfloat16 into IEEE half.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "soft-fp.h"
+#include "half.h"
+#include "brain.h"
+#include "single.h"
+
+/* BFtype and HFtype are unordered, neither is a superset or subset
+ of each other. Convert BFtype to SFtype (lossless) and then
+ truncate to HFtype. */
+
+HFtype
+__truncbfhf2 (BFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_H (A);
+ FP_DECL_S (B);
+ FP_DECL_B (R);
+ SFtype b;
+ HFtype r;
+
+ FP_INIT_ROUNDMODE;
+ /* Optimize BFtype to SFtype conversion to simple left shift
+ by 16 if possible, we don't need to raise exceptions on sNaN
+ here as the SFtype to HFtype truncation should do that too. */
+ if (sizeof (BFtype) == 2
+ && sizeof (unsigned short) == 2
+ && sizeof (SFtype) == 4
+ && sizeof (unsigned int) == 4)
+ {
+ union { BFtype a; unsigned short b; } u1;
+ union { SFtype a; unsigned int b; } u2;
+ u1.a = a;
+ u2.b = (u1.b << 8) << 8;
+ b = u2.a;
+ }
+ else
+ {
+ FP_UNPACK_RAW_B (A, a);
+ FP_EXTEND (S, B, 1, 1, B, A);
+ FP_PACK_RAW_S (b, B);
+ }
+ FP_UNPACK_SEMIRAW_S (B, b);
+ FP_TRUNC (H, S, 1, 1, R, B);
+ FP_PACK_SEMIRAW_H (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libgcc/soft-fp/truncdfbf2.c b/libgcc/soft-fp/truncdfbf2.c
new file mode 100644
index 00000000000..dfa0b263514
--- /dev/null
+++ b/libgcc/soft-fp/truncdfbf2.c
@@ -0,0 +1,52 @@
+/* Software floating-point emulation.
+ Truncate IEEE double into bfloat16.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "soft-fp.h"
+#include "brain.h"
+#include "double.h"
+
+BFtype
+__truncdfbf2 (DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D (A);
+ FP_DECL_B (R);
+ BFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_D (A, a);
+#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
+ FP_TRUNC (B, D, 1, 2, R, A);
+#else
+ FP_TRUNC (B, D, 1, 1, R, A);
+#endif
+ FP_PACK_SEMIRAW_B (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libgcc/soft-fp/trunchfbf2.c b/libgcc/soft-fp/trunchfbf2.c
new file mode 100644
index 00000000000..f3d650123ef
--- /dev/null
+++ b/libgcc/soft-fp/trunchfbf2.c
@@ -0,0 +1,58 @@
+/* Software floating-point emulation.
+ Truncate IEEE half into bfloat16.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "soft-fp.h"
+#include "brain.h"
+#include "half.h"
+#include "single.h"
+
+/* BFtype and HFtype are unordered, neither is a superset or subset
+ of each other. Convert HFtype to SFtype (lossless) and then
+ truncate to BFtype. */
+
+BFtype
+__trunchfbf2 (HFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_H (A);
+ FP_DECL_S (B);
+ FP_DECL_B (R);
+ SFtype b;
+ BFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_RAW_H (A, a);
+ FP_EXTEND (S, H, 1, 1, B, A);
+ FP_PACK_RAW_S (b, B);
+ FP_UNPACK_SEMIRAW_S (B, b);
+ FP_TRUNC (B, S, 1, 1, R, B);
+ FP_PACK_SEMIRAW_B (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libgcc/soft-fp/truncsfbf2.c b/libgcc/soft-fp/truncsfbf2.c
new file mode 100644
index 00000000000..ccd90b6a107
--- /dev/null
+++ b/libgcc/soft-fp/truncsfbf2.c
@@ -0,0 +1,48 @@
+/* Software floating-point emulation.
+ Truncate IEEE single into bfloat16.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "soft-fp.h"
+#include "brain.h"
+#include "single.h"
+
+BFtype
+__truncsfbf2 (SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S (A);
+ FP_DECL_B (R);
+ BFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_S (A, a);
+ FP_TRUNC (B, S, 1, 1, R, A);
+ FP_PACK_SEMIRAW_B (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libgcc/soft-fp/trunctfbf2.c b/libgcc/soft-fp/trunctfbf2.c
new file mode 100644
index 00000000000..095c12ec2c3
--- /dev/null
+++ b/libgcc/soft-fp/trunctfbf2.c
@@ -0,0 +1,52 @@
+/* Software floating-point emulation.
+ Truncate IEEE quad into bfloat16.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include "soft-fp.h"
+#include "brain.h"
+#include "quad.h"
+
+BFtype
+__trunctfbf2 (TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q (A);
+ FP_DECL_B (R);
+ BFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q (A, a);
+#if _FP_W_TYPE_SIZE < 64
+ FP_TRUNC (B, Q, 1, 4, R, A);
+#else
+ FP_TRUNC (B, Q, 1, 2, R, A);
+#endif
+ FP_PACK_SEMIRAW_B (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libgcc/soft-fp/truncxfbf2.c b/libgcc/soft-fp/truncxfbf2.c
new file mode 100644
index 00000000000..fbff063be82
--- /dev/null
+++ b/libgcc/soft-fp/truncxfbf2.c
@@ -0,0 +1,52 @@
+/* Software floating-point emulation.
+ Truncate IEEE extended into bfloat16.
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser General Public
+ License, the Free Software Foundation gives you unlimited
+ permission to link the compiled version of this file into
+ combinations with other programs, and to distribute those
+ combinations without any restriction coming from the use of this
+ file. (The Lesser General Public License restrictions do apply in
+ other respects; for example, they cover modification of the file,
+ and distribution when not linked into a combine executable.)
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "soft-fp.h"
+#include "brain.h"
+#include "extended.h"
+
+BFtype
+__truncxfbf2 (XFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_E (A);
+ FP_DECL_B (R);
+ BFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_E (A, a);
+#if _FP_W_TYPE_SIZE < 64
+ FP_TRUNC (B, E, 1, 4, R, A);
+#else
+ FP_TRUNC (B, E, 1, 2, R, A);
+#endif
+ FP_PACK_SEMIRAW_B (r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 4beb4d257bb..8413dcdc785 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -2487,6 +2487,7 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
/* 33 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
D_PRINT_DEFAULT },
/* 34 */ { NL ("_Float"), NL ("_Float"), D_PRINT_FLOAT },
+ /* 35 */ { NL ("std::bfloat16_t"), NL ("std::bfloat16_t"), D_PRINT_FLOAT },
};
CP_STATIC_IF_GLIBCPP_V3
@@ -2751,11 +2752,22 @@ cplus_demangle_type (struct d_info *di)
case 'F':
/* DF<number>_ - _Float<number>.
- DF<number>x - _Float<number>x. */
+ DF<number>x - _Float<number>x
+ DF16b - std::bfloat16_t. */
{
int arg = d_number (di);
char buf[12];
char suffix = 0;
+ if (d_peek_char (di) == 'b')
+ {
+ if (arg != 16)
+ return NULL;
+ d_advance (di, 1);
+ ret = d_make_builtin_type (di,
+ &cplus_demangle_builtin_types[35]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+ }
if (d_peek_char (di) == 'x')
suffix = 'x';
if (!suffix && d_peek_char (di) != '_')
diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h
index c5d046b3f01..7f710be4a01 100644
--- a/libiberty/cp-demangle.h
+++ b/libiberty/cp-demangle.h
@@ -180,7 +180,7 @@ d_advance (struct d_info *di, int i)
extern const struct demangle_operator_info cplus_demangle_operators[];
#endif
-#define D_BUILTIN_TYPE_COUNT (35)
+#define D_BUILTIN_TYPE_COUNT (36)
CP_STATIC_IF_GLIBCPP_V3
const struct demangle_builtin_type_info
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index bd92b12076b..ee8fdfdd9cf 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1249,6 +1249,10 @@ xxx
_Z3xxxDF32xDF64xDF128xCDF32xVb
xxx(_Float32x, _Float64x, _Float128x, _Float32x _Complex, bool volatile)
xxx
+--format=auto --no-params
+_Z3xxxDF16b
+xxx(std::bfloat16_t)
+xxx
# https://sourceware.org/bugzilla/show_bug.cgi?id=16817
--format=auto --no-params
_QueueNotification_QueueController__$4PPPPPPPM_A_INotice___Z