Message ID | 20230421135347.2519452-1-hongtao.liu@intel.com |
---|---|
State | New |
Headers | show |
Series | [1/2,i386] Support type _Float16/__bf16 independent of SSE2. | expand |
ping. On Fri, Apr 21, 2023 at 9:55 PM liuhongt <hongtao.liu@intel.com> wrote: > > > > + if (!TARGET_SSE2) > > > + { > > > + if (c_dialect_cxx () > > > + && cxx_dialect > cxx20) > > > > Formatting, both conditions are short, so just put them on one line. > Changed. > > > But for the C++23 macros, more importantly I think we really should > > also in ix86_target_macros_internal add > > if (c_dialect_cxx () > > && cxx_dialect > cxx20 > > && (isa_flag & OPTION_MASK_ISA_SSE2)) > > { > > def_or_undef (parse_in, "__STDCPP_FLOAT16_T__"); > > def_or_undef (parse_in, "__STDCPP_BFLOAT16_T__"); > > } > > plus associated libstdc++ changes. It can be done incrementally though. > Added in PATCH 2/2 > > > > + if (flag_building_libgcc) > > > + { > > > + /* libbid uses __LIBGCC_HAS_HF_MODE__ and __LIBGCC_HAS_BF_MODE__ > > > + to check backend support of _Float16 and __bf16 type. */ > > > > That is actually the case only for HFmode, but not for BFmode right now. > > So, we need further work. One is to add the BFmode support in there, > > and another one is make sure the _Float16 <-> _Decimal* and __bf16 <-> > > _Decimal* conversions are compiled in also if not -msse2 by default. > > One way to do that is wrap the HF and BF mode related functions on x86 > > #ifndef __SSE2__ into the pragmas like intrin headers use (but then > > perhaps we don't need to undef this stuff here), another is not provide > > the hf/bf support in that case from the TUs where they are provided now, > > but from a different one which would be compiled with -msse2. > Add CFLAGS-_hf_to_sd.c += -msse2, similar for other files in libbid, just like > we did before for HFtype softfp. Then no need to undef libgcc macros. > > > > /* 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))) > > > > Formatting, no need to split this up that much. > > if (needed_sseregs > > && (!TARGET_SSE > > || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > or even better > > if (needed_sseregs > > && (!TARGET_SSE || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > will do it. > Changed. > > > Instead of this, just use > > if (!float16_type_node) > > { > > float16_type_node = ix86_float16_type_node; > > callback (float16_type_node); > > float16_type_node = NULL_TREE; > > } > > if (!bfloat16_type_node) > > { > > bfloat16_type_node = ix86_bf16_type_node; > > callback (bfloat16_type_node); > > bfloat16_type_node = NULL_TREE; > > } > Changed. > > > > > +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) > > > > First of all, not really sure if this should be purely about scalar > > modes, not also complex and vector modes involving those inner modes. > > Because complex or vector modes with BF/HF elements will be without > > TARGET_SSE2 for sure lowered into scalar code and that can't be handled > > either. > > So if (!TARGET_SSE2 && GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode) > > or even better > > if (!TARGET_SSE2 && element_mode (fromtype) == BFmode) > > ? > > Or even better remember the 2 modes above into machine_mode temporaries > > and just use those in the != comparison and for the checks? > > > > Also, I think it is weird to tell user %<__bf16%> or %<_Float16%> when > > we know which one it is. Just return separate messages? > Changed. > > > > + /* 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%>"); > > > > Similarly. Also, check !TARGET_SSE2 first as inexpensive one. > Changed. > > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. > Successfully cross-build i686-linux-gnu. > Ok for trunk? > > 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): New function. > (ix86_invalid_unary_op): Ditto. > (ix86_invalid_binary_op): Ditto. > (TARGET_INVALID_CONVERSION): Define. > (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. > --- > gcc/config/i386/i386-builtins.cc | 4 +- > gcc/config/i386/i386-c.cc | 15 ++ > gcc/config/i386/i386.cc | 130 ++++++++++++++++-- > gcc/config/i386/i386.h | 4 + > gcc/config/i386/immintrin.h | 4 - > gcc/testsuite/g++.target/i386/float16-1.C | 8 +- > gcc/testsuite/gcc.target/i386/pr109504.c | 6 + > .../gcc.target/i386/sse2-bfloat16-1.c | 8 +- > .../gcc.target/i386/sse2-float16-1.c | 8 +- > .../gcc.target/i386/sse2-float16-4.c | 25 ++++ > .../gcc.target/i386/sse2-float16-5.c | 24 ++++ > libgcc/config/i386/t-softfp | 7 + > 12 files changed, 215 insertions(+), 28 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/i386/pr109504.c > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-4.c > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc > index fc0c82b156e..1cdabfd3a0a 100644 > --- a/gcc/config/i386/i386-builtins.cc > +++ b/gcc/config/i386/i386-builtins.cc > @@ -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"); > } > > diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc > index e7bd7cc706c..2f83c9981e1 100644 > --- a/gcc/config/i386/i386-c.cc > +++ b/gcc/config/i386/i386-c.cc > @@ -817,6 +817,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__"); > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > index fbd33a6bfd1..633a0f41e60 100644 > --- a/gcc/config/i386/i386.cc > +++ b/gcc/config/i386/i386.cc > @@ -2651,7 +2651,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. */ > @@ -2661,13 +2662,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 +4029,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 +22479,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 +22495,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 +22825,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; > @@ -24259,6 +24280,86 @@ 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) > +{ > + 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%>"); > + } > + > + /* 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) > +{ > + 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; > +} > + > /* 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 +25349,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 > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > index 1da6dce8e0b..7e839bc5c7e 100644 > --- a/gcc/config/i386/i386.h > +++ b/gcc/config/i386/i386.h > @@ -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 \ > diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h > index b220d871942..cc78df56940 100644 > --- a/gcc/config/i386/immintrin.h > +++ b/gcc/config/i386/immintrin.h > @@ -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> > > diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C > index f96b932b698..938852ee9ad 100644 > --- a/gcc/testsuite/g++.target/i386/float16-1.C > +++ b/gcc/testsuite/g++.target/i386/float16-1.C > @@ -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 } } */ > +} > diff --git a/gcc/testsuite/gcc.target/i386/pr109504.c b/gcc/testsuite/gcc.target/i386/pr109504.c > new file mode 100644 > index 00000000000..fe5bcda10ad > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr109504.c > @@ -0,0 +1,6 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -mno-sse" } */ > + > +#pragma GCC target("sse4.1") > +#include <immintrin.h> > +int main(){return 0;} > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > index 612d55be826..717055bc9ad 100644 > --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > @@ -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} } */ > } > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > index 1b645eb499d..faf818df75f 100644 > --- a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > @@ -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} } */ > } > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-4.c b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > new file mode 100644 > index 00000000000..64baf92ff56 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > @@ -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; > +} > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-5.c b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > new file mode 100644 > index 00000000000..c3ed23b8ab3 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > @@ -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; > +} > diff --git a/libgcc/config/i386/t-softfp b/libgcc/config/i386/t-softfp > index 69d0f819822..80d1fac121b 100644 > --- a/libgcc/config/i386/t-softfp > +++ b/libgcc/config/i386/t-softfp > @@ -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 > -- > 2.39.1.388.g2fc9e9ca3c >
I'd like to ping for this patch (only patch 1/2, for patch 2/2, I think that may not be necessary). On Mon, May 15, 2023 at 9:20 AM Hongtao Liu <crazylht@gmail.com> wrote: > > ping. > > On Fri, Apr 21, 2023 at 9:55 PM liuhongt <hongtao.liu@intel.com> wrote: > > > > > > + if (!TARGET_SSE2) > > > > + { > > > > + if (c_dialect_cxx () > > > > + && cxx_dialect > cxx20) > > > > > > Formatting, both conditions are short, so just put them on one line. > > Changed. > > > > > But for the C++23 macros, more importantly I think we really should > > > also in ix86_target_macros_internal add > > > if (c_dialect_cxx () > > > && cxx_dialect > cxx20 > > > && (isa_flag & OPTION_MASK_ISA_SSE2)) > > > { > > > def_or_undef (parse_in, "__STDCPP_FLOAT16_T__"); > > > def_or_undef (parse_in, "__STDCPP_BFLOAT16_T__"); > > > } > > > plus associated libstdc++ changes. It can be done incrementally though. > > Added in PATCH 2/2 > > > > > > + if (flag_building_libgcc) > > > > + { > > > > + /* libbid uses __LIBGCC_HAS_HF_MODE__ and __LIBGCC_HAS_BF_MODE__ > > > > + to check backend support of _Float16 and __bf16 type. */ > > > > > > That is actually the case only for HFmode, but not for BFmode right now. > > > So, we need further work. One is to add the BFmode support in there, > > > and another one is make sure the _Float16 <-> _Decimal* and __bf16 <-> > > > _Decimal* conversions are compiled in also if not -msse2 by default. > > > One way to do that is wrap the HF and BF mode related functions on x86 > > > #ifndef __SSE2__ into the pragmas like intrin headers use (but then > > > perhaps we don't need to undef this stuff here), another is not provide > > > the hf/bf support in that case from the TUs where they are provided now, > > > but from a different one which would be compiled with -msse2. > > Add CFLAGS-_hf_to_sd.c += -msse2, similar for other files in libbid, just like > > we did before for HFtype softfp. Then no need to undef libgcc macros. > > > > > > /* 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))) > > > > > > Formatting, no need to split this up that much. > > > if (needed_sseregs > > > && (!TARGET_SSE > > > || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > > or even better > > > if (needed_sseregs > > > && (!TARGET_SSE || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > > will do it. > > Changed. > > > > > Instead of this, just use > > > if (!float16_type_node) > > > { > > > float16_type_node = ix86_float16_type_node; > > > callback (float16_type_node); > > > float16_type_node = NULL_TREE; > > > } > > > if (!bfloat16_type_node) > > > { > > > bfloat16_type_node = ix86_bf16_type_node; > > > callback (bfloat16_type_node); > > > bfloat16_type_node = NULL_TREE; > > > } > > Changed. > > > > > > > > +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) > > > > > > First of all, not really sure if this should be purely about scalar > > > modes, not also complex and vector modes involving those inner modes. > > > Because complex or vector modes with BF/HF elements will be without > > > TARGET_SSE2 for sure lowered into scalar code and that can't be handled > > > either. > > > So if (!TARGET_SSE2 && GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode) > > > or even better > > > if (!TARGET_SSE2 && element_mode (fromtype) == BFmode) > > > ? > > > Or even better remember the 2 modes above into machine_mode temporaries > > > and just use those in the != comparison and for the checks? > > > > > > Also, I think it is weird to tell user %<__bf16%> or %<_Float16%> when > > > we know which one it is. Just return separate messages? > > Changed. > > > > > > + /* 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%>"); > > > > > > Similarly. Also, check !TARGET_SSE2 first as inexpensive one. > > Changed. > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. > > Successfully cross-build i686-linux-gnu. > > Ok for trunk? > > > > 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): New function. > > (ix86_invalid_unary_op): Ditto. > > (ix86_invalid_binary_op): Ditto. > > (TARGET_INVALID_CONVERSION): Define. > > (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. > > --- > > gcc/config/i386/i386-builtins.cc | 4 +- > > gcc/config/i386/i386-c.cc | 15 ++ > > gcc/config/i386/i386.cc | 130 ++++++++++++++++-- > > gcc/config/i386/i386.h | 4 + > > gcc/config/i386/immintrin.h | 4 - > > gcc/testsuite/g++.target/i386/float16-1.C | 8 +- > > gcc/testsuite/gcc.target/i386/pr109504.c | 6 + > > .../gcc.target/i386/sse2-bfloat16-1.c | 8 +- > > .../gcc.target/i386/sse2-float16-1.c | 8 +- > > .../gcc.target/i386/sse2-float16-4.c | 25 ++++ > > .../gcc.target/i386/sse2-float16-5.c | 24 ++++ > > libgcc/config/i386/t-softfp | 7 + > > 12 files changed, 215 insertions(+), 28 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/i386/pr109504.c > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > > diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc > > index fc0c82b156e..1cdabfd3a0a 100644 > > --- a/gcc/config/i386/i386-builtins.cc > > +++ b/gcc/config/i386/i386-builtins.cc > > @@ -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"); > > } > > > > diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc > > index e7bd7cc706c..2f83c9981e1 100644 > > --- a/gcc/config/i386/i386-c.cc > > +++ b/gcc/config/i386/i386-c.cc > > @@ -817,6 +817,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__"); > > > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > > index fbd33a6bfd1..633a0f41e60 100644 > > --- a/gcc/config/i386/i386.cc > > +++ b/gcc/config/i386/i386.cc > > @@ -2651,7 +2651,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. */ > > @@ -2661,13 +2662,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 +4029,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 +22479,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 +22495,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 +22825,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; > > @@ -24259,6 +24280,86 @@ 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) > > +{ > > + 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%>"); > > + } > > + > > + /* 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) > > +{ > > + 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; > > +} > > + > > /* 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 +25349,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 > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > > index 1da6dce8e0b..7e839bc5c7e 100644 > > --- a/gcc/config/i386/i386.h > > +++ b/gcc/config/i386/i386.h > > @@ -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 \ > > diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h > > index b220d871942..cc78df56940 100644 > > --- a/gcc/config/i386/immintrin.h > > +++ b/gcc/config/i386/immintrin.h > > @@ -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> > > > > diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C > > index f96b932b698..938852ee9ad 100644 > > --- a/gcc/testsuite/g++.target/i386/float16-1.C > > +++ b/gcc/testsuite/g++.target/i386/float16-1.C > > @@ -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 } } */ > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/pr109504.c b/gcc/testsuite/gcc.target/i386/pr109504.c > > new file mode 100644 > > index 00000000000..fe5bcda10ad > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/pr109504.c > > @@ -0,0 +1,6 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -mno-sse" } */ > > + > > +#pragma GCC target("sse4.1") > > +#include <immintrin.h> > > +int main(){return 0;} > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > index 612d55be826..717055bc9ad 100644 > > --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > @@ -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} } */ > > } > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > index 1b645eb499d..faf818df75f 100644 > > --- a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > @@ -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} } */ > > } > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-4.c b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > new file mode 100644 > > index 00000000000..64baf92ff56 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > @@ -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; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-5.c b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > new file mode 100644 > > index 00000000000..c3ed23b8ab3 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > @@ -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; > > +} > > diff --git a/libgcc/config/i386/t-softfp b/libgcc/config/i386/t-softfp > > index 69d0f819822..80d1fac121b 100644 > > --- a/libgcc/config/i386/t-softfp > > +++ b/libgcc/config/i386/t-softfp > > @@ -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 > > -- > > 2.39.1.388.g2fc9e9ca3c > > > > > -- > BR, > Hongtao
On Mon, Jul 17, 2023 at 10:28 AM Hongtao Liu <crazylht@gmail.com> wrote: > > I'd like to ping for this patch (only patch 1/2, for patch 2/2, I > think that may not be necessary). > > On Mon, May 15, 2023 at 9:20 AM Hongtao Liu <crazylht@gmail.com> wrote: > > > > ping. > > > > On Fri, Apr 21, 2023 at 9:55 PM liuhongt <hongtao.liu@intel.com> wrote: > > > > > > > > + if (!TARGET_SSE2) > > > > > + { > > > > > + if (c_dialect_cxx () > > > > > + && cxx_dialect > cxx20) > > > > > > > > Formatting, both conditions are short, so just put them on one line. > > > Changed. > > > > > > > But for the C++23 macros, more importantly I think we really should > > > > also in ix86_target_macros_internal add > > > > if (c_dialect_cxx () > > > > && cxx_dialect > cxx20 > > > > && (isa_flag & OPTION_MASK_ISA_SSE2)) > > > > { > > > > def_or_undef (parse_in, "__STDCPP_FLOAT16_T__"); > > > > def_or_undef (parse_in, "__STDCPP_BFLOAT16_T__"); > > > > } > > > > plus associated libstdc++ changes. It can be done incrementally though. > > > Added in PATCH 2/2 > > > > > > > > + if (flag_building_libgcc) > > > > > + { > > > > > + /* libbid uses __LIBGCC_HAS_HF_MODE__ and __LIBGCC_HAS_BF_MODE__ > > > > > + to check backend support of _Float16 and __bf16 type. */ > > > > > > > > That is actually the case only for HFmode, but not for BFmode right now. > > > > So, we need further work. One is to add the BFmode support in there, > > > > and another one is make sure the _Float16 <-> _Decimal* and __bf16 <-> > > > > _Decimal* conversions are compiled in also if not -msse2 by default. > > > > One way to do that is wrap the HF and BF mode related functions on x86 > > > > #ifndef __SSE2__ into the pragmas like intrin headers use (but then > > > > perhaps we don't need to undef this stuff here), another is not provide > > > > the hf/bf support in that case from the TUs where they are provided now, > > > > but from a different one which would be compiled with -msse2. > > > Add CFLAGS-_hf_to_sd.c += -msse2, similar for other files in libbid, just like > > > we did before for HFtype softfp. Then no need to undef libgcc macros. > > > > > > > > /* 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))) > > > > > > > > Formatting, no need to split this up that much. > > > > if (needed_sseregs > > > > && (!TARGET_SSE > > > > || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > > > or even better > > > > if (needed_sseregs > > > > && (!TARGET_SSE || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > > > will do it. > > > Changed. > > > > > > > Instead of this, just use > > > > if (!float16_type_node) > > > > { > > > > float16_type_node = ix86_float16_type_node; > > > > callback (float16_type_node); > > > > float16_type_node = NULL_TREE; > > > > } > > > > if (!bfloat16_type_node) > > > > { > > > > bfloat16_type_node = ix86_bf16_type_node; > > > > callback (bfloat16_type_node); > > > > bfloat16_type_node = NULL_TREE; > > > > } > > > Changed. > > > > > > > > > > > +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) > > > > > > > > First of all, not really sure if this should be purely about scalar > > > > modes, not also complex and vector modes involving those inner modes. > > > > Because complex or vector modes with BF/HF elements will be without > > > > TARGET_SSE2 for sure lowered into scalar code and that can't be handled > > > > either. > > > > So if (!TARGET_SSE2 && GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode) > > > > or even better > > > > if (!TARGET_SSE2 && element_mode (fromtype) == BFmode) > > > > ? > > > > Or even better remember the 2 modes above into machine_mode temporaries > > > > and just use those in the != comparison and for the checks? > > > > > > > > Also, I think it is weird to tell user %<__bf16%> or %<_Float16%> when > > > > we know which one it is. Just return separate messages? > > > Changed. > > > > > > > > + /* 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%>"); > > > > > > > > Similarly. Also, check !TARGET_SSE2 first as inexpensive one. > > > Changed. > > > > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. > > > Successfully cross-build i686-linux-gnu. > > > Ok for trunk? > > > > > > 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): New function. > > > (ix86_invalid_unary_op): Ditto. > > > (ix86_invalid_binary_op): Ditto. > > > (TARGET_INVALID_CONVERSION): Define. > > > (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. LGTM, if you need someone to rubber-stamp the patch. I'm not really versed in this part of the compiler, so please wait a day if someone has anything to say about the patch. Thanks, Uros. > > > --- > > > gcc/config/i386/i386-builtins.cc | 4 +- > > > gcc/config/i386/i386-c.cc | 15 ++ > > > gcc/config/i386/i386.cc | 130 ++++++++++++++++-- > > > gcc/config/i386/i386.h | 4 + > > > gcc/config/i386/immintrin.h | 4 - > > > gcc/testsuite/g++.target/i386/float16-1.C | 8 +- > > > gcc/testsuite/gcc.target/i386/pr109504.c | 6 + > > > .../gcc.target/i386/sse2-bfloat16-1.c | 8 +- > > > .../gcc.target/i386/sse2-float16-1.c | 8 +- > > > .../gcc.target/i386/sse2-float16-4.c | 25 ++++ > > > .../gcc.target/i386/sse2-float16-5.c | 24 ++++ > > > libgcc/config/i386/t-softfp | 7 + > > > 12 files changed, 215 insertions(+), 28 deletions(-) > > > create mode 100644 gcc/testsuite/gcc.target/i386/pr109504.c > > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > > > > diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc > > > index fc0c82b156e..1cdabfd3a0a 100644 > > > --- a/gcc/config/i386/i386-builtins.cc > > > +++ b/gcc/config/i386/i386-builtins.cc > > > @@ -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"); > > > } > > > > > > diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc > > > index e7bd7cc706c..2f83c9981e1 100644 > > > --- a/gcc/config/i386/i386-c.cc > > > +++ b/gcc/config/i386/i386-c.cc > > > @@ -817,6 +817,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__"); > > > > > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > > > index fbd33a6bfd1..633a0f41e60 100644 > > > --- a/gcc/config/i386/i386.cc > > > +++ b/gcc/config/i386/i386.cc > > > @@ -2651,7 +2651,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. */ > > > @@ -2661,13 +2662,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 +4029,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 +22479,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 +22495,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 +22825,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; > > > @@ -24259,6 +24280,86 @@ 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) > > > +{ > > > + 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%>"); > > > + } > > > + > > > + /* 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) > > > +{ > > > + 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; > > > +} > > > + > > > /* 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 +25349,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 > > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > > > index 1da6dce8e0b..7e839bc5c7e 100644 > > > --- a/gcc/config/i386/i386.h > > > +++ b/gcc/config/i386/i386.h > > > @@ -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 \ > > > diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h > > > index b220d871942..cc78df56940 100644 > > > --- a/gcc/config/i386/immintrin.h > > > +++ b/gcc/config/i386/immintrin.h > > > @@ -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> > > > > > > diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C > > > index f96b932b698..938852ee9ad 100644 > > > --- a/gcc/testsuite/g++.target/i386/float16-1.C > > > +++ b/gcc/testsuite/g++.target/i386/float16-1.C > > > @@ -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 } } */ > > > +} > > > diff --git a/gcc/testsuite/gcc.target/i386/pr109504.c b/gcc/testsuite/gcc.target/i386/pr109504.c > > > new file mode 100644 > > > index 00000000000..fe5bcda10ad > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.target/i386/pr109504.c > > > @@ -0,0 +1,6 @@ > > > +/* { dg-do compile } */ > > > +/* { dg-options "-O2 -mno-sse" } */ > > > + > > > +#pragma GCC target("sse4.1") > > > +#include <immintrin.h> > > > +int main(){return 0;} > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > > index 612d55be826..717055bc9ad 100644 > > > --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > > @@ -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} } */ > > > } > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > > index 1b645eb499d..faf818df75f 100644 > > > --- a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > > @@ -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} } */ > > > } > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-4.c b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > > new file mode 100644 > > > index 00000000000..64baf92ff56 > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > > @@ -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; > > > +} > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-5.c b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > new file mode 100644 > > > index 00000000000..c3ed23b8ab3 > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > @@ -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; > > > +} > > > diff --git a/libgcc/config/i386/t-softfp b/libgcc/config/i386/t-softfp > > > index 69d0f819822..80d1fac121b 100644 > > > --- a/libgcc/config/i386/t-softfp > > > +++ b/libgcc/config/i386/t-softfp > > > @@ -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 > > > -- > > > 2.39.1.388.g2fc9e9ca3c > > > > > > > > > -- > > BR, > > Hongtao > > > > -- > BR, > Hongtao
On Mon, Jul 17, 2023 at 7:38 PM Uros Bizjak <ubizjak@gmail.com> wrote: > > On Mon, Jul 17, 2023 at 10:28 AM Hongtao Liu <crazylht@gmail.com> wrote: > > > > I'd like to ping for this patch (only patch 1/2, for patch 2/2, I > > think that may not be necessary). > > > > On Mon, May 15, 2023 at 9:20 AM Hongtao Liu <crazylht@gmail.com> wrote: > > > > > > ping. > > > > > > On Fri, Apr 21, 2023 at 9:55 PM liuhongt <hongtao.liu@intel.com> wrote: > > > > > > > > > > + if (!TARGET_SSE2) > > > > > > + { > > > > > > + if (c_dialect_cxx () > > > > > > + && cxx_dialect > cxx20) > > > > > > > > > > Formatting, both conditions are short, so just put them on one line. > > > > Changed. > > > > > > > > > But for the C++23 macros, more importantly I think we really should > > > > > also in ix86_target_macros_internal add > > > > > if (c_dialect_cxx () > > > > > && cxx_dialect > cxx20 > > > > > && (isa_flag & OPTION_MASK_ISA_SSE2)) > > > > > { > > > > > def_or_undef (parse_in, "__STDCPP_FLOAT16_T__"); > > > > > def_or_undef (parse_in, "__STDCPP_BFLOAT16_T__"); > > > > > } > > > > > plus associated libstdc++ changes. It can be done incrementally though. > > > > Added in PATCH 2/2 > > > > > > > > > > + if (flag_building_libgcc) > > > > > > + { > > > > > > + /* libbid uses __LIBGCC_HAS_HF_MODE__ and __LIBGCC_HAS_BF_MODE__ > > > > > > + to check backend support of _Float16 and __bf16 type. */ > > > > > > > > > > That is actually the case only for HFmode, but not for BFmode right now. > > > > > So, we need further work. One is to add the BFmode support in there, > > > > > and another one is make sure the _Float16 <-> _Decimal* and __bf16 <-> > > > > > _Decimal* conversions are compiled in also if not -msse2 by default. > > > > > One way to do that is wrap the HF and BF mode related functions on x86 > > > > > #ifndef __SSE2__ into the pragmas like intrin headers use (but then > > > > > perhaps we don't need to undef this stuff here), another is not provide > > > > > the hf/bf support in that case from the TUs where they are provided now, > > > > > but from a different one which would be compiled with -msse2. > > > > Add CFLAGS-_hf_to_sd.c += -msse2, similar for other files in libbid, just like > > > > we did before for HFtype softfp. Then no need to undef libgcc macros. > > > > > > > > > > /* 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))) > > > > > > > > > > Formatting, no need to split this up that much. > > > > > if (needed_sseregs > > > > > && (!TARGET_SSE > > > > > || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > > > > or even better > > > > > if (needed_sseregs > > > > > && (!TARGET_SSE || (VALID_SSE2_TYPE_MODE (mode) && !TARGET_SSE2))) > > > > > will do it. > > > > Changed. > > > > > > > > > Instead of this, just use > > > > > if (!float16_type_node) > > > > > { > > > > > float16_type_node = ix86_float16_type_node; > > > > > callback (float16_type_node); > > > > > float16_type_node = NULL_TREE; > > > > > } > > > > > if (!bfloat16_type_node) > > > > > { > > > > > bfloat16_type_node = ix86_bf16_type_node; > > > > > callback (bfloat16_type_node); > > > > > bfloat16_type_node = NULL_TREE; > > > > > } > > > > Changed. > > > > > > > > > > > > > > +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) > > > > > > > > > > First of all, not really sure if this should be purely about scalar > > > > > modes, not also complex and vector modes involving those inner modes. > > > > > Because complex or vector modes with BF/HF elements will be without > > > > > TARGET_SSE2 for sure lowered into scalar code and that can't be handled > > > > > either. > > > > > So if (!TARGET_SSE2 && GET_MODE_INNER (TYPE_MODE (fromtype)) == BFmode) > > > > > or even better > > > > > if (!TARGET_SSE2 && element_mode (fromtype) == BFmode) > > > > > ? > > > > > Or even better remember the 2 modes above into machine_mode temporaries > > > > > and just use those in the != comparison and for the checks? > > > > > > > > > > Also, I think it is weird to tell user %<__bf16%> or %<_Float16%> when > > > > > we know which one it is. Just return separate messages? > > > > Changed. > > > > > > > > > > + /* 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%>"); > > > > > > > > > > Similarly. Also, check !TARGET_SSE2 first as inexpensive one. > > > > Changed. > > > > > > > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}. > > > > Successfully cross-build i686-linux-gnu. > > > > Ok for trunk? > > > > > > > > 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): New function. > > > > (ix86_invalid_unary_op): Ditto. > > > > (ix86_invalid_binary_op): Ditto. > > > > (TARGET_INVALID_CONVERSION): Define. > > > > (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. > > LGTM, if you need someone to rubber-stamp the patch. I'm not really > versed in this part of the compiler, so please wait a day if someone > has anything to say about the patch. Thanks, pushed to trunk. > > Thanks, > Uros. > > > > > --- > > > > gcc/config/i386/i386-builtins.cc | 4 +- > > > > gcc/config/i386/i386-c.cc | 15 ++ > > > > gcc/config/i386/i386.cc | 130 ++++++++++++++++-- > > > > gcc/config/i386/i386.h | 4 + > > > > gcc/config/i386/immintrin.h | 4 - > > > > gcc/testsuite/g++.target/i386/float16-1.C | 8 +- > > > > gcc/testsuite/gcc.target/i386/pr109504.c | 6 + > > > > .../gcc.target/i386/sse2-bfloat16-1.c | 8 +- > > > > .../gcc.target/i386/sse2-float16-1.c | 8 +- > > > > .../gcc.target/i386/sse2-float16-4.c | 25 ++++ > > > > .../gcc.target/i386/sse2-float16-5.c | 24 ++++ > > > > libgcc/config/i386/t-softfp | 7 + > > > > 12 files changed, 215 insertions(+), 28 deletions(-) > > > > create mode 100644 gcc/testsuite/gcc.target/i386/pr109504.c > > > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > > > > > > diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc > > > > index fc0c82b156e..1cdabfd3a0a 100644 > > > > --- a/gcc/config/i386/i386-builtins.cc > > > > +++ b/gcc/config/i386/i386-builtins.cc > > > > @@ -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"); > > > > } > > > > > > > > diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc > > > > index e7bd7cc706c..2f83c9981e1 100644 > > > > --- a/gcc/config/i386/i386-c.cc > > > > +++ b/gcc/config/i386/i386-c.cc > > > > @@ -817,6 +817,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__"); > > > > > > > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > > > > index fbd33a6bfd1..633a0f41e60 100644 > > > > --- a/gcc/config/i386/i386.cc > > > > +++ b/gcc/config/i386/i386.cc > > > > @@ -2651,7 +2651,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. */ > > > > @@ -2661,13 +2662,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 +4029,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 +22479,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 +22495,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 +22825,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; > > > > @@ -24259,6 +24280,86 @@ 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) > > > > +{ > > > > + 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%>"); > > > > + } > > > > + > > > > + /* 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) > > > > +{ > > > > + 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; > > > > +} > > > > + > > > > /* 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 +25349,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 > > > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h > > > > index 1da6dce8e0b..7e839bc5c7e 100644 > > > > --- a/gcc/config/i386/i386.h > > > > +++ b/gcc/config/i386/i386.h > > > > @@ -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 \ > > > > diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h > > > > index b220d871942..cc78df56940 100644 > > > > --- a/gcc/config/i386/immintrin.h > > > > +++ b/gcc/config/i386/immintrin.h > > > > @@ -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> > > > > > > > > diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C > > > > index f96b932b698..938852ee9ad 100644 > > > > --- a/gcc/testsuite/g++.target/i386/float16-1.C > > > > +++ b/gcc/testsuite/g++.target/i386/float16-1.C > > > > @@ -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 } } */ > > > > +} > > > > diff --git a/gcc/testsuite/gcc.target/i386/pr109504.c b/gcc/testsuite/gcc.target/i386/pr109504.c > > > > new file mode 100644 > > > > index 00000000000..fe5bcda10ad > > > > --- /dev/null > > > > +++ b/gcc/testsuite/gcc.target/i386/pr109504.c > > > > @@ -0,0 +1,6 @@ > > > > +/* { dg-do compile } */ > > > > +/* { dg-options "-O2 -mno-sse" } */ > > > > + > > > > +#pragma GCC target("sse4.1") > > > > +#include <immintrin.h> > > > > +int main(){return 0;} > > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > > > index 612d55be826..717055bc9ad 100644 > > > > --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > > > @@ -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} } */ > > > > } > > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > > > index 1b645eb499d..faf818df75f 100644 > > > > --- a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c > > > > @@ -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} } */ > > > > } > > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-4.c b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > > > new file mode 100644 > > > > index 00000000000..64baf92ff56 > > > > --- /dev/null > > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c > > > > @@ -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; > > > > +} > > > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-5.c b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > > new file mode 100644 > > > > index 00000000000..c3ed23b8ab3 > > > > --- /dev/null > > > > +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c > > > > @@ -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; > > > > +} > > > > diff --git a/libgcc/config/i386/t-softfp b/libgcc/config/i386/t-softfp > > > > index 69d0f819822..80d1fac121b 100644 > > > > --- a/libgcc/config/i386/t-softfp > > > > +++ b/libgcc/config/i386/t-softfp > > > > @@ -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 > > > > -- > > > > 2.39.1.388.g2fc9e9ca3c > > > > > > > > > > > > > -- > > > BR, > > > Hongtao > > > > > > > > -- > > BR, > > Hongtao
On Wed, Jul 19, 2023 at 01:58:21PM +0800, Hongtao Liu wrote: > > LGTM, if you need someone to rubber-stamp the patch. I'm not really > > versed in this part of the compiler, so please wait a day if someone > > has anything to say about the patch. > Thanks, pushed to trunk. I see some regressions most likely with this change on i686-linux, in particular: +FAIL: gcc.dg/pr107547.c (test for excess errors) +FAIL: gcc.dg/torture/floatn-convert.c -O0 (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O0 compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -O1 (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O1 compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -O2 (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O2 compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -O2 -flto (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O2 -flto compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -O2 -flto -flto-partition=none (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O2 -flto -flto-partition=none compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -O3 -g (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -O3 -g compilation failed to produce executable +FAIL: gcc.dg/torture/floatn-convert.c -Os (test for excess errors) +UNRESOLVED: gcc.dg/torture/floatn-convert.c -Os compilation failed to produce executable +FAIL: gcc.target/i386/float16-7.c (test for errors, line 7) Perhaps we need to tweak gcc/testsuite/lib/target-supports.exp (add_options_for_float16) so that it adds -msse2 for i?86-*-* x86_64-*-* (that would likely fix up floatn-convert) and for the others perhaps /* { dg-add-options float16 } */ ? Jakub
diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc index fc0c82b156e..1cdabfd3a0a 100644 --- a/gcc/config/i386/i386-builtins.cc +++ b/gcc/config/i386/i386-builtins.cc @@ -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"); } diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc index e7bd7cc706c..2f83c9981e1 100644 --- a/gcc/config/i386/i386-c.cc +++ b/gcc/config/i386/i386-c.cc @@ -817,6 +817,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__"); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index fbd33a6bfd1..633a0f41e60 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -2651,7 +2651,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. */ @@ -2661,13 +2662,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 +4029,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 +22479,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 +22495,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 +22825,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; @@ -24259,6 +24280,86 @@ 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) +{ + 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%>"); + } + + /* 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) +{ + 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; +} + /* 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 +25349,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 diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 1da6dce8e0b..7e839bc5c7e 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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 \ diff --git a/gcc/config/i386/immintrin.h b/gcc/config/i386/immintrin.h index b220d871942..cc78df56940 100644 --- a/gcc/config/i386/immintrin.h +++ b/gcc/config/i386/immintrin.h @@ -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> diff --git a/gcc/testsuite/g++.target/i386/float16-1.C b/gcc/testsuite/g++.target/i386/float16-1.C index f96b932b698..938852ee9ad 100644 --- a/gcc/testsuite/g++.target/i386/float16-1.C +++ b/gcc/testsuite/g++.target/i386/float16-1.C @@ -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 } } */ +} diff --git a/gcc/testsuite/gcc.target/i386/pr109504.c b/gcc/testsuite/gcc.target/i386/pr109504.c new file mode 100644 index 00000000000..fe5bcda10ad --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr109504.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mno-sse" } */ + +#pragma GCC target("sse4.1") +#include <immintrin.h> +int main(){return 0;} diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c index 612d55be826..717055bc9ad 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c @@ -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} } */ } diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c index 1b645eb499d..faf818df75f 100644 --- a/gcc/testsuite/gcc.target/i386/sse2-float16-1.c +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-1.c @@ -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} } */ } diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-4.c b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c new file mode 100644 index 00000000000..64baf92ff56 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-4.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-float16-5.c b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c new file mode 100644 index 00000000000..c3ed23b8ab3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-float16-5.c @@ -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; +} diff --git a/libgcc/config/i386/t-softfp b/libgcc/config/i386/t-softfp index 69d0f819822..80d1fac121b 100644 --- a/libgcc/config/i386/t-softfp +++ b/libgcc/config/i386/t-softfp @@ -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