Support type _Float16/__bf16 independent of SSE2.
Enable _Float16 and __bf16 all the time but issue errors when the types are used in conversion, unary operation, binary operation, parameter passing or value return when TARGET_SSE2 is not available. Also undef macros which are used by libgcc/libstdc++ to check the backend support of the _Float16/__bf16 types when TARGET_SSE2 is not available. gcc/ChangeLog: PR target/109504 * config/i386/i386-builtins.cc (ix86_register_float16_builtin_type): Remove TARGET_SSE2. (ix86_register_bf16_builtin_type): Ditto. * config/i386/i386-c.cc (ix86_target_macros): When TARGET_SSE2 isn't available, undef the macros which are used to check the backend support of the _Float16/__bf16 types when building libstdc++ and libgcc. * config/i386/i386.cc (construct_container): Issue errors for HFmode/BFmode when TARGET_SSE2 is not available. (function_value_32): Ditto. (ix86_scalar_mode_supported_p): Remove TARGET_SSE2 for HFmode/BFmode. (ix86_libgcc_floating_mode_supported_p): Ditto. (ix86_emit_support_tinfos): Adjust codes. (ix86_invalid_conversion): Return diagnostic message string when there's conversion from/to BF/HFmode w/o TARGET_SSE2. (ix86_invalid_unary_op): New function. (ix86_invalid_binary_op): Ditto. (TARGET_INVALID_UNARY_OP): Define. (TARGET_INVALID_BINARY_OP): Define. * config/i386/immintrin.h [__SSE2__]: Remove for fp16/bf16 related instrinsics header files. * config/i386/i386.h (VALID_SSE2_TYPE_MODE): New macro. gcc/testsuite/ChangeLog: * gcc.target/i386/pr109504.c: New test. * gcc.target/i386/sse2-bfloat16-1.c: Adjust error info. * gcc.target/i386/sse2-float16-1.c: Ditto. * gcc.target/i386/sse2-float16-4.c: New test. * gcc.target/i386/sse2-float16-5.c: New test. * g++.target/i386/float16-1.C: Adjust error info. libgcc/ChangeLog: * config/i386/t-softfp: Add -msse2 to libbid HFtype related files.
This commit is contained in:
parent
ec84261161
commit
9a19fa8b61
12 changed files with 206 additions and 32 deletions
|
@ -1376,7 +1376,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");
|
||||
}
|
||||
|
@ -1394,7 +1394,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");
|
||||
}
|
||||
|
||||
|
|
|
@ -832,6 +832,21 @@ 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 (TARGET_LONG_DOUBLE_64)
|
||||
cpp_define (parse_in, "__LONG_DOUBLE_64__");
|
||||
|
||||
|
|
|
@ -2661,7 +2661,8 @@ 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. */
|
||||
|
@ -2671,13 +2672,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;
|
||||
|
@ -4032,13 +4039,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;
|
||||
}
|
||||
|
@ -22786,14 +22806,35 @@ x86_emit_floatuns (rtx operands[2])
|
|||
}
|
||||
|
||||
/* Return the diagnostic message string if conversion from FROMTYPE to
|
||||
TOTYPE is not allowed, NULL otherwise.
|
||||
Currently it's used to warn for silent implicit conversion between __bf16
|
||||
and short, since __bfloat16 is refined as real __bf16 instead of short
|
||||
since GCC13. */
|
||||
TOTYPE is not allowed, NULL otherwise. */
|
||||
|
||||
static const char *
|
||||
ix86_invalid_conversion (const_tree fromtype, const_tree totype)
|
||||
{
|
||||
machine_mode from_mode = element_mode (fromtype);
|
||||
machine_mode to_mode = element_mode (totype);
|
||||
|
||||
if (!TARGET_SSE2 && from_mode != to_mode)
|
||||
{
|
||||
/* Do no allow conversions to/from BFmode/HFmode scalar types
|
||||
when TARGET_SSE2 is not available. */
|
||||
if (from_mode == BFmode)
|
||||
return N_("invalid conversion from type %<__bf16%> "
|
||||
"without option %<-msse2%>");
|
||||
if (from_mode == HFmode)
|
||||
return N_("invalid conversion from type %<_Float16%> "
|
||||
"without option %<-msse2%>");
|
||||
if (to_mode == BFmode)
|
||||
return N_("invalid conversion to type %<__bf16%> "
|
||||
"without option %<-msse2%>");
|
||||
if (to_mode == HFmode)
|
||||
return N_("invalid conversion to type %<_Float16%> "
|
||||
"without option %<-msse2%>");
|
||||
}
|
||||
|
||||
/* Warn for silent implicit conversion between __bf16 and short,
|
||||
since __bfloat16 is refined as real __bf16 instead of short
|
||||
since GCC13. */
|
||||
if (element_mode (fromtype) != element_mode (totype)
|
||||
&& (TARGET_AVX512BF16 || TARGET_AVXNECONVERT))
|
||||
{
|
||||
|
@ -22813,6 +22854,55 @@ ix86_invalid_conversion (const_tree fromtype, const_tree totype)
|
|||
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)
|
||||
{
|
||||
machine_mode mmode = element_mode (type);
|
||||
/* Reject all single-operand operations on BFmode/HFmode except for &
|
||||
when TARGET_SSE2 is not available. */
|
||||
if (!TARGET_SSE2 && op != ADDR_EXPR)
|
||||
{
|
||||
if (mmode == BFmode)
|
||||
return N_("operation not permitted on type %<__bf16%> "
|
||||
"without option %<-msse2%>");
|
||||
if (mmode == HFmode)
|
||||
return N_("operation not permitted on type %<_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)
|
||||
{
|
||||
machine_mode type1_mode = element_mode (type1);
|
||||
machine_mode type2_mode = element_mode (type2);
|
||||
/* Reject all 2-operand operations on BFmode or HFmode
|
||||
when TARGET_SSE2 is not available. */
|
||||
if (!TARGET_SSE2)
|
||||
{
|
||||
if (type1_mode == BFmode || type2_mode == BFmode)
|
||||
return N_("operation not permitted on type %<__bf16%> "
|
||||
"without option %<-msse2%>");
|
||||
|
||||
if (type1_mode == HFmode || type2_mode == HFmode)
|
||||
return N_("operation not permitted on type %<_Float16%> "
|
||||
"without option %<-msse2%>");
|
||||
}
|
||||
|
||||
/* Operation allowed. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Target hook for scalar_mode_supported_p. */
|
||||
static bool
|
||||
|
@ -22822,7 +22912,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);
|
||||
|
@ -22838,7 +22928,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));
|
||||
}
|
||||
|
@ -23168,9 +23258,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;
|
||||
if (!float16_type_node)
|
||||
float16_type_node = ix86_float16_type_node;
|
||||
if (!bfloat16_type_node)
|
||||
bfloat16_type_node = ix86_bf16_type_node;
|
||||
callback (float16_type_node);
|
||||
callback (bfloat16_type_node);
|
||||
float16_type_node = NULL_TREE;
|
||||
|
@ -25107,6 +25198,12 @@ ix86_run_selftests (void)
|
|||
#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_COMP_TYPE_ATTRIBUTES
|
||||
#define TARGET_COMP_TYPE_ATTRIBUTES ix86_comp_type_attributes
|
||||
|
||||
|
|
|
@ -1047,6 +1047,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 \
|
||||
|
|
|
@ -100,11 +100,9 @@
|
|||
|
||||
#include <avx512vp2intersectvlintrin.h>
|
||||
|
||||
#ifdef __SSE2__
|
||||
#include <avx512fp16intrin.h>
|
||||
|
||||
#include <avx512fp16vlintrin.h>
|
||||
#endif
|
||||
|
||||
#include <shaintrin.h>
|
||||
|
||||
|
@ -126,13 +124,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 } } */
|
||||
}
|
||||
|
|
6
gcc/testsuite/gcc.target/i386/pr109504.c
Normal file
6
gcc/testsuite/gcc.target/i386/pr109504.c
Normal file
|
@ -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} } */
|
||||
}
|
||||
|
|
25
gcc/testsuite/gcc.target/i386/sse2-float16-4.c
Normal file
25
gcc/testsuite/gcc.target/i386/sse2-float16-4.c
Normal file
|
@ -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;
|
||||
}
|
24
gcc/testsuite/gcc.target/i386/sse2-float16-5.c
Normal file
24
gcc/testsuite/gcc.target/i386/sse2-float16-5.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -31,3 +31,10 @@ CFLAGS-trunchfbf2.c += -msse2
|
|||
CFLAGS-eqhf2.c += -msse2
|
||||
CFLAGS-_divhc3.c += -msse2
|
||||
CFLAGS-_mulhc3.c += -msse2
|
||||
|
||||
CFLAGS-_hf_to_sd.c += -msse2
|
||||
CFLAGS-_hf_to_dd.c += -msse2
|
||||
CFLAGS-_hf_to_td.c += -msse2
|
||||
CFLAGS-_sd_to_hf.c += -msse2
|
||||
CFLAGS-_dd_to_hf.c += -msse2
|
||||
CFLAGS-_td_to_hf.c += -msse2
|
||||
|
|
Loading…
Add table
Reference in a new issue