@@ -1367,7 +1367,7 @@ ix86_register_float16_builtin_type (void)
else
ix86_float16_type_node = float16_type_node;
- if (!maybe_get_identifier ("_Float16") && TARGET_SSE2)
+ if (!maybe_get_identifier ("_Float16"))
lang_hooks.types.register_builtin_type (ix86_float16_type_node,
"_Float16");
}
@@ -1385,7 +1385,7 @@ ix86_register_bf16_builtin_type (void)
else
ix86_bf16_type_node = bfloat16_type_node;
- if (!maybe_get_identifier ("__bf16") && TARGET_SSE2)
+ if (!maybe_get_identifier ("__bf16"))
lang_hooks.types.register_builtin_type (ix86_bf16_type_node, "__bf16");
}
@@ -817,6 +817,43 @@ ix86_target_macros (void)
if (!TARGET_80387)
cpp_define (parse_in, "_SOFT_FLOAT");
+ /* HFmode/BFmode is supported without depending any isa
+ in scalar_mode_supported_p and libgcc_floating_mode_supported_p,
+ but according to psABI, they're really supported w/ SSE2 and above.
+ Since libstdc++ uses __STDCPP_FLOAT16_T__ and __STDCPP_BFLOAT16_T__
+ for backend support of the types, undef the macros to avoid
+ build failure, see PR109504. */
+ if (!TARGET_SSE2)
+ {
+ if (c_dialect_cxx ()
+ && cxx_dialect > cxx20)
+ {
+ cpp_undef (parse_in, "__STDCPP_FLOAT16_T__");
+ cpp_undef (parse_in, "__STDCPP_BFLOAT16_T__");
+ }
+
+ if (flag_building_libgcc)
+ {
+ /* libbid uses __LIBGCC_HAS_HF_MODE__ and __LIBGCC_HAS_BF_MODE__
+ to check backend support of _Float16 and __bf16 type. */
+ cpp_undef (parse_in, "__LIBGCC_HAS_HF_MODE__");
+ cpp_undef (parse_in, "__LIBGCC_HF_FUNC_EXT__");
+ cpp_undef (parse_in, "__LIBGCC_HF_MANT_DIG__");
+ cpp_undef (parse_in, "__LIBGCC_HF_EXCESS_PRECISION__");
+ cpp_undef (parse_in, "__LIBGCC_HF_EPSILON__");
+ cpp_undef (parse_in, "__LIBGCC_HF_MAX__");
+ cpp_undef (parse_in, "__LIBGCC_HF_MIN__");
+
+ cpp_undef (parse_in, "__LIBGCC_HAS_BF_MODE__");
+ cpp_undef (parse_in, "__LIBGCC_BF_FUNC_EXT__");
+ cpp_undef (parse_in, "__LIBGCC_BF_MANT_DIG__");
+ cpp_undef (parse_in, "__LIBGCC_BF_EXCESS_PRECISION__");
+ cpp_undef (parse_in, "__LIBGCC_BF_EPSILON__");
+ cpp_undef (parse_in, "__LIBGCC_BF_MAX__");
+ cpp_undef (parse_in, "__LIBGCC_BF_MIN__");
+ }
+ }
+
if (TARGET_LONG_DOUBLE_64)
cpp_define (parse_in, "__LONG_DOUBLE_64__");
@@ -2651,7 +2651,10 @@ construct_container (machine_mode mode, machine_mode orig_mode,
/* We allowed the user to turn off SSE for kernel mode. Don't crash if
some less clueful developer tries to use floating-point anyway. */
- if (needed_sseregs && !TARGET_SSE)
+ if (needed_sseregs
+ && (!TARGET_SSE
+ || (VALID_SSE2_TYPE_MODE (mode)
+ && !TARGET_SSE2)))
{
/* Return early if we shouldn't raise an error for invalid
calls. */
@@ -2661,13 +2664,19 @@ construct_container (machine_mode mode, machine_mode orig_mode,
{
if (!issued_sse_ret_error)
{
- error ("SSE register return with SSE disabled");
+ if (VALID_SSE2_TYPE_MODE (mode))
+ error ("SSE register return with SSE2 disabled");
+ else
+ error ("SSE register return with SSE disabled");
issued_sse_ret_error = true;
}
}
else if (!issued_sse_arg_error)
{
- error ("SSE register argument with SSE disabled");
+ if (VALID_SSE2_TYPE_MODE (mode))
+ error ("SSE register argument with SSE2 disabled");
+ else
+ error ("SSE register argument with SSE disabled");
issued_sse_arg_error = true;
}
return NULL;
@@ -4022,13 +4031,26 @@ function_value_32 (machine_mode orig_mode, machine_mode mode,
/* Return __bf16/ _Float16/_Complex _Foat16 by sse register. */
if (mode == HFmode || mode == BFmode)
- regno = FIRST_SSE_REG;
+ {
+ if (!TARGET_SSE2)
+ {
+ error ("SSE register return with SSE2 disabled");
+ regno = AX_REG;
+ }
+ else
+ regno = FIRST_SSE_REG;
+ }
+
if (mode == HCmode)
{
+ if (!TARGET_SSE2)
+ error ("SSE register return with SSE2 disabled");
+
rtx ret = gen_rtx_PARALLEL (mode, rtvec_alloc(1));
XVECEXP (ret, 0, 0)
= gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (SImode, FIRST_SSE_REG),
+ gen_rtx_REG (SImode,
+ TARGET_SSE2 ? FIRST_SSE_REG : AX_REG),
GEN_INT (0));
return ret;
}
@@ -22459,7 +22481,7 @@ ix86_scalar_mode_supported_p (scalar_mode mode)
return default_decimal_float_supported_p ();
else if (mode == TFmode)
return true;
- else if ((mode == HFmode || mode == BFmode) && TARGET_SSE2)
+ else if (mode == HFmode || mode == BFmode)
return true;
else
return default_scalar_mode_supported_p (mode);
@@ -22475,7 +22497,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 || mode == BFmode) && TARGET_SSE2)
+ return ((mode == HFmode || mode == BFmode)
? true
: default_libgcc_floating_mode_supported_p (mode));
}
@@ -22805,9 +22827,10 @@ ix86_emit_support_tinfos (emit_support_tinfos_callback callback)
if (!TARGET_SSE2)
{
- gcc_checking_assert (!float16_type_node && !bfloat16_type_node);
- float16_type_node = ix86_float16_type_node;
- bfloat16_type_node = ix86_bf16_type_node;
+ float16_type_node
+ = float16_type_node ? float16_type_node : ix86_float16_type_node;
+ bfloat16_type_node
+ = bfloat16_type_node ? bfloat16_type_node : ix86_bf16_type_node;
callback (float16_type_node);
callback (bfloat16_type_node);
float16_type_node = NULL_TREE;
@@ -24259,6 +24282,71 @@ ix86_init_libfuncs (void)
#endif
}
+/* 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/HFmode scalar types
+ when TARGET_SSE2 is not available. */
+ if ((TYPE_MODE (fromtype) == BFmode
+ || TYPE_MODE (fromtype) == HFmode)
+ && !TARGET_SSE2)
+ return N_("invalid conversion from type %<__bf16%> "
+ "or %<_Float16%> without option %<-msse2%>");
+
+ if ((TYPE_MODE (totype) == BFmode
+ || TYPE_MODE (totype) == HFmode)
+ && !TARGET_SSE2)
+ return N_("invalid conversion to type %<__bf16%> "
+ "or %<_Float16%> without option %<-msse2%>");
+ }
+
+ /* 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/HFmode except for &
+ when TARGET_SSE2 is not available. */
+ if ((element_mode (type) == BFmode || element_mode (type) == HFmode)
+ && !TARGET_SSE2 && op != ADDR_EXPR)
+ return N_("operation not permitted on type %<__bf16%> "
+ "or %<_Float16%> without option %<-msse2%>");
+
+ /* 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 or HFmode
+ when TARGET_SSE2 is not available. */
+ if ((element_mode (type1) == BFmode
+ || element_mode (type2) == BFmode
+ || element_mode (type1) == HFmode
+ || element_mode (type2) == HFmode)
+ && !TARGET_SSE2)
+ return N_("operation not permitted on type %<__bf16%> "
+ "or %<_Float16%> without option %<-msse2%>");
+
+ /* Operation allowed. */
+ return NULL;
+}
+
/* Set the value of FLT_EVAL_METHOD in float.h. When using only the
FPU, assume that the fpcw is set to extended precision; when using
only SSE, rounding is correct; when using both SSE and the FPU,
@@ -25248,6 +25336,15 @@ ix86_libgcc_floating_mode_supported_p
#undef TARGET_MEMTAG_TAG_SIZE
#define TARGET_MEMTAG_TAG_SIZE ix86_memtag_tag_size
+#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
+
static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
{
#ifdef OPTION_GLIBC
@@ -1046,6 +1046,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define VALID_AVX512FP16_REG_MODE(MODE) \
((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode)
+#define VALID_SSE2_TYPE_MODE(MODE) \
+ ((MODE) == HFmode || (MODE) == BFmode \
+ || (MODE) == HCmode || (MODE) == BCmode)
+
#define VALID_SSE2_REG_MODE(MODE) \
((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \
|| (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \
@@ -98,11 +98,9 @@
#include <avx512vp2intersectvlintrin.h>
-#ifdef __SSE2__
#include <avx512fp16intrin.h>
#include <avx512fp16vlintrin.h>
-#endif
#include <shaintrin.h>
@@ -118,13 +116,11 @@
#include <vpclmulqdqintrin.h>
-#ifdef __SSE2__
#include <avx512bf16vlintrin.h>
#include <avx512bf16intrin.h>
#include <avxneconvertintrin.h>
-#endif
#include <amxtileintrin.h>
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-_Float16 /* { dg-error "expected unqualified-id before '_Float16'" } */
-foo (_Float16 x)
+_Float16
+foo (_Float16 x)/* { dg-error "SSE register return with SSE2 disabled" } */
{
- return x;
-} /* { dg-error "'_Float16' is not supported on this target" } */
+ return x;/* { dg-error "SSE register return with SSE2 disabled" "" { target ia32 } } */
+}
new file mode 100644
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse" } */
+
+#pragma GCC target("sse4.1")
+#include <immintrin.h>
+int main(){return 0;}
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-__bf16/* { dg-error "unknown type name '__bf16'" } */
-foo (__bf16 x) /* { dg-error "unknown type name '__bf16'" } */
-{
- return x;
+__bf16
+foo (__bf16 x) /* { dg-error "SSE register return with SSE2 disabled" } */
+{ /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32 } } */
+ return x; /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32} } */
}
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-_Float16/* { dg-error "is not supported on this target" } */
-foo (_Float16 x) /* { dg-error "is not supported on this target" } */
-{
- return x;
+_Float16
+foo (_Float16 x) /* { dg-error "SSE register return with SSE2 disabled" } */
+{ /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32 } } */
+ return x; /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32} } */
}
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+_Float16 a;
+__bf16 c;
+_Complex _Float16 ac;
+
+void
+foo (_Float16* p)
+{
+ a = *p;
+}
+
+void
+foo1 (__bf16 *p)
+{
+ c = *p;
+}
+
+
+void
+foo2 (_Complex _Float16* p)
+{
+ ac = *p;
+}
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile { target ia32} } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+_Float16 a;
+__bf16 c;
+_Complex ac;
+void
+foo (_Float16 p)
+{
+ a = p;
+}
+
+void
+foo1 (__bf16 p)
+{
+ c = p;
+}
+
+
+void
+foo2 (_Complex p)
+{
+ ac = p;
+}