[1/2,i386] Support type _Float16/__bf16 independent of SSE2.
Checks
Commit Message
> > + 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
Comments
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
@@ -1367,7 +1367,7 @@ ix86_register_float16_builtin_type (void)
else
ix86_float16_type_node = float16_type_node;
- if (!maybe_get_identifier ("_Float16") && TARGET_SSE2)
+ if (!maybe_get_identifier ("_Float16"))
lang_hooks.types.register_builtin_type (ix86_float16_type_node,
"_Float16");
}
@@ -1385,7 +1385,7 @@ ix86_register_bf16_builtin_type (void)
else
ix86_bf16_type_node = bfloat16_type_node;
- if (!maybe_get_identifier ("__bf16") && TARGET_SSE2)
+ if (!maybe_get_identifier ("__bf16"))
lang_hooks.types.register_builtin_type (ix86_bf16_type_node, "__bf16");
}
@@ -817,6 +817,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__");
@@ -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
@@ -1046,6 +1046,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define VALID_AVX512FP16_REG_MODE(MODE) \
((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode)
+#define VALID_SSE2_TYPE_MODE(MODE) \
+ ((MODE) == HFmode || (MODE) == BFmode \
+ || (MODE) == HCmode || (MODE) == BCmode)
+
#define VALID_SSE2_REG_MODE(MODE) \
((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \
|| (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \
@@ -98,11 +98,9 @@
#include <avx512vp2intersectvlintrin.h>
-#ifdef __SSE2__
#include <avx512fp16intrin.h>
#include <avx512fp16vlintrin.h>
-#endif
#include <shaintrin.h>
@@ -118,13 +116,11 @@
#include <vpclmulqdqintrin.h>
-#ifdef __SSE2__
#include <avx512bf16vlintrin.h>
#include <avx512bf16intrin.h>
#include <avxneconvertintrin.h>
-#endif
#include <amxtileintrin.h>
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-_Float16 /* { dg-error "expected unqualified-id before '_Float16'" } */
-foo (_Float16 x)
+_Float16
+foo (_Float16 x)/* { dg-error "SSE register return with SSE2 disabled" } */
{
- return x;
-} /* { dg-error "'_Float16' is not supported on this target" } */
+ return x;/* { dg-error "SSE register return with SSE2 disabled" "" { target ia32 } } */
+}
new file mode 100644
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse" } */
+
+#pragma GCC target("sse4.1")
+#include <immintrin.h>
+int main(){return 0;}
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-__bf16/* { dg-error "unknown type name '__bf16'" } */
-foo (__bf16 x) /* { dg-error "unknown type name '__bf16'" } */
-{
- return x;
+__bf16
+foo (__bf16 x) /* { dg-error "SSE register return with SSE2 disabled" } */
+{ /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32 } } */
+ return x; /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32} } */
}
@@ -1,8 +1,8 @@
/* { dg-do compile } */
/* { dg-options "-O2 -mno-sse2" } */
-_Float16/* { dg-error "is not supported on this target" } */
-foo (_Float16 x) /* { dg-error "is not supported on this target" } */
-{
- return x;
+_Float16
+foo (_Float16 x) /* { dg-error "SSE register return with SSE2 disabled" } */
+{ /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32 } } */
+ return x; /* { dg-error "SSE register return with SSE2 disabled" "" { target ia32} } */
}
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+_Float16 a;
+__bf16 c;
+_Complex _Float16 ac;
+
+void
+foo (_Float16* p)
+{
+ a = *p;
+}
+
+void
+foo1 (__bf16 *p)
+{
+ c = *p;
+}
+
+
+void
+foo2 (_Complex _Float16* p)
+{
+ ac = *p;
+}
new file mode 100644
@@ -0,0 +1,24 @@
+/* { dg-do compile { target ia32} } */
+/* { dg-options "-O2 -mno-sse2" } */
+
+_Float16 a;
+__bf16 c;
+_Complex ac;
+void
+foo (_Float16 p)
+{
+ a = p;
+}
+
+void
+foo1 (__bf16 p)
+{
+ c = p;
+}
+
+
+void
+foo2 (_Complex p)
+{
+ ac = p;
+}
@@ -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