* [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above [not found] <20220726011357.12001-1-lingling.kong@intel.com> @ 2022-07-26 1:31 ` Kong, Lingling 2022-08-03 8:40 ` Kong, Lingling 0 siblings, 1 reply; 3+ messages in thread From: Kong, Lingling @ 2022-07-26 1:31 UTC (permalink / raw) To: Liu, Hongtao, gcc-patches Hi, The patch is enable __bf16 scalar type for target sse2 and above according to psABI(https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/35/diffs). The __bf16 type is a storage type like arm. OK for master? gcc/ChangeLog: * config/i386/i386-builtin-types.def (BFLOAT16): New primitive type. * config/i386/i386-builtins.cc : Support __bf16 type for i386 backend. (ix86_register_bf16_builtin_type): New function. (ix86_bf16_type_node): New. (ix86_bf16_ptr_type_node): Ditto. (ix86_init_builtin_types): Add ix86_register_bf16_builtin_type function call. * config/i386/i386-modes.def (FLOAT_MODE): Add BFmode. (ADJUST_FLOAT_FORMAT): Ditto. * config/i386/i386.cc (merge_classes): Handle BFmode. (classify_argument): Ditto. (examine_argument): Ditto. (construct_container): Ditto. (function_value_32): Return __bf16 by %xmm0. (function_value_64): Return __bf16 by SSE register. (ix86_print_operand): Handle CONST_DOUBLE BFmode. (ix86_secondary_reload): Require gpr as intermediate register to store __bf16 from sse register when sse4 is not available. (ix86_scalar_mode_supported_p): Enable __bf16 under sse2. (ix86_mangle_type): Add manlging for __bf16 type. (ix86_invalid_conversion): New function for target hook. (ix86_invalid_unary_op): Ditto. (ix86_invalid_binary_op): Ditto. (TARGET_INVALID_CONVERSION): New define for target hook. (TARGET_INVALID_UNARY_OP): Ditto. (TARGET_INVALID_BINARY_OP): Ditto. * config/i386/i386.h (host_detect_local_cpu): Add BFmode. * config/i386/i386.md (*pushhf_rex64): Change for BFmode. (*push<mode>_rex64): Ditto. (*pushhf): Ditto. (*push<mode>): Ditto. (*movhf_internal): Ditto. (*mov<mode>_internal): Ditto. gcc/testsuite/ChangeLog: * g++.target/i386/bfloat_cpp_typecheck.C: New test. * gcc.target/i386/bfloat16-1.c: Ditto. * gcc.target/i386/sse2-bfloat16-1.c: Ditto. * gcc.target/i386/sse2-bfloat16-2.c: Ditto. * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Ditto. --- gcc/config/i386/i386-builtin-types.def | 1 + gcc/config/i386/i386-builtins.cc | 21 ++ gcc/config/i386/i386-modes.def | 2 + gcc/config/i386/i386.cc | 75 +++++- gcc/config/i386/i386.h | 4 +- gcc/config/i386/i386.md | 32 +-- .../g++.target/i386/bfloat_cpp_typecheck.C | 10 + gcc/testsuite/gcc.target/i386/bfloat16-1.c | 12 + .../gcc.target/i386/sse2-bfloat16-1.c | 8 + .../gcc.target/i386/sse2-bfloat16-2.c | 17 ++ .../i386/sse2-bfloat16-scalar-typecheck.c | 215 ++++++++++++++++++ 11 files changed, 375 insertions(+), 22 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C create mode 100644 gcc/testsuite/gcc.target/i386/bfloat16-1.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 7a2da1db0b0..63a360b0f8b 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -69,6 +69,7 @@ DEF_PRIMITIVE_TYPE (UINT16, short_unsigned_type_node) DEF_PRIMITIVE_TYPE (INT64, long_long_integer_type_node) DEF_PRIMITIVE_TYPE (UINT64, long_long_unsigned_type_node) DEF_PRIMITIVE_TYPE (FLOAT16, ix86_float16_type_node) +DEF_PRIMITIVE_TYPE (BFLOAT16, ix86_bf16_type_node) DEF_PRIMITIVE_TYPE (FLOAT, float_type_node) DEF_PRIMITIVE_TYPE (DOUBLE, double_type_node) DEF_PRIMITIVE_TYPE (FLOAT80, float80_type_node) diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc index fe7243c3837..6a04fb57e65 100644 --- a/gcc/config/i386/i386-builtins.cc +++ b/gcc/config/i386/i386-builtins.cc @@ -126,6 +126,9 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX, static GTY(()) tree ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1]; tree ix86_float16_type_node = NULL_TREE; +tree ix86_bf16_type_node = NULL_TREE; +tree ix86_bf16_ptr_type_node = NULL_TREE; + /* Retrieve an element from the above table, building some of the types lazily. */ @@ -1366,6 +1369,22 @@ ix86_register_float16_builtin_type (void) "_Float16"); } +static void +ix86_register_bf16_builtin_type (void) +{ + ix86_bf16_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ix86_bf16_type_node) = 16; + SET_TYPE_MODE (ix86_bf16_type_node, BFmode); + layout_type (ix86_bf16_type_node); + + if (!maybe_get_identifier ("__bf16") && TARGET_SSE2) + { + lang_hooks.types.register_builtin_type (ix86_bf16_type_node, + "__bf16"); + ix86_bf16_ptr_type_node = build_pointer_type (ix86_bf16_type_node); + } +} + static void ix86_init_builtin_types (void) { @@ -1396,6 +1415,8 @@ ix86_init_builtin_types (void) ix86_register_float16_builtin_type (); + ix86_register_bf16_builtin_type (); + const_string_type_node = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index e2e1e18d24d..b49daaef253 100644 --- a/gcc/config/i386/i386-modes.def +++ b/gcc/config/i386/i386-modes.def @@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format); FLOAT_MODE (TF, 16, ieee_quad_format); FLOAT_MODE (HF, 2, ieee_half_format); +FLOAT_MODE (BF, 2, 0); +ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format); /* In ILP32 mode, XFmode has size 12 and alignment 4. In LP64 mode, XFmode has size and alignment 16. */ diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index e03f86d4a23..5d589f6a05c 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -2399,6 +2399,7 @@ classify_argument (machine_mode mode, const_tree type, case E_CTImode: return 0; case E_HFmode: + case E_BFmode: if (!(bit_offset % 64)) classes[0] = X86_64_SSEHF_CLASS; else @@ -2792,9 +2793,10 @@ construct_container (machine_mode mode, machine_mode orig_mode, intreg++; break; case X86_64_SSEHF_CLASS: + tmpmode = (mode == BFmode ? BFmode : HFmode); exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_REG (HFmode, + gen_rtx_REG (tmpmode, GET_SSE_REGNO (sse_regno)), GEN_INT (i*8)); sse_regno++; @@ -4001,8 +4003,8 @@ function_value_32 (machine_mode orig_mode, machine_mode mode, /* Most things go in %eax. */ regno = AX_REG; - /* Return _Float16/_Complex _Foat16 by sse register. */ - if (mode == HFmode) + /* Return __bf16/ _Float16/_Complex _Foat16 by sse register. */ if + (mode == HFmode || mode == BFmode) regno = FIRST_SSE_REG; if (mode == HCmode) { @@ -4050,6 +4052,7 @@ function_value_64 (machine_mode orig_mode, machine_mode mode, switch (mode) { + case E_BFmode: case E_HFmode: case E_HCmode: case E_SFmode: @@ -5631,6 +5634,7 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands) return "%vmovss\t{%1, %0|%0, %1}"; case MODE_HF: + case MODE_BF: if (REG_P (operands[0]) && REG_P (operands[1])) return "vmovsh\t{%d1, %0|%0, %d1}"; else @@ -19402,7 +19406,8 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass, } /* Require movement to gpr, and then store to memory. */ - if ((mode == HFmode || mode == HImode || mode == V2QImode) + if ((mode == HFmode || mode == HImode || mode == V2QImode + || mode == BFmode) && !TARGET_SSE4_1 && SSE_CLASS_P (rclass) && !in_p && MEM_P (x)) @@ -22331,7 +22336,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 && TARGET_SSE2) + else if ((mode == HFmode || mode == BFmode) && TARGET_SSE2) return true; else return default_scalar_mode_supported_p (mode); @@ -22646,6 +22651,8 @@ ix86_mangle_type (const_tree type) switch (TYPE_MODE (type)) { + case E_BFmode: + return "u6__bf16"; case E_HFmode: /* _Float16 is "DF16_". Align with clang's decision in https://reviews.llvm.org/D33719. */ @@ -22661,6 +22668,55 @@ ix86_mangle_type (const_tree type) } } +/* Return the diagnostic message string if conversion from FROMTYPE to + TOTYPE is not allowed, NULL otherwise. */ + +static const char * +ix86_invalid_conversion (const_tree fromtype, const_tree totype) { + if (element_mode (fromtype) != element_mode (totype)) + { + /* Do no allow conversions to/from BFmode scalar types. */ + if (TYPE_MODE (fromtype) == BFmode) + return N_("invalid conversion from type %<__bf16%>"); + if (TYPE_MODE (totype) == BFmode) + return N_("invalid conversion to type %<__bf16%>"); + } + + /* Conversion allowed. */ + return NULL; +} + +/* Return the diagnostic message string if the unary operation OP is + not permitted on TYPE, NULL otherwise. */ + +static const char * +ix86_invalid_unary_op (int op, const_tree type) { + /* Reject all single-operand operations on BFmode except for &. */ + if (element_mode (type) == BFmode && op != ADDR_EXPR) + return N_("operation not permitted on type %<__bf16%>"); + + /* Operation allowed. */ + return NULL; +} + +/* Return the diagnostic message string if the binary operation OP is + not permitted on TYPE1 and TYPE2, NULL otherwise. */ + +static const char * +ix86_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, + const_tree type2) +{ + /* Reject all 2-operand operations on BFmode. */ + if (element_mode (type1) == BFmode + || element_mode (type2) == BFmode) + return N_("operation not permitted on type %<__bf16%>"); + + /* Operation allowed. */ + return NULL; +} + static GTY(()) tree ix86_tls_stack_chk_guard_decl; static tree @@ -24718,6 +24774,15 @@ ix86_libgcc_floating_mode_supported_p #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE ix86_mangle_type +#undef TARGET_INVALID_CONVERSION +#define TARGET_INVALID_CONVERSION ix86_invalid_conversion + +#undef TARGET_INVALID_UNARY_OP +#define TARGET_INVALID_UNARY_OP ix86_invalid_unary_op + +#undef TARGET_INVALID_BINARY_OP +#define TARGET_INVALID_BINARY_OP ix86_invalid_binary_op + #undef TARGET_STACK_PROTECT_GUARD #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f16df633e84..0da3dce1d31 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1046,7 +1046,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \ || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ || (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode \ - || (MODE) == HFmode) + || (MODE) == HFmode || (MODE) == BFmode) #define VALID_SSE_REG_MODE(MODE) \ ((MODE) == V1TImode || (MODE) == TImode \ @@ -1077,7 +1077,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == CQImode || (MODE) == CHImode \ || (MODE) == CSImode || (MODE) == CDImode \ || (MODE) == SDmode || (MODE) == DDmode \ - || (MODE) == HFmode || (MODE) == HCmode \ + || (MODE) == HFmode || (MODE) == HCmode || (MODE) == BFmode \ || (MODE) == V2HImode || (MODE) == V2HFmode \ || (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode \ || (TARGET_64BIT \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 9aaeb695f0f..1f7b018913a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -499,7 +499,7 @@ ;; Main data type used by the insn (define_attr "mode" - "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF, + + "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,BF,SF,DF,XF,TF,V32HF,V16HF,V8HF, V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF" (const_string "unknown")) @@ -1104,7 +1104,7 @@ ;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on ;; command line options just use GET_MODE_SIZE macro. (define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8") - (TI "16") (HF "2") (SF "4") (DF "8") + (TI "16") (HF "2") (BF "2") (SF "4") (DF "8") (XF "GET_MODE_SIZE (XFmode)") (V16QI "16") (V32QI "32") (V64QI "64") (V8HI "16") (V16HI "32") (V32HI "64") @@ -1248,7 +1248,7 @@ (define_mode_iterator X87MODEF [SF DF XF]) ;; All x87 floating point modes plus HFmode -(define_mode_iterator X87MODEFH [HF SF DF XF]) +(define_mode_iterator X87MODEFH [HF SF DF XF BF]) ;; All SSE floating point modes (define_mode_iterator SSEMODEF [HF SF DF TF]) @@ -3408,9 +3408,11 @@ operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); }) -(define_insn "*pushhf_rex64" - [(set (match_operand:HF 0 "push_operand" "=X,X") - (match_operand:HF 1 "nonmemory_no_elim_operand" "r,x"))] +(define_mode_iterator HFBF [HF BF]) + +(define_insn "*push<mode>_rex64" + [(set (match_operand:HFBF 0 "push_operand" "=X,X") + (match_operand:HFBF 1 "nonmemory_no_elim_operand" "r,x"))] "TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -3421,9 +3423,9 @@ (set_attr "type" "push,multi") (set_attr "mode" "DI,TI")]) -(define_insn "*pushhf" - [(set (match_operand:HF 0 "push_operand" "=X,X") - (match_operand:HF 1 "general_no_elim_operand" "rmF,x"))] +(define_insn "*push<mode>" + [(set (match_operand:HFBF 0 "push_operand" "=X,X") + (match_operand:HFBF 1 "general_no_elim_operand" "rmF,x"))] "!TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -3462,7 +3464,7 @@ (set_attr "unit" "i387,*,*") (set_attr "mode" "SF,SI,SF")]) -(define_mode_iterator MODESH [SF HF]) +(define_mode_iterator MODESH [SF HF BF]) ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:MODESH 0 "push_operand") @@ -3950,18 +3952,18 @@ ] (const_string "*")))]) -(define_insn "*movhf_internal" - [(set (match_operand:HF 0 "nonimmediate_operand" +(define_insn "*mov<mode>_internal" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "=?r,?r,?r,?m,v,v,?r,m,?v,v") - (match_operand:HF 1 "general_operand" + (match_operand:HFBF 1 "general_operand" "r ,F ,m ,rF,C,v, v,v,r ,m"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (lra_in_progress || reload_completed || !CONST_DOUBLE_P (operands[1]) || (TARGET_SSE2 - && standard_sse_constant_p (operands[1], HFmode) == 1) - || memory_operand (operands[0], HFmode))" + && standard_sse_constant_p (operands[1], <MODE>mode) == 1) + || memory_operand (operands[0], <MODE>mode))" { switch (get_attr_type (insn)) { diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C new file mode 100644 index 00000000000..962c8504775 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C @@ -0,0 +1,10 @@ +/* { dg-do assemble { target sse2} } */ +/* { dg-options "-msse2 -O3 --save-temps" } */ + +void foo (void) +{ + __bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} } */ + __bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type +'__bf16'} } */ + __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} +} */ + __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } +*/ } diff --git a/gcc/testsuite/gcc.target/i386/bfloat16-1.c b/gcc/testsuite/gcc.target/i386/bfloat16-1.c new file mode 100644 index 00000000000..6aaec28efd2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/bfloat16-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O2" } */ +__bf16 +foo (int a) +{ + union { + int a; + __bf16 b; + }c; + c.a = a; + return c.b; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c new file mode 100644 index 00000000000..612d55be826 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c @@ -0,0 +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; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c new file mode 100644 index 00000000000..a3286e26c48 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2 -mno-avx512f" } */ + +union flt +{ + __bf16 flt; + short s; +}; + +__bf16 +foo (union flt x) +{ + return x.flt; +} + +/* { dg-final { scan-assembler {(?n)pinsrw[\t ].*%xmm0} { target ia32 } +} } */ +/* { dg-final { scan-assembler {(?n)movd[\t ].*%xmm0} { target { ! ia32 +} } } } */ diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c new file mode 100644 index 00000000000..f76d5547758 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c @@ -0,0 +1,215 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O2" } */ + + +__bf16 glob_bfloat; + +int is_an_int; +short is_a_short_int; +float is_a_float; +float is_a_float16; +double is_a_double; + +float *float_ptr; + +__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid +conversion to type '__bf16'} } */ +__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error +{invalid conversion to type '__bf16'} } */ + +__bf16 footest (__bf16 scalar0) +{ + + /* Initialisation */ + + __bf16 scalar1_1; + __bf16 scalar1_2 = glob_bfloat; + __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type + '__bf16'} } */ + __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to + type '__bf16'} } */ + __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to + type '__bf16'} } */ + __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to + type '__bf16'} } */ + __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to + type '__bf16'} } */ + __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion + to type '__bf16'} } */ + + int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from + type '__bf16'} } */ float initi_1_2 = glob_bfloat; /* { dg-error + {invalid conversion from type '__bf16'} } */ + _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion + from type '__bf16'} } */ short initi_1_4 = glob_bfloat; /* { dg-error + {invalid conversion from type '__bf16'} } */ double initi_1_5 = + glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } + */ + + __bf16 scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */ + __bf16 scalar2_2 = { glob_bfloat }; + __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type + '__bf16'} } */ + __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type + '__bf16'} } */ + __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion + to type '__bf16'} } */ + __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion + to type '__bf16'} } */ + __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid + conversion to type '__bf16'} } */ + __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion + to type '__bf16'} } */ + __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid + conversion to type '__bf16'} } */ + + int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion + from type '__bf16'} } */ float initi_2_2 = { glob_bfloat }; /* { + dg-error {invalid conversion from type '__bf16'} } */ + _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid + conversion from type '__bf16'} } */ short initi_2_4 = { glob_bfloat + }; /* { dg-error {invalid conversion from type '__bf16'} } */ double + initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from + type '__bf16'} } */ + + /* Assignments. */ + + glob_bfloat = glob_bfloat; + glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = 0.1; /* { dg-error {invalid conversion to type + '__bf16'} } */ glob_bfloat = is_a_float; /* { dg-error {invalid + conversion to type '__bf16'} } */ glob_bfloat = is_an_int; /* { + dg-error {invalid conversion to type '__bf16'} } */ glob_bfloat = + is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type + '__bf16'} } */ glob_bfloat = is_a_short_int; /* { dg-error {invalid + conversion to type '__bf16'} } */ + + is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type + '__bf16'} } */ is_a_float = glob_bfloat; /* { dg-error {invalid + conversion from type '__bf16'} } */ + is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from + type '__bf16'} } */ is_a_double = glob_bfloat; /* { dg-error {invalid + conversion from type '__bf16'} } */ is_a_short_int = glob_bfloat; /* + { dg-error {invalid conversion from type '__bf16'} } */ + + /* Casting. */ + + (void) glob_bfloat; + (__bf16) glob_bfloat; + + (int) glob_bfloat; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (float) glob_bfloat; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (double) glob_bfloat; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (short) glob_bfloat; /* { dg-error {invalid conversion from type + '__bf16'} } */ + + (__bf16) is_an_int; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) is_a_float; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) is_a_float16; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) is_a_double; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type + '__bf16'} } */ + + /* Compound literals. */ + + (__bf16) {}; /* { dg-error {empty scalar initializer} } */ + (__bf16) { glob_bfloat }; + (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } + */ + (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} + } */ + (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type + '__bf16'} } */ + (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to + type '__bf16'} } */ + + (int) { glob_bfloat }; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (float) { glob_bfloat }; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from + type '__bf16'} } */ + (double) { glob_bfloat }; /* { dg-error {invalid conversion from type + '__bf16'} } */ + (short) { glob_bfloat }; /* { dg-error {invalid conversion from type + '__bf16'} } */ + + /* Arrays and Structs. */ + + typedef __bf16 array_type[2]; + extern __bf16 extern_array[]; + + __bf16 array[2]; + __bf16 zero_length_array[0]; + __bf16 empty_init_array[] = {}; + typedef __bf16 some_other_type[is_an_int]; + + struct struct1 { + __bf16 a; + }; + + union union1 { + __bf16 a; + }; + + /* Addressing and dereferencing. */ + + __bf16 *bfloat_ptr = &scalar0; + scalar0 = *bfloat_ptr; + + /* Pointer assignment. */ + + __bf16 *bfloat_ptr2 = bfloat_ptr; + __bf16 *bfloat_ptr3 = array; + + /* Pointer arithmetic. */ + + ++bfloat_ptr; + --bfloat_ptr; + bfloat_ptr++; + bfloat_ptr--; + bfloat_ptr += 1; + bfloat_ptr -= 1; + bfloat_ptr - bfloat_ptr2; + bfloat_ptr = &bfloat_ptr3[0]; + bfloat_ptr = &bfloat_ptr3[1]; + + /* Simple comparison. */ + scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type + '__bf16'} } */ glob_bfloat == scalar0; /* { dg-error {operation not + permitted on type '__bf16'} } */ + scalar0 > is_a_float; /* { dg-error {operation not permitted on type + '__bf16'} } */ is_a_float == scalar0; /* { dg-error {operation not + permitted on type '__bf16'} } */ + scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} + } */ + 0 == scalar0; /* { dg-error {operation not permitted on type + '__bf16'} } */ + scalar0 > 0.1; /* { dg-error {operation not permitted on type + '__bf16'} } */ + 0.1 == scalar0; /* { dg-error {operation not permitted on type + '__bf16'} } */ + scalar0 > is_an_int; /* { dg-error {operation not permitted on type + '__bf16'} } */ is_an_int == scalar0; /* { dg-error {operation not + permitted on type '__bf16'} } */ + + /* Pointer comparison. */ + + bfloat_ptr == &scalar0; + bfloat_ptr != &scalar0; + bfloat_ptr < &scalar0; + bfloat_ptr <= &scalar0; + bfloat_ptr > &scalar0; + bfloat_ptr >= &scalar0; + bfloat_ptr == bfloat_ptr2; + bfloat_ptr != bfloat_ptr2; + bfloat_ptr < bfloat_ptr2; + bfloat_ptr <= bfloat_ptr2; + bfloat_ptr > bfloat_ptr2; + bfloat_ptr >= bfloat_ptr2; + + /* Conditional expressions. */ + + 0 ? scalar0 : scalar0; + 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type + '__bf16'} } */ + 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type + '__bf16'} } */ + 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} + } */ + 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} + } */ + 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type + '__bf16'} } */ + 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type + '__bf16'} } */ + 0 ? bfloat_ptr : bfloat_ptr2; + 0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in + conditional expression} } */ + 0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in + conditional expression} } */ + + scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted + on type '__bf16'} } */ + scalar0 ? is_a_float : scalar0; /* { dg-error {operation not + permitted on type '__bf16'} } */ + scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not + permitted on type '__bf16'} } */ + scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not + permitted on type '__bf16'} } */ + + /* Unary operators. */ + + +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } + */ -scalar0; /* { dg-error {operation not permitted on type '__bf16'} + } */ ~scalar0; /* { dg-error {operation not permitted on type + '__bf16'} } */ !scalar0; /* { dg-error {operation not permitted on + type '__bf16'} } */ *scalar0; /* { dg-error {invalid type argument of + unary '\*'} } */ __real scalar0; /* { dg-error {operation not + permitted on type '__bf16'} } */ __imag scalar0; /* { dg-error + {operation not permitted on type '__bf16'} } */ ++scalar0; /* { + dg-error {operation not permitted on type '__bf16'} } */ --scalar0; + /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } + */ scalar0--; /* { dg-error {operation not permitted on type + '__bf16'} } */ + + /* Binary arithmetic operations. */ + + scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not + permitted on type '__bf16'} } */ + scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted + on type '__bf16'} } */ + scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on + type '__bf16'} } */ + scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not + permitted on type '__bf16'} } */ + + return scalar0; +} + -- 2.18.2 ^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above 2022-07-26 1:31 ` [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above Kong, Lingling @ 2022-08-03 8:40 ` Kong, Lingling 2022-08-04 4:35 ` Hongtao Liu 0 siblings, 1 reply; 3+ messages in thread From: Kong, Lingling @ 2022-08-03 8:40 UTC (permalink / raw) To: Liu, Hongtao, gcc-patches [-- Attachment #1: Type: text/plain, Size: 30852 bytes --] Hi, Old patch has some mistake in `*movbf_internal` , now disable BFmode constant double move in `*movbf_internal`. Thanks, Lingling > -----Original Message----- > From: Kong, Lingling <lingling.kong@intel.com> > Sent: Tuesday, July 26, 2022 9:31 AM > To: Liu, Hongtao <hongtao.liu@intel.com>; gcc-patches@gcc.gnu.org > Cc: Kong, Lingling <lingling.kong@intel.com> > Subject: [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above > > Hi, > > The patch is enable __bf16 scalar type for target sse2 and above according to > psABI(https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/35/diffs). > The __bf16 type is a storage type like arm. > > OK for master? > > gcc/ChangeLog: > > * config/i386/i386-builtin-types.def (BFLOAT16): New primitive type. > * config/i386/i386-builtins.cc : Support __bf16 type for i386 backend. > (ix86_register_bf16_builtin_type): New function. > (ix86_bf16_type_node): New. > (ix86_bf16_ptr_type_node): Ditto. > (ix86_init_builtin_types): Add ix86_register_bf16_builtin_type function > call. > * config/i386/i386-modes.def (FLOAT_MODE): Add BFmode. > (ADJUST_FLOAT_FORMAT): Ditto. > * config/i386/i386.cc (merge_classes): Handle BFmode. > (classify_argument): Ditto. > (examine_argument): Ditto. > (construct_container): Ditto. > (function_value_32): Return __bf16 by %xmm0. > (function_value_64): Return __bf16 by SSE register. > (ix86_print_operand): Handle CONST_DOUBLE BFmode. > (ix86_secondary_reload): Require gpr as intermediate register > to store __bf16 from sse register when sse4 is not available. > (ix86_scalar_mode_supported_p): Enable __bf16 under sse2. > (ix86_mangle_type): Add manlging for __bf16 type. > (ix86_invalid_conversion): New function for target hook. > (ix86_invalid_unary_op): Ditto. > (ix86_invalid_binary_op): Ditto. > (TARGET_INVALID_CONVERSION): New define for target hook. > (TARGET_INVALID_UNARY_OP): Ditto. > (TARGET_INVALID_BINARY_OP): Ditto. > * config/i386/i386.h (host_detect_local_cpu): Add BFmode. > * config/i386/i386.md (*pushhf_rex64): Change for BFmode. > (*push<mode>_rex64): Ditto. > (*pushhf): Ditto. > (*push<mode>): Ditto. > (*movhf_internal): Ditto. > (*mov<mode>_internal): Ditto. > > gcc/testsuite/ChangeLog: > > * g++.target/i386/bfloat_cpp_typecheck.C: New test. > * gcc.target/i386/bfloat16-1.c: Ditto. > * gcc.target/i386/sse2-bfloat16-1.c: Ditto. > * gcc.target/i386/sse2-bfloat16-2.c: Ditto. > * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Ditto. > --- > gcc/config/i386/i386-builtin-types.def | 1 + > gcc/config/i386/i386-builtins.cc | 21 ++ > gcc/config/i386/i386-modes.def | 2 + > gcc/config/i386/i386.cc | 75 +++++- > gcc/config/i386/i386.h | 4 +- > gcc/config/i386/i386.md | 32 +-- > .../g++.target/i386/bfloat_cpp_typecheck.C | 10 + > gcc/testsuite/gcc.target/i386/bfloat16-1.c | 12 + > .../gcc.target/i386/sse2-bfloat16-1.c | 8 + > .../gcc.target/i386/sse2-bfloat16-2.c | 17 ++ > .../i386/sse2-bfloat16-scalar-typecheck.c | 215 ++++++++++++++++++ > 11 files changed, 375 insertions(+), 22 deletions(-) create mode 100644 > gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > create mode 100644 gcc/testsuite/gcc.target/i386/bfloat16-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar- > typecheck.c > > diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386- > builtin-types.def > index 7a2da1db0b0..63a360b0f8b 100644 > --- a/gcc/config/i386/i386-builtin-types.def > +++ b/gcc/config/i386/i386-builtin-types.def > @@ -69,6 +69,7 @@ DEF_PRIMITIVE_TYPE (UINT16, > short_unsigned_type_node) DEF_PRIMITIVE_TYPE (INT64, > long_long_integer_type_node) DEF_PRIMITIVE_TYPE (UINT64, > long_long_unsigned_type_node) DEF_PRIMITIVE_TYPE (FLOAT16, > ix86_float16_type_node) > +DEF_PRIMITIVE_TYPE (BFLOAT16, ix86_bf16_type_node) > DEF_PRIMITIVE_TYPE (FLOAT, float_type_node) DEF_PRIMITIVE_TYPE > (DOUBLE, double_type_node) DEF_PRIMITIVE_TYPE (FLOAT80, > float80_type_node) diff --git a/gcc/config/i386/i386-builtins.cc > b/gcc/config/i386/i386-builtins.cc > index fe7243c3837..6a04fb57e65 100644 > --- a/gcc/config/i386/i386-builtins.cc > +++ b/gcc/config/i386/i386-builtins.cc > @@ -126,6 +126,9 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX, static GTY(()) tree > ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1]; > > tree ix86_float16_type_node = NULL_TREE; > +tree ix86_bf16_type_node = NULL_TREE; > +tree ix86_bf16_ptr_type_node = NULL_TREE; > + > /* Retrieve an element from the above table, building some of > the types lazily. */ > > @@ -1366,6 +1369,22 @@ ix86_register_float16_builtin_type (void) > "_Float16"); > } > > +static void > +ix86_register_bf16_builtin_type (void) > +{ > + ix86_bf16_type_node = make_node (REAL_TYPE); > + TYPE_PRECISION (ix86_bf16_type_node) = 16; > + SET_TYPE_MODE (ix86_bf16_type_node, BFmode); > + layout_type (ix86_bf16_type_node); > + > + if (!maybe_get_identifier ("__bf16") && TARGET_SSE2) > + { > + lang_hooks.types.register_builtin_type (ix86_bf16_type_node, > + "__bf16"); > + ix86_bf16_ptr_type_node = build_pointer_type (ix86_bf16_type_node); > + } > +} > + > static void > ix86_init_builtin_types (void) > { > @@ -1396,6 +1415,8 @@ ix86_init_builtin_types (void) > > ix86_register_float16_builtin_type (); > > + ix86_register_bf16_builtin_type (); > + > const_string_type_node > = build_pointer_type (build_qualified_type > (char_type_node, TYPE_QUAL_CONST)); diff --git > a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index > e2e1e18d24d..b49daaef253 100644 > --- a/gcc/config/i386/i386-modes.def > +++ b/gcc/config/i386/i386-modes.def > @@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see > FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format); > FLOAT_MODE (TF, 16, ieee_quad_format); FLOAT_MODE (HF, 2, > ieee_half_format); > +FLOAT_MODE (BF, 2, 0); > +ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format); > > /* In ILP32 mode, XFmode has size 12 and alignment 4. > In LP64 mode, XFmode has size and alignment 16. */ diff --git > a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index > e03f86d4a23..5d589f6a05c 100644 > --- a/gcc/config/i386/i386.cc > +++ b/gcc/config/i386/i386.cc > @@ -2399,6 +2399,7 @@ classify_argument (machine_mode mode, const_tree > type, > case E_CTImode: > return 0; > case E_HFmode: > + case E_BFmode: > if (!(bit_offset % 64)) > classes[0] = X86_64_SSEHF_CLASS; > else > @@ -2792,9 +2793,10 @@ construct_container (machine_mode mode, > machine_mode orig_mode, > intreg++; > break; > case X86_64_SSEHF_CLASS: > + tmpmode = (mode == BFmode ? BFmode : HFmode); > exp [nexps++] > = gen_rtx_EXPR_LIST (VOIDmode, > - gen_rtx_REG (HFmode, > + gen_rtx_REG (tmpmode, > GET_SSE_REGNO (sse_regno)), > GEN_INT (i*8)); > sse_regno++; > @@ -4001,8 +4003,8 @@ function_value_32 (machine_mode orig_mode, > machine_mode mode, > /* Most things go in %eax. */ > regno = AX_REG; > > - /* Return _Float16/_Complex _Foat16 by sse register. */ > - if (mode == HFmode) > + /* Return __bf16/ _Float16/_Complex _Foat16 by sse register. */ if > + (mode == HFmode || mode == BFmode) > regno = FIRST_SSE_REG; > if (mode == HCmode) > { > @@ -4050,6 +4052,7 @@ function_value_64 (machine_mode orig_mode, > machine_mode mode, > > switch (mode) > { > + case E_BFmode: > case E_HFmode: > case E_HCmode: > case E_SFmode: > @@ -5631,6 +5634,7 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands) > return "%vmovss\t{%1, %0|%0, %1}"; > > case MODE_HF: > + case MODE_BF: > if (REG_P (operands[0]) && REG_P (operands[1])) > return "vmovsh\t{%d1, %0|%0, %d1}"; > else > @@ -19402,7 +19406,8 @@ ix86_secondary_reload (bool in_p, rtx x, > reg_class_t rclass, > } > > /* Require movement to gpr, and then store to memory. */ > - if ((mode == HFmode || mode == HImode || mode == V2QImode) > + if ((mode == HFmode || mode == HImode || mode == V2QImode > + || mode == BFmode) > && !TARGET_SSE4_1 > && SSE_CLASS_P (rclass) > && !in_p && MEM_P (x)) > @@ -22331,7 +22336,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 && TARGET_SSE2) > + else if ((mode == HFmode || mode == BFmode) && TARGET_SSE2) > return true; > else > return default_scalar_mode_supported_p (mode); @@ -22646,6 +22651,8 > @@ ix86_mangle_type (const_tree type) > > switch (TYPE_MODE (type)) > { > + case E_BFmode: > + return "u6__bf16"; > case E_HFmode: > /* _Float16 is "DF16_". > Align with clang's decision in https://reviews.llvm.org/D33719. */ @@ - > 22661,6 +22668,55 @@ ix86_mangle_type (const_tree type) > } > } > > +/* Return the diagnostic message string if conversion from FROMTYPE to > + TOTYPE is not allowed, NULL otherwise. */ > + > +static const char * > +ix86_invalid_conversion (const_tree fromtype, const_tree totype) { > + if (element_mode (fromtype) != element_mode (totype)) > + { > + /* Do no allow conversions to/from BFmode scalar types. */ > + if (TYPE_MODE (fromtype) == BFmode) > + return N_("invalid conversion from type %<__bf16%>"); > + if (TYPE_MODE (totype) == BFmode) > + return N_("invalid conversion to type %<__bf16%>"); > + } > + > + /* Conversion allowed. */ > + return NULL; > +} > + > +/* Return the diagnostic message string if the unary operation OP is > + not permitted on TYPE, NULL otherwise. */ > + > +static const char * > +ix86_invalid_unary_op (int op, const_tree type) { > + /* Reject all single-operand operations on BFmode except for &. */ > + if (element_mode (type) == BFmode && op != ADDR_EXPR) > + return N_("operation not permitted on type %<__bf16%>"); > + > + /* Operation allowed. */ > + return NULL; > +} > + > +/* Return the diagnostic message string if the binary operation OP is > + not permitted on TYPE1 and TYPE2, NULL otherwise. */ > + > +static const char * > +ix86_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, > + const_tree type2) > +{ > + /* Reject all 2-operand operations on BFmode. */ > + if (element_mode (type1) == BFmode > + || element_mode (type2) == BFmode) > + return N_("operation not permitted on type %<__bf16%>"); > + > + /* Operation allowed. */ > + return NULL; > +} > + > static GTY(()) tree ix86_tls_stack_chk_guard_decl; > > static tree > @@ -24718,6 +24774,15 @@ ix86_libgcc_floating_mode_supported_p > #undef TARGET_MANGLE_TYPE > #define TARGET_MANGLE_TYPE ix86_mangle_type > > +#undef TARGET_INVALID_CONVERSION > +#define TARGET_INVALID_CONVERSION ix86_invalid_conversion > + > +#undef TARGET_INVALID_UNARY_OP > +#define TARGET_INVALID_UNARY_OP ix86_invalid_unary_op > + > +#undef TARGET_INVALID_BINARY_OP > +#define TARGET_INVALID_BINARY_OP ix86_invalid_binary_op > + > #undef TARGET_STACK_PROTECT_GUARD > #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index > f16df633e84..0da3dce1d31 100644 > --- a/gcc/config/i386/i386.h > +++ b/gcc/config/i386/i386.h > @@ -1046,7 +1046,7 @@ extern const char *host_detect_local_cpu (int argc, > const char **argv); > || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode > \ > || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode > \ > || (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode > \ > - || (MODE) == HFmode) > + || (MODE) == HFmode || (MODE) == BFmode) > > #define VALID_SSE_REG_MODE(MODE) \ > ((MODE) == V1TImode || (MODE) == TImode \ > @@ -1077,7 +1077,7 @@ extern const char *host_detect_local_cpu (int argc, > const char **argv); > || (MODE) == CQImode || (MODE) == CHImode > \ > || (MODE) == CSImode || (MODE) == CDImode > \ > || (MODE) == SDmode || (MODE) == DDmode \ > - || (MODE) == HFmode || (MODE) == HCmode \ > + || (MODE) == HFmode || (MODE) == HCmode || (MODE) == BFmode > \ > || (MODE) == V2HImode || (MODE) == V2HFmode > \ > || (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode > \ > || (TARGET_64BIT \ > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index > 9aaeb695f0f..1f7b018913a 100644 > --- a/gcc/config/i386/i386.md > +++ b/gcc/config/i386/i386.md > @@ -499,7 +499,7 @@ > > ;; Main data type used by the insn > (define_attr "mode" > - "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF, > + > + "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,BF,SF,DF,XF,TF,V32HF,V16HF,V8HF, > V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF" > (const_string "unknown")) > > @@ -1104,7 +1104,7 @@ > ;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on ;; > command line options just use GET_MODE_SIZE macro. > (define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8") > - (TI "16") (HF "2") (SF "4") (DF "8") > + (TI "16") (HF "2") (BF "2") (SF "4") (DF "8") > (XF "GET_MODE_SIZE (XFmode)") > (V16QI "16") (V32QI "32") (V64QI "64") > (V8HI "16") (V16HI "32") (V32HI "64") @@ -1248,7 > +1248,7 @@ (define_mode_iterator X87MODEF [SF DF XF]) > > ;; All x87 floating point modes plus HFmode -(define_mode_iterator > X87MODEFH [HF SF DF XF]) > +(define_mode_iterator X87MODEFH [HF SF DF XF BF]) > > ;; All SSE floating point modes > (define_mode_iterator SSEMODEF [HF SF DF TF]) @@ -3408,9 +3408,11 @@ > operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); > }) > > -(define_insn "*pushhf_rex64" > - [(set (match_operand:HF 0 "push_operand" "=X,X") > - (match_operand:HF 1 "nonmemory_no_elim_operand" "r,x"))] > +(define_mode_iterator HFBF [HF BF]) > + > +(define_insn "*push<mode>_rex64" > + [(set (match_operand:HFBF 0 "push_operand" "=X,X") > + (match_operand:HFBF 1 "nonmemory_no_elim_operand" "r,x"))] > "TARGET_64BIT" > { > /* Anything else should be already split before reg-stack. */ @@ -3421,9 > +3423,9 @@ > (set_attr "type" "push,multi") > (set_attr "mode" "DI,TI")]) > > -(define_insn "*pushhf" > - [(set (match_operand:HF 0 "push_operand" "=X,X") > - (match_operand:HF 1 "general_no_elim_operand" "rmF,x"))] > +(define_insn "*push<mode>" > + [(set (match_operand:HFBF 0 "push_operand" "=X,X") > + (match_operand:HFBF 1 "general_no_elim_operand" "rmF,x"))] > "!TARGET_64BIT" > { > /* Anything else should be already split before reg-stack. */ @@ -3462,7 > +3464,7 @@ > (set_attr "unit" "i387,*,*") > (set_attr "mode" "SF,SI,SF")]) > > -(define_mode_iterator MODESH [SF HF]) > +(define_mode_iterator MODESH [SF HF BF]) > ;; %%% Kill this when call knows how to work this out. > (define_split > [(set (match_operand:MODESH 0 "push_operand") @@ -3950,18 +3952,18 > @@ > ] > (const_string "*")))]) > > -(define_insn "*movhf_internal" > - [(set (match_operand:HF 0 "nonimmediate_operand" > +(define_insn "*mov<mode>_internal" > + [(set (match_operand:HFBF 0 "nonimmediate_operand" > "=?r,?r,?r,?m,v,v,?r,m,?v,v") > - (match_operand:HF 1 "general_operand" > + (match_operand:HFBF 1 "general_operand" > "r ,F ,m ,rF,C,v, v,v,r ,m"))] > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > && (lra_in_progress > || reload_completed > || !CONST_DOUBLE_P (operands[1]) > || (TARGET_SSE2 > - && standard_sse_constant_p (operands[1], HFmode) == 1) > - || memory_operand (operands[0], HFmode))" > + && standard_sse_constant_p (operands[1], <MODE>mode) == 1) > + || memory_operand (operands[0], <MODE>mode))" > { > switch (get_attr_type (insn)) > { > diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > new file mode 100644 > index 00000000000..962c8504775 > --- /dev/null > +++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > @@ -0,0 +1,10 @@ > +/* { dg-do assemble { target sse2} } */ > +/* { dg-options "-msse2 -O3 --save-temps" } */ > + > +void foo (void) > +{ > + __bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} } */ > + __bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type > +'__bf16'} } */ > + __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} > +} */ > + __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } > +*/ } > diff --git a/gcc/testsuite/gcc.target/i386/bfloat16-1.c > b/gcc/testsuite/gcc.target/i386/bfloat16-1.c > new file mode 100644 > index 00000000000..6aaec28efd2 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/bfloat16-1.c > @@ -0,0 +1,12 @@ > +/* { dg-do compile } */ > +/* { dg-options "-msse2 -O2" } */ > +__bf16 > +foo (int a) > +{ > + union { > + int a; > + __bf16 b; > + }c; > + c.a = a; > + return c.b; > +} > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > new file mode 100644 > index 00000000000..612d55be826 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > @@ -0,0 +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; > +} > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > new file mode 100644 > index 00000000000..a3286e26c48 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > @@ -0,0 +1,17 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -msse2 -mno-avx512f" } */ > + > +union flt > +{ > + __bf16 flt; > + short s; > +}; > + > +__bf16 > +foo (union flt x) > +{ > + return x.flt; > +} > + > +/* { dg-final { scan-assembler {(?n)pinsrw[\t ].*%xmm0} { target ia32 } > +} } */ > +/* { dg-final { scan-assembler {(?n)movd[\t ].*%xmm0} { target { ! ia32 > +} } } } */ > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c > b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c > new file mode 100644 > index 00000000000..f76d5547758 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c > @@ -0,0 +1,215 @@ > +/* { dg-do compile } */ > +/* { dg-options "-msse2 -O2" } */ > + > + > +__bf16 glob_bfloat; > + > +int is_an_int; > +short is_a_short_int; > +float is_a_float; > +float is_a_float16; > +double is_a_double; > + > +float *float_ptr; > + > +__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid > +conversion to type '__bf16'} } */ > +__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error > +{invalid conversion to type '__bf16'} } */ > + > +__bf16 footest (__bf16 scalar0) > +{ > + > + /* Initialisation */ > + > + __bf16 scalar1_1; > + __bf16 scalar1_2 = glob_bfloat; > + __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ > + __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to > + type '__bf16'} } */ > + __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to > + type '__bf16'} } */ > + __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to > + type '__bf16'} } */ > + __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to > + type '__bf16'} } */ > + __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion > + to type '__bf16'} } */ > + > + int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from > + type '__bf16'} } */ float initi_1_2 = glob_bfloat; /* { dg-error > + {invalid conversion from type '__bf16'} } */ > + _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion > + from type '__bf16'} } */ short initi_1_4 = glob_bfloat; /* { dg-error > + {invalid conversion from type '__bf16'} } */ double initi_1_5 = > + glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } > + */ > + > + __bf16 scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */ > + __bf16 scalar2_2 = { glob_bfloat }; > + __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion > + to type '__bf16'} } */ > + __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion > + to type '__bf16'} } */ > + __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid > + conversion to type '__bf16'} } */ > + __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion > + to type '__bf16'} } */ > + __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid > + conversion to type '__bf16'} } */ > + > + int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion > + from type '__bf16'} } */ float initi_2_2 = { glob_bfloat }; /* { > + dg-error {invalid conversion from type '__bf16'} } */ > + _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid > + conversion from type '__bf16'} } */ short initi_2_4 = { glob_bfloat > + }; /* { dg-error {invalid conversion from type '__bf16'} } */ double > + initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from > + type '__bf16'} } */ > + > + /* Assignments. */ > + > + glob_bfloat = glob_bfloat; > + glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ > + glob_bfloat = 0.1; /* { dg-error {invalid conversion to type > + '__bf16'} } */ glob_bfloat = is_a_float; /* { dg-error {invalid > + conversion to type '__bf16'} } */ glob_bfloat = is_an_int; /* { > + dg-error {invalid conversion to type '__bf16'} } */ glob_bfloat = > + is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ > + glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type > + '__bf16'} } */ glob_bfloat = is_a_short_int; /* { dg-error {invalid > + conversion to type '__bf16'} } */ > + > + is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type > + '__bf16'} } */ is_a_float = glob_bfloat; /* { dg-error {invalid > + conversion from type '__bf16'} } */ > + is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from > + type '__bf16'} } */ is_a_double = glob_bfloat; /* { dg-error {invalid > + conversion from type '__bf16'} } */ is_a_short_int = glob_bfloat; /* > + { dg-error {invalid conversion from type '__bf16'} } */ > + > + /* Casting. */ > + > + (void) glob_bfloat; > + (__bf16) glob_bfloat; > + > + (int) glob_bfloat; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (float) glob_bfloat; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (double) glob_bfloat; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (short) glob_bfloat; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + > + (__bf16) is_an_int; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) is_a_float; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) is_a_float16; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) is_a_double; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + > + /* Compound literals. */ > + > + (__bf16) {}; /* { dg-error {empty scalar initializer} } */ > + (__bf16) { glob_bfloat }; > + (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } > + */ > + (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} > + } */ > + (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type > + '__bf16'} } */ > + (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to > + type '__bf16'} } */ > + > + (int) { glob_bfloat }; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (float) { glob_bfloat }; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from > + type '__bf16'} } */ > + (double) { glob_bfloat }; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + (short) { glob_bfloat }; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + > + /* Arrays and Structs. */ > + > + typedef __bf16 array_type[2]; > + extern __bf16 extern_array[]; > + > + __bf16 array[2]; > + __bf16 zero_length_array[0]; > + __bf16 empty_init_array[] = {}; > + typedef __bf16 some_other_type[is_an_int]; > + > + struct struct1 { > + __bf16 a; > + }; > + > + union union1 { > + __bf16 a; > + }; > + > + /* Addressing and dereferencing. */ > + > + __bf16 *bfloat_ptr = &scalar0; > + scalar0 = *bfloat_ptr; > + > + /* Pointer assignment. */ > + > + __bf16 *bfloat_ptr2 = bfloat_ptr; > + __bf16 *bfloat_ptr3 = array; > + > + /* Pointer arithmetic. */ > + > + ++bfloat_ptr; > + --bfloat_ptr; > + bfloat_ptr++; > + bfloat_ptr--; > + bfloat_ptr += 1; > + bfloat_ptr -= 1; > + bfloat_ptr - bfloat_ptr2; > + bfloat_ptr = &bfloat_ptr3[0]; > + bfloat_ptr = &bfloat_ptr3[1]; > + > + /* Simple comparison. */ > + scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type > + '__bf16'} } */ glob_bfloat == scalar0; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + scalar0 > is_a_float; /* { dg-error {operation not permitted on type > + '__bf16'} } */ is_a_float == scalar0; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} > + } */ > + 0 == scalar0; /* { dg-error {operation not permitted on type > + '__bf16'} } */ > + scalar0 > 0.1; /* { dg-error {operation not permitted on type > + '__bf16'} } */ > + 0.1 == scalar0; /* { dg-error {operation not permitted on type > + '__bf16'} } */ > + scalar0 > is_an_int; /* { dg-error {operation not permitted on type > + '__bf16'} } */ is_an_int == scalar0; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + > + /* Pointer comparison. */ > + > + bfloat_ptr == &scalar0; > + bfloat_ptr != &scalar0; > + bfloat_ptr < &scalar0; > + bfloat_ptr <= &scalar0; > + bfloat_ptr > &scalar0; > + bfloat_ptr >= &scalar0; > + bfloat_ptr == bfloat_ptr2; > + bfloat_ptr != bfloat_ptr2; > + bfloat_ptr < bfloat_ptr2; > + bfloat_ptr <= bfloat_ptr2; > + bfloat_ptr > bfloat_ptr2; > + bfloat_ptr >= bfloat_ptr2; > + > + /* Conditional expressions. */ > + > + 0 ? scalar0 : scalar0; > + 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} > + } */ > + 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} > + } */ > + 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type > + '__bf16'} } */ > + 0 ? bfloat_ptr : bfloat_ptr2; > + 0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in > + conditional expression} } */ > + 0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in > + conditional expression} } */ > + > + scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted > + on type '__bf16'} } */ > + scalar0 ? is_a_float : scalar0; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + > + /* Unary operators. */ > + > + +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } > + */ -scalar0; /* { dg-error {operation not permitted on type '__bf16'} > + } */ ~scalar0; /* { dg-error {operation not permitted on type > + '__bf16'} } */ !scalar0; /* { dg-error {operation not permitted on > + type '__bf16'} } */ *scalar0; /* { dg-error {invalid type argument of > + unary '\*'} } */ __real scalar0; /* { dg-error {operation not > + permitted on type '__bf16'} } */ __imag scalar0; /* { dg-error > + {operation not permitted on type '__bf16'} } */ ++scalar0; /* { > + dg-error {operation not permitted on type '__bf16'} } */ --scalar0; > + /* { dg-error {operation not permitted on type '__bf16'} } */ > + scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } > + */ scalar0--; /* { dg-error {operation not permitted on type > + '__bf16'} } */ > + > + /* Binary arithmetic operations. */ > + > + scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted > + on type '__bf16'} } */ > + scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on > + type '__bf16'} } */ > + scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not > + permitted on type '__bf16'} } */ > + > + return scalar0; > +} > + > -- > 2.18.2 [-- Attachment #2: 0001-Enable-__bf16-type-for-TARGET_SSE2-and-above.patch --] [-- Type: application/octet-stream, Size: 28791 bytes --] From 72c77ade48cb99dab997b4c1910101bac4eb2499 Mon Sep 17 00:00:00 2001 From: konglingling7 <lingling.kong@intel.com> Date: Wed, 15 Jun 2022 14:12:12 +0800 Subject: [PATCH] Enable __bf16 type for TARGET_SSE2 and above gcc/ChangeLog: * config/i386/i386-builtin-types.def (BFLOAT16): New primitive type. * config/i386/i386-builtins.cc : Support __bf16 type for i386 backend. (ix86_register_bf16_builtin_type): New function. (ix86_bf16_type_node): New. (ix86_bf16_ptr_type_node): Ditto. (ix86_init_builtin_types): Add ix86_register_bf16_builtin_type function call. * config/i386/i386-modes.def (FLOAT_MODE): Add BFmode. (ADJUST_FLOAT_FORMAT): Ditto. * config/i386/i386.cc (merge_classes): Handle BFmode. (classify_argument): Ditto. (examine_argument): Ditto. (construct_container): Ditto. (function_value_32): Return __bf16 by %xmm0. (function_value_64): Return __bf16 by SSE register. (ix86_print_operand): Handle CONST_DOUBLE BFmode. (ix86_legitimate_constant_p): Disable BFmode constant double. (ix86_secondary_reload): Require gpr as intermediate register to store __bf16 from sse register when sse4 is not available. (ix86_scalar_mode_supported_p): Enable __bf16 under sse2. (ix86_mangle_type): Add manlging for __bf16 type. (ix86_invalid_conversion): New function for target hook. (ix86_invalid_unary_op): Ditto. (ix86_invalid_binary_op): Ditto. (TARGET_INVALID_CONVERSION): New define for target hook. (TARGET_INVALID_UNARY_OP): Ditto. (TARGET_INVALID_BINARY_OP): Ditto. * config/i386/i386.h (host_detect_local_cpu): Add BFmode. * config/i386/i386.md (*pushhf_rex64): Change for BFmode. (*push<mode>_rex64): Ditto. (*pushhf): Ditto. (*push<mode>): Ditto. (hfbfconstf): Add new define_mode_attr. (*mov<mode>_internal): Add BFmode. gcc/testsuite/ChangeLog: * g++.target/i386/bfloat_cpp_typecheck.C: New test. * gcc.target/i386/bfloat16-1.c: Ditto. * gcc.target/i386/sse2-bfloat16-1.c: Ditto. * gcc.target/i386/sse2-bfloat16-2.c: Ditto. * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Ditto. --- gcc/config/i386/i386-builtin-types.def | 1 + gcc/config/i386/i386-builtins.cc | 21 ++ gcc/config/i386/i386-modes.def | 2 + gcc/config/i386/i386.cc | 80 ++++++- gcc/config/i386/i386.h | 4 +- gcc/config/i386/i386.md | 45 ++-- .../g++.target/i386/bfloat_cpp_typecheck.C | 10 + gcc/testsuite/gcc.target/i386/bfloat16-1.c | 12 + .../gcc.target/i386/sse2-bfloat16-1.c | 8 + .../gcc.target/i386/sse2-bfloat16-2.c | 17 ++ .../i386/sse2-bfloat16-scalar-typecheck.c | 215 ++++++++++++++++++ 11 files changed, 391 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C create mode 100644 gcc/testsuite/gcc.target/i386/bfloat16-1.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 7a2da1db0b0..63a360b0f8b 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -69,6 +69,7 @@ DEF_PRIMITIVE_TYPE (UINT16, short_unsigned_type_node) DEF_PRIMITIVE_TYPE (INT64, long_long_integer_type_node) DEF_PRIMITIVE_TYPE (UINT64, long_long_unsigned_type_node) DEF_PRIMITIVE_TYPE (FLOAT16, ix86_float16_type_node) +DEF_PRIMITIVE_TYPE (BFLOAT16, ix86_bf16_type_node) DEF_PRIMITIVE_TYPE (FLOAT, float_type_node) DEF_PRIMITIVE_TYPE (DOUBLE, double_type_node) DEF_PRIMITIVE_TYPE (FLOAT80, float80_type_node) diff --git a/gcc/config/i386/i386-builtins.cc b/gcc/config/i386/i386-builtins.cc index fe7243c3837..6a04fb57e65 100644 --- a/gcc/config/i386/i386-builtins.cc +++ b/gcc/config/i386/i386-builtins.cc @@ -126,6 +126,9 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX, static GTY(()) tree ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1]; tree ix86_float16_type_node = NULL_TREE; +tree ix86_bf16_type_node = NULL_TREE; +tree ix86_bf16_ptr_type_node = NULL_TREE; + /* Retrieve an element from the above table, building some of the types lazily. */ @@ -1366,6 +1369,22 @@ ix86_register_float16_builtin_type (void) "_Float16"); } +static void +ix86_register_bf16_builtin_type (void) +{ + ix86_bf16_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ix86_bf16_type_node) = 16; + SET_TYPE_MODE (ix86_bf16_type_node, BFmode); + layout_type (ix86_bf16_type_node); + + if (!maybe_get_identifier ("__bf16") && TARGET_SSE2) + { + lang_hooks.types.register_builtin_type (ix86_bf16_type_node, + "__bf16"); + ix86_bf16_ptr_type_node = build_pointer_type (ix86_bf16_type_node); + } +} + static void ix86_init_builtin_types (void) { @@ -1396,6 +1415,8 @@ ix86_init_builtin_types (void) ix86_register_float16_builtin_type (); + ix86_register_bf16_builtin_type (); + const_string_type_node = build_pointer_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST)); diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index e2e1e18d24d..b49daaef253 100644 --- a/gcc/config/i386/i386-modes.def +++ b/gcc/config/i386/i386-modes.def @@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format); FLOAT_MODE (TF, 16, ieee_quad_format); FLOAT_MODE (HF, 2, ieee_half_format); +FLOAT_MODE (BF, 2, 0); +ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format); /* In ILP32 mode, XFmode has size 12 and alignment 4. In LP64 mode, XFmode has size and alignment 16. */ diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 5e30dc884bf..87b48bac7be 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -2399,6 +2399,7 @@ classify_argument (machine_mode mode, const_tree type, case E_CTImode: return 0; case E_HFmode: + case E_BFmode: if (!(bit_offset % 64)) classes[0] = X86_64_SSEHF_CLASS; else @@ -2792,9 +2793,10 @@ construct_container (machine_mode mode, machine_mode orig_mode, intreg++; break; case X86_64_SSEHF_CLASS: + tmpmode = (mode == BFmode ? BFmode : HFmode); exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_REG (HFmode, + gen_rtx_REG (tmpmode, GET_SSE_REGNO (sse_regno)), GEN_INT (i*8)); sse_regno++; @@ -4001,8 +4003,8 @@ function_value_32 (machine_mode orig_mode, machine_mode mode, /* Most things go in %eax. */ regno = AX_REG; - /* Return _Float16/_Complex _Foat16 by sse register. */ - if (mode == HFmode) + /* Return __bf16/ _Float16/_Complex _Foat16 by sse register. */ + if (mode == HFmode || mode == BFmode) regno = FIRST_SSE_REG; if (mode == HCmode) { @@ -4050,6 +4052,7 @@ function_value_64 (machine_mode orig_mode, machine_mode mode, switch (mode) { + case E_BFmode: case E_HFmode: case E_HCmode: case E_SFmode: @@ -5631,6 +5634,7 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands) return "%vmovss\t{%1, %0|%0, %1}"; case MODE_HF: + case MODE_BF: if (REG_P (operands[0]) && REG_P (operands[1])) return "vmovsh\t{%d1, %0|%0, %d1}"; else @@ -10648,6 +10652,11 @@ ix86_legitimate_constant_p (machine_mode mode, rtx x) case CONST_VECTOR: if (!standard_sse_constant_p (x, mode)) return false; + break; + + case CONST_DOUBLE: + if (mode == E_BFmode) + return false; default: break; @@ -19415,7 +19424,8 @@ ix86_secondary_reload (bool in_p, rtx x, reg_class_t rclass, } /* Require movement to gpr, and then store to memory. */ - if ((mode == HFmode || mode == HImode || mode == V2QImode) + if ((mode == HFmode || mode == HImode || mode == V2QImode + || mode == BFmode) && !TARGET_SSE4_1 && SSE_CLASS_P (rclass) && !in_p && MEM_P (x)) @@ -22344,7 +22354,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 && TARGET_SSE2) + else if ((mode == HFmode || mode == BFmode) && TARGET_SSE2) return true; else return default_scalar_mode_supported_p (mode); @@ -22659,6 +22669,8 @@ ix86_mangle_type (const_tree type) switch (TYPE_MODE (type)) { + case E_BFmode: + return "u6__bf16"; case E_HFmode: /* _Float16 is "DF16_". Align with clang's decision in https://reviews.llvm.org/D33719. */ @@ -22674,6 +22686,55 @@ ix86_mangle_type (const_tree type) } } +/* Return the diagnostic message string if conversion from FROMTYPE to + TOTYPE is not allowed, NULL otherwise. */ + +static const char * +ix86_invalid_conversion (const_tree fromtype, const_tree totype) +{ + if (element_mode (fromtype) != element_mode (totype)) + { + /* Do no allow conversions to/from BFmode scalar types. */ + if (TYPE_MODE (fromtype) == BFmode) + return N_("invalid conversion from type %<__bf16%>"); + if (TYPE_MODE (totype) == BFmode) + return N_("invalid conversion to type %<__bf16%>"); + } + + /* Conversion allowed. */ + return NULL; +} + +/* Return the diagnostic message string if the unary operation OP is + not permitted on TYPE, NULL otherwise. */ + +static const char * +ix86_invalid_unary_op (int op, const_tree type) +{ + /* Reject all single-operand operations on BFmode except for &. */ + if (element_mode (type) == BFmode && op != ADDR_EXPR) + return N_("operation not permitted on type %<__bf16%>"); + + /* Operation allowed. */ + return NULL; +} + +/* Return the diagnostic message string if the binary operation OP is + not permitted on TYPE1 and TYPE2, NULL otherwise. */ + +static const char * +ix86_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, + const_tree type2) +{ + /* Reject all 2-operand operations on BFmode. */ + if (element_mode (type1) == BFmode + || element_mode (type2) == BFmode) + return N_("operation not permitted on type %<__bf16%>"); + + /* Operation allowed. */ + return NULL; +} + static GTY(()) tree ix86_tls_stack_chk_guard_decl; static tree @@ -24731,6 +24792,15 @@ ix86_libgcc_floating_mode_supported_p #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE ix86_mangle_type +#undef TARGET_INVALID_CONVERSION +#define TARGET_INVALID_CONVERSION ix86_invalid_conversion + +#undef TARGET_INVALID_UNARY_OP +#define TARGET_INVALID_UNARY_OP ix86_invalid_unary_op + +#undef TARGET_INVALID_BINARY_OP +#define TARGET_INVALID_BINARY_OP ix86_invalid_binary_op + #undef TARGET_STACK_PROTECT_GUARD #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f16df633e84..0da3dce1d31 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1046,7 +1046,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \ || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \ || (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode \ - || (MODE) == HFmode) + || (MODE) == HFmode || (MODE) == BFmode) #define VALID_SSE_REG_MODE(MODE) \ ((MODE) == V1TImode || (MODE) == TImode \ @@ -1077,7 +1077,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (MODE) == CQImode || (MODE) == CHImode \ || (MODE) == CSImode || (MODE) == CDImode \ || (MODE) == SDmode || (MODE) == DDmode \ - || (MODE) == HFmode || (MODE) == HCmode \ + || (MODE) == HFmode || (MODE) == HCmode || (MODE) == BFmode \ || (MODE) == V2HImode || (MODE) == V2HFmode \ || (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode \ || (TARGET_64BIT \ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index f1158e1356b..b0eb76d3bcb 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -499,7 +499,7 @@ ;; Main data type used by the insn (define_attr "mode" - "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF, + "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,BF,SF,DF,XF,TF,V32HF,V16HF,V8HF, V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF" (const_string "unknown")) @@ -1104,7 +1104,7 @@ ;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on ;; command line options just use GET_MODE_SIZE macro. (define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8") - (TI "16") (HF "2") (SF "4") (DF "8") + (TI "16") (HF "2") (BF "2") (SF "4") (DF "8") (XF "GET_MODE_SIZE (XFmode)") (V16QI "16") (V32QI "32") (V64QI "64") (V8HI "16") (V16HI "32") (V32HI "64") @@ -1248,7 +1248,7 @@ (define_mode_iterator X87MODEF [SF DF XF]) ;; All x87 floating point modes plus HFmode -(define_mode_iterator X87MODEFH [HF SF DF XF]) +(define_mode_iterator X87MODEFH [HF SF DF XF BF]) ;; All SSE floating point modes (define_mode_iterator SSEMODEF [HF SF DF TF]) @@ -3408,9 +3408,11 @@ operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); }) -(define_insn "*pushhf_rex64" - [(set (match_operand:HF 0 "push_operand" "=X,X") - (match_operand:HF 1 "nonmemory_no_elim_operand" "r,x"))] +(define_mode_iterator HFBF [HF BF]) + +(define_insn "*push<mode>_rex64" + [(set (match_operand:HFBF 0 "push_operand" "=X,X") + (match_operand:HFBF 1 "nonmemory_no_elim_operand" "r,x"))] "TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -3421,9 +3423,9 @@ (set_attr "type" "push,multi") (set_attr "mode" "DI,TI")]) -(define_insn "*pushhf" - [(set (match_operand:HF 0 "push_operand" "=X,X") - (match_operand:HF 1 "general_no_elim_operand" "rmF,x"))] +(define_insn "*push<mode>" + [(set (match_operand:HFBF 0 "push_operand" "=X,X") + (match_operand:HFBF 1 "general_no_elim_operand" "rmF,x"))] "!TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -3462,7 +3464,7 @@ (set_attr "unit" "i387,*,*") (set_attr "mode" "SF,SI,SF")]) -(define_mode_iterator MODESH [SF HF]) +(define_mode_iterator MODESH [SF HF BF]) ;; %%% Kill this when call knows how to work this out. (define_split [(set (match_operand:MODESH 0 "push_operand") @@ -3950,18 +3952,21 @@ ] (const_string "*")))]) -(define_insn "*movhf_internal" - [(set (match_operand:HF 0 "nonimmediate_operand" +(define_mode_attr hfbfconstf + [(HF "F") (BF "")]) + +(define_insn "*mov<mode>_internal" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "=?r,?r,?r,?m,v,v,?r,m,?v,v") - (match_operand:HF 1 "general_operand" - "r ,F ,m ,rF,C,v, v,v,r ,m"))] + (match_operand:HFBF 1 "general_operand" + "r ,F ,m ,r<hfbfconstf>,C,v, v,v,r ,m"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (lra_in_progress || reload_completed || !CONST_DOUBLE_P (operands[1]) || (TARGET_SSE2 - && standard_sse_constant_p (operands[1], HFmode) == 1) - || memory_operand (operands[0], HFmode))" + && standard_sse_constant_p (operands[1], <MODE>mode) == 1) + || memory_operand (operands[0], <MODE>mode))" { switch (get_attr_type (insn)) { @@ -4056,7 +4061,13 @@ (not (match_test "TARGET_HIMODE_MATH")))) (const_string "SI") ] - (const_string "HI")))]) + (const_string "HI"))) + (set (attr "enabled") + (cond [(and (match_test "<MODE>mode == BFmode") + (eq_attr "alternative" "1")) + (symbol_ref "false") + ] + (const_string "*")))]) (define_split [(set (match_operand 0 "any_fp_register_operand") diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C new file mode 100644 index 00000000000..5152336efe6 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O3 --save-temps" } */ + +void foo (void) +{ + __bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} "" { xfail *-*-* } } */ + __bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type '__bf16'} "" { xfail *-*-* } } */ + __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } */ +} diff --git a/gcc/testsuite/gcc.target/i386/bfloat16-1.c b/gcc/testsuite/gcc.target/i386/bfloat16-1.c new file mode 100644 index 00000000000..6aaec28efd2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/bfloat16-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O2" } */ +__bf16 +foo (int a) +{ + union { + int a; + __bf16 b; + }c; + c.a = a; + return c.b; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c new file mode 100644 index 00000000000..612d55be826 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c @@ -0,0 +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; +} diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c new file mode 100644 index 00000000000..a3286e26c48 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -msse2 -mno-avx512f" } */ + +union flt +{ + __bf16 flt; + short s; +}; + +__bf16 +foo (union flt x) +{ + return x.flt; +} + +/* { dg-final { scan-assembler {(?n)pinsrw[\t ].*%xmm0} { target ia32 } } } */ +/* { dg-final { scan-assembler {(?n)movd[\t ].*%xmm0} { target { ! ia32 } } } } */ diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c new file mode 100644 index 00000000000..f76d5547758 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c @@ -0,0 +1,215 @@ +/* { dg-do compile } */ +/* { dg-options "-msse2 -O2" } */ + + +__bf16 glob_bfloat; + +int is_an_int; +short is_a_short_int; +float is_a_float; +float is_a_float16; +double is_a_double; + +float *float_ptr; + +__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */ +__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error {invalid conversion to type '__bf16'} } */ + +__bf16 footest (__bf16 scalar0) +{ + + /* Initialisation */ + + __bf16 scalar1_1; + __bf16 scalar1_2 = glob_bfloat; + __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + + int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + float initi_1_2 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + short initi_1_4 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + double initi_1_5 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + + __bf16 scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */ + __bf16 scalar2_2 = { glob_bfloat }; + __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */ + __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ + + int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + float initi_2_2 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + short initi_2_4 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + double initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + + /* Assignments. */ + + glob_bfloat = glob_bfloat; + glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = 0.1; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */ + glob_bfloat = is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + + is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + is_a_float = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + is_a_double = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + is_a_short_int = glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + + /* Casting. */ + + (void) glob_bfloat; + (__bf16) glob_bfloat; + + (int) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + (float) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + (double) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + (short) glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } */ + + (__bf16) is_an_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) is_a_float; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) is_a_double; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type '__bf16'} } */ + + /* Compound literals. */ + + (__bf16) {}; /* { dg-error {empty scalar initializer} } */ + (__bf16) { glob_bfloat }; + (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type '__bf16'} } */ + (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to type '__bf16'} } */ + + (int) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + (float) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + (double) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + (short) { glob_bfloat }; /* { dg-error {invalid conversion from type '__bf16'} } */ + + /* Arrays and Structs. */ + + typedef __bf16 array_type[2]; + extern __bf16 extern_array[]; + + __bf16 array[2]; + __bf16 zero_length_array[0]; + __bf16 empty_init_array[] = {}; + typedef __bf16 some_other_type[is_an_int]; + + struct struct1 { + __bf16 a; + }; + + union union1 { + __bf16 a; + }; + + /* Addressing and dereferencing. */ + + __bf16 *bfloat_ptr = &scalar0; + scalar0 = *bfloat_ptr; + + /* Pointer assignment. */ + + __bf16 *bfloat_ptr2 = bfloat_ptr; + __bf16 *bfloat_ptr3 = array; + + /* Pointer arithmetic. */ + + ++bfloat_ptr; + --bfloat_ptr; + bfloat_ptr++; + bfloat_ptr--; + bfloat_ptr += 1; + bfloat_ptr -= 1; + bfloat_ptr - bfloat_ptr2; + bfloat_ptr = &bfloat_ptr3[0]; + bfloat_ptr = &bfloat_ptr3[1]; + + /* Simple comparison. */ + scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type '__bf16'} } */ + glob_bfloat == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 > is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ + is_a_float == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} } */ + 0 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 > 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ + 0.1 == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 > is_an_int; /* { dg-error {operation not permitted on type '__bf16'} } */ + is_an_int == scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + + /* Pointer comparison. */ + + bfloat_ptr == &scalar0; + bfloat_ptr != &scalar0; + bfloat_ptr < &scalar0; + bfloat_ptr <= &scalar0; + bfloat_ptr > &scalar0; + bfloat_ptr >= &scalar0; + bfloat_ptr == bfloat_ptr2; + bfloat_ptr != bfloat_ptr2; + bfloat_ptr < bfloat_ptr2; + bfloat_ptr <= bfloat_ptr2; + bfloat_ptr > bfloat_ptr2; + bfloat_ptr >= bfloat_ptr2; + + /* Conditional expressions. */ + + 0 ? scalar0 : scalar0; + 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type '__bf16'} } */ + 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */ + 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} } */ + 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} } */ + 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type '__bf16'} } */ + 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type '__bf16'} } */ + 0 ? bfloat_ptr : bfloat_ptr2; + 0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ + 0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ + + scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 ? is_a_float : scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ + + /* Unary operators. */ + + +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + -scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + ~scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + !scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + *scalar0; /* { dg-error {invalid type argument of unary '\*'} } */ + __real scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + __imag scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + ++scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + --scalar0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0--; /* { dg-error {operation not permitted on type '__bf16'} } */ + + /* Binary arithmetic operations. */ + + scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on type '__bf16'} } */ + scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not permitted on type '__bf16'} } */ + + return scalar0; +} + -- 2.18.2 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above 2022-08-03 8:40 ` Kong, Lingling @ 2022-08-04 4:35 ` Hongtao Liu 0 siblings, 0 replies; 3+ messages in thread From: Hongtao Liu @ 2022-08-04 4:35 UTC (permalink / raw) To: Kong, Lingling; +Cc: Liu, Hongtao, gcc-patches On Wed, Aug 3, 2022 at 4:41 PM Kong, Lingling via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > Hi, > > Old patch has some mistake in `*movbf_internal` , now disable BFmode constant double move in `*movbf_internal`. LGTM. > > Thanks, > Lingling > > > -----Original Message----- > > From: Kong, Lingling <lingling.kong@intel.com> > > Sent: Tuesday, July 26, 2022 9:31 AM > > To: Liu, Hongtao <hongtao.liu@intel.com>; gcc-patches@gcc.gnu.org > > Cc: Kong, Lingling <lingling.kong@intel.com> > > Subject: [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above > > > > Hi, > > > > The patch is enable __bf16 scalar type for target sse2 and above according to > > psABI(https://gitlab.com/x86-psABIs/x86-64-ABI/-/merge_requests/35/diffs). > > The __bf16 type is a storage type like arm. > > > > OK for master? > > > > gcc/ChangeLog: > > > > * config/i386/i386-builtin-types.def (BFLOAT16): New primitive type. > > * config/i386/i386-builtins.cc : Support __bf16 type for i386 backend. > > (ix86_register_bf16_builtin_type): New function. > > (ix86_bf16_type_node): New. > > (ix86_bf16_ptr_type_node): Ditto. > > (ix86_init_builtin_types): Add ix86_register_bf16_builtin_type function > > call. > > * config/i386/i386-modes.def (FLOAT_MODE): Add BFmode. > > (ADJUST_FLOAT_FORMAT): Ditto. > > * config/i386/i386.cc (merge_classes): Handle BFmode. > > (classify_argument): Ditto. > > (examine_argument): Ditto. > > (construct_container): Ditto. > > (function_value_32): Return __bf16 by %xmm0. > > (function_value_64): Return __bf16 by SSE register. > > (ix86_print_operand): Handle CONST_DOUBLE BFmode. > > (ix86_secondary_reload): Require gpr as intermediate register > > to store __bf16 from sse register when sse4 is not available. > > (ix86_scalar_mode_supported_p): Enable __bf16 under sse2. > > (ix86_mangle_type): Add manlging for __bf16 type. > > (ix86_invalid_conversion): New function for target hook. > > (ix86_invalid_unary_op): Ditto. > > (ix86_invalid_binary_op): Ditto. > > (TARGET_INVALID_CONVERSION): New define for target hook. > > (TARGET_INVALID_UNARY_OP): Ditto. > > (TARGET_INVALID_BINARY_OP): Ditto. > > * config/i386/i386.h (host_detect_local_cpu): Add BFmode. > > * config/i386/i386.md (*pushhf_rex64): Change for BFmode. > > (*push<mode>_rex64): Ditto. > > (*pushhf): Ditto. > > (*push<mode>): Ditto. > > (*movhf_internal): Ditto. > > (*mov<mode>_internal): Ditto. > > > > gcc/testsuite/ChangeLog: > > > > * g++.target/i386/bfloat_cpp_typecheck.C: New test. > > * gcc.target/i386/bfloat16-1.c: Ditto. > > * gcc.target/i386/sse2-bfloat16-1.c: Ditto. > > * gcc.target/i386/sse2-bfloat16-2.c: Ditto. > > * gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Ditto. > > --- > > gcc/config/i386/i386-builtin-types.def | 1 + > > gcc/config/i386/i386-builtins.cc | 21 ++ > > gcc/config/i386/i386-modes.def | 2 + > > gcc/config/i386/i386.cc | 75 +++++- > > gcc/config/i386/i386.h | 4 +- > > gcc/config/i386/i386.md | 32 +-- > > .../g++.target/i386/bfloat_cpp_typecheck.C | 10 + > > gcc/testsuite/gcc.target/i386/bfloat16-1.c | 12 + > > .../gcc.target/i386/sse2-bfloat16-1.c | 8 + > > .../gcc.target/i386/sse2-bfloat16-2.c | 17 ++ > > .../i386/sse2-bfloat16-scalar-typecheck.c | 215 ++++++++++++++++++ > > 11 files changed, 375 insertions(+), 22 deletions(-) create mode 100644 > > gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > > create mode 100644 gcc/testsuite/gcc.target/i386/bfloat16-1.c > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > > create mode 100644 gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar- > > typecheck.c > > > > diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386- > > builtin-types.def > > index 7a2da1db0b0..63a360b0f8b 100644 > > --- a/gcc/config/i386/i386-builtin-types.def > > +++ b/gcc/config/i386/i386-builtin-types.def > > @@ -69,6 +69,7 @@ DEF_PRIMITIVE_TYPE (UINT16, > > short_unsigned_type_node) DEF_PRIMITIVE_TYPE (INT64, > > long_long_integer_type_node) DEF_PRIMITIVE_TYPE (UINT64, > > long_long_unsigned_type_node) DEF_PRIMITIVE_TYPE (FLOAT16, > > ix86_float16_type_node) > > +DEF_PRIMITIVE_TYPE (BFLOAT16, ix86_bf16_type_node) > > DEF_PRIMITIVE_TYPE (FLOAT, float_type_node) DEF_PRIMITIVE_TYPE > > (DOUBLE, double_type_node) DEF_PRIMITIVE_TYPE (FLOAT80, > > float80_type_node) diff --git a/gcc/config/i386/i386-builtins.cc > > b/gcc/config/i386/i386-builtins.cc > > index fe7243c3837..6a04fb57e65 100644 > > --- a/gcc/config/i386/i386-builtins.cc > > +++ b/gcc/config/i386/i386-builtins.cc > > @@ -126,6 +126,9 @@ BDESC_VERIFYS (IX86_BUILTIN_MAX, static GTY(()) tree > > ix86_builtin_type_tab[(int) IX86_BT_LAST_CPTR + 1]; > > > > tree ix86_float16_type_node = NULL_TREE; > > +tree ix86_bf16_type_node = NULL_TREE; > > +tree ix86_bf16_ptr_type_node = NULL_TREE; > > + > > /* Retrieve an element from the above table, building some of > > the types lazily. */ > > > > @@ -1366,6 +1369,22 @@ ix86_register_float16_builtin_type (void) > > "_Float16"); > > } > > > > +static void > > +ix86_register_bf16_builtin_type (void) > > +{ > > + ix86_bf16_type_node = make_node (REAL_TYPE); > > + TYPE_PRECISION (ix86_bf16_type_node) = 16; > > + SET_TYPE_MODE (ix86_bf16_type_node, BFmode); > > + layout_type (ix86_bf16_type_node); > > + > > + if (!maybe_get_identifier ("__bf16") && TARGET_SSE2) > > + { > > + lang_hooks.types.register_builtin_type (ix86_bf16_type_node, > > + "__bf16"); > > + ix86_bf16_ptr_type_node = build_pointer_type (ix86_bf16_type_node); > > + } > > +} > > + > > static void > > ix86_init_builtin_types (void) > > { > > @@ -1396,6 +1415,8 @@ ix86_init_builtin_types (void) > > > > ix86_register_float16_builtin_type (); > > > > + ix86_register_bf16_builtin_type (); > > + > > const_string_type_node > > = build_pointer_type (build_qualified_type > > (char_type_node, TYPE_QUAL_CONST)); diff --git > > a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index > > e2e1e18d24d..b49daaef253 100644 > > --- a/gcc/config/i386/i386-modes.def > > +++ b/gcc/config/i386/i386-modes.def > > @@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see > > FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format); > > FLOAT_MODE (TF, 16, ieee_quad_format); FLOAT_MODE (HF, 2, > > ieee_half_format); > > +FLOAT_MODE (BF, 2, 0); > > +ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format); > > > > /* In ILP32 mode, XFmode has size 12 and alignment 4. > > In LP64 mode, XFmode has size and alignment 16. */ diff --git > > a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index > > e03f86d4a23..5d589f6a05c 100644 > > --- a/gcc/config/i386/i386.cc > > +++ b/gcc/config/i386/i386.cc > > @@ -2399,6 +2399,7 @@ classify_argument (machine_mode mode, const_tree > > type, > > case E_CTImode: > > return 0; > > case E_HFmode: > > + case E_BFmode: > > if (!(bit_offset % 64)) > > classes[0] = X86_64_SSEHF_CLASS; > > else > > @@ -2792,9 +2793,10 @@ construct_container (machine_mode mode, > > machine_mode orig_mode, > > intreg++; > > break; > > case X86_64_SSEHF_CLASS: > > + tmpmode = (mode == BFmode ? BFmode : HFmode); > > exp [nexps++] > > = gen_rtx_EXPR_LIST (VOIDmode, > > - gen_rtx_REG (HFmode, > > + gen_rtx_REG (tmpmode, > > GET_SSE_REGNO (sse_regno)), > > GEN_INT (i*8)); > > sse_regno++; > > @@ -4001,8 +4003,8 @@ function_value_32 (machine_mode orig_mode, > > machine_mode mode, > > /* Most things go in %eax. */ > > regno = AX_REG; > > > > - /* Return _Float16/_Complex _Foat16 by sse register. */ > > - if (mode == HFmode) > > + /* Return __bf16/ _Float16/_Complex _Foat16 by sse register. */ if > > + (mode == HFmode || mode == BFmode) > > regno = FIRST_SSE_REG; > > if (mode == HCmode) > > { > > @@ -4050,6 +4052,7 @@ function_value_64 (machine_mode orig_mode, > > machine_mode mode, > > > > switch (mode) > > { > > + case E_BFmode: > > case E_HFmode: > > case E_HCmode: > > case E_SFmode: > > @@ -5631,6 +5634,7 @@ ix86_output_ssemov (rtx_insn *insn, rtx *operands) > > return "%vmovss\t{%1, %0|%0, %1}"; > > > > case MODE_HF: > > + case MODE_BF: > > if (REG_P (operands[0]) && REG_P (operands[1])) > > return "vmovsh\t{%d1, %0|%0, %d1}"; > > else > > @@ -19402,7 +19406,8 @@ ix86_secondary_reload (bool in_p, rtx x, > > reg_class_t rclass, > > } > > > > /* Require movement to gpr, and then store to memory. */ > > - if ((mode == HFmode || mode == HImode || mode == V2QImode) > > + if ((mode == HFmode || mode == HImode || mode == V2QImode > > + || mode == BFmode) > > && !TARGET_SSE4_1 > > && SSE_CLASS_P (rclass) > > && !in_p && MEM_P (x)) > > @@ -22331,7 +22336,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 && TARGET_SSE2) > > + else if ((mode == HFmode || mode == BFmode) && TARGET_SSE2) > > return true; > > else > > return default_scalar_mode_supported_p (mode); @@ -22646,6 +22651,8 > > @@ ix86_mangle_type (const_tree type) > > > > switch (TYPE_MODE (type)) > > { > > + case E_BFmode: > > + return "u6__bf16"; > > case E_HFmode: > > /* _Float16 is "DF16_". > > Align with clang's decision in https://reviews.llvm.org/D33719. */ @@ - > > 22661,6 +22668,55 @@ ix86_mangle_type (const_tree type) > > } > > } > > > > +/* Return the diagnostic message string if conversion from FROMTYPE to > > + TOTYPE is not allowed, NULL otherwise. */ > > + > > +static const char * > > +ix86_invalid_conversion (const_tree fromtype, const_tree totype) { > > + if (element_mode (fromtype) != element_mode (totype)) > > + { > > + /* Do no allow conversions to/from BFmode scalar types. */ > > + if (TYPE_MODE (fromtype) == BFmode) > > + return N_("invalid conversion from type %<__bf16%>"); > > + if (TYPE_MODE (totype) == BFmode) > > + return N_("invalid conversion to type %<__bf16%>"); > > + } > > + > > + /* Conversion allowed. */ > > + return NULL; > > +} > > + > > +/* Return the diagnostic message string if the unary operation OP is > > + not permitted on TYPE, NULL otherwise. */ > > + > > +static const char * > > +ix86_invalid_unary_op (int op, const_tree type) { > > + /* Reject all single-operand operations on BFmode except for &. */ > > + if (element_mode (type) == BFmode && op != ADDR_EXPR) > > + return N_("operation not permitted on type %<__bf16%>"); > > + > > + /* Operation allowed. */ > > + return NULL; > > +} > > + > > +/* Return the diagnostic message string if the binary operation OP is > > + not permitted on TYPE1 and TYPE2, NULL otherwise. */ > > + > > +static const char * > > +ix86_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, > > + const_tree type2) > > +{ > > + /* Reject all 2-operand operations on BFmode. */ > > + if (element_mode (type1) == BFmode > > + || element_mode (type2) == BFmode) > > + return N_("operation not permitted on type %<__bf16%>"); > > + > > + /* Operation allowed. */ > > + return NULL; > > +} > > + > > static GTY(()) tree ix86_tls_stack_chk_guard_decl; > > > > static tree > > @@ -24718,6 +24774,15 @@ ix86_libgcc_floating_mode_supported_p > > #undef TARGET_MANGLE_TYPE > > #define TARGET_MANGLE_TYPE ix86_mangle_type > > > > +#undef TARGET_INVALID_CONVERSION > > +#define TARGET_INVALID_CONVERSION ix86_invalid_conversion > > + > > +#undef TARGET_INVALID_UNARY_OP > > +#define TARGET_INVALID_UNARY_OP ix86_invalid_unary_op > > + > > +#undef TARGET_INVALID_BINARY_OP > > +#define TARGET_INVALID_BINARY_OP ix86_invalid_binary_op > > + > > #undef TARGET_STACK_PROTECT_GUARD > > #define TARGET_STACK_PROTECT_GUARD ix86_stack_protect_guard > > > > diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index > > f16df633e84..0da3dce1d31 100644 > > --- a/gcc/config/i386/i386.h > > +++ b/gcc/config/i386/i386.h > > @@ -1046,7 +1046,7 @@ extern const char *host_detect_local_cpu (int argc, > > const char **argv); > > || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode > > \ > > || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode > > \ > > || (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode > > \ > > - || (MODE) == HFmode) > > + || (MODE) == HFmode || (MODE) == BFmode) > > > > #define VALID_SSE_REG_MODE(MODE) \ > > ((MODE) == V1TImode || (MODE) == TImode \ > > @@ -1077,7 +1077,7 @@ extern const char *host_detect_local_cpu (int argc, > > const char **argv); > > || (MODE) == CQImode || (MODE) == CHImode > > \ > > || (MODE) == CSImode || (MODE) == CDImode > > \ > > || (MODE) == SDmode || (MODE) == DDmode \ > > - || (MODE) == HFmode || (MODE) == HCmode \ > > + || (MODE) == HFmode || (MODE) == HCmode || (MODE) == BFmode > > \ > > || (MODE) == V2HImode || (MODE) == V2HFmode > > \ > > || (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode > > \ > > || (TARGET_64BIT \ > > diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index > > 9aaeb695f0f..1f7b018913a 100644 > > --- a/gcc/config/i386/i386.md > > +++ b/gcc/config/i386/i386.md > > @@ -499,7 +499,7 @@ > > > > ;; Main data type used by the insn > > (define_attr "mode" > > - "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,SF,DF,XF,TF,V32HF,V16HF,V8HF, > > + > > + "unknown,none,QI,HI,SI,DI,TI,OI,XI,HF,BF,SF,DF,XF,TF,V32HF,V16HF,V8HF, > > V16SF,V8SF,V4DF,V4SF,V2DF,V2SF,V1DF,V8DF,V4HF,V2HF" > > (const_string "unknown")) > > > > @@ -1104,7 +1104,7 @@ > > ;; GET_MODE_SIZE (<MODE>mode). For XFmode which depends on ;; > > command line options just use GET_MODE_SIZE macro. > > (define_mode_attr MODE_SIZE [(QI "1") (HI "2") (SI "4") (DI "8") > > - (TI "16") (HF "2") (SF "4") (DF "8") > > + (TI "16") (HF "2") (BF "2") (SF "4") (DF "8") > > (XF "GET_MODE_SIZE (XFmode)") > > (V16QI "16") (V32QI "32") (V64QI "64") > > (V8HI "16") (V16HI "32") (V32HI "64") @@ -1248,7 > > +1248,7 @@ (define_mode_iterator X87MODEF [SF DF XF]) > > > > ;; All x87 floating point modes plus HFmode -(define_mode_iterator > > X87MODEFH [HF SF DF XF]) > > +(define_mode_iterator X87MODEFH [HF SF DF XF BF]) > > > > ;; All SSE floating point modes > > (define_mode_iterator SSEMODEF [HF SF DF TF]) @@ -3408,9 +3408,11 @@ > > operands[0] = replace_equiv_address (operands[0], stack_pointer_rtx); > > }) > > > > -(define_insn "*pushhf_rex64" > > - [(set (match_operand:HF 0 "push_operand" "=X,X") > > - (match_operand:HF 1 "nonmemory_no_elim_operand" "r,x"))] > > +(define_mode_iterator HFBF [HF BF]) > > + > > +(define_insn "*push<mode>_rex64" > > + [(set (match_operand:HFBF 0 "push_operand" "=X,X") > > + (match_operand:HFBF 1 "nonmemory_no_elim_operand" "r,x"))] > > "TARGET_64BIT" > > { > > /* Anything else should be already split before reg-stack. */ @@ -3421,9 > > +3423,9 @@ > > (set_attr "type" "push,multi") > > (set_attr "mode" "DI,TI")]) > > > > -(define_insn "*pushhf" > > - [(set (match_operand:HF 0 "push_operand" "=X,X") > > - (match_operand:HF 1 "general_no_elim_operand" "rmF,x"))] > > +(define_insn "*push<mode>" > > + [(set (match_operand:HFBF 0 "push_operand" "=X,X") > > + (match_operand:HFBF 1 "general_no_elim_operand" "rmF,x"))] > > "!TARGET_64BIT" > > { > > /* Anything else should be already split before reg-stack. */ @@ -3462,7 > > +3464,7 @@ > > (set_attr "unit" "i387,*,*") > > (set_attr "mode" "SF,SI,SF")]) > > > > -(define_mode_iterator MODESH [SF HF]) > > +(define_mode_iterator MODESH [SF HF BF]) > > ;; %%% Kill this when call knows how to work this out. > > (define_split > > [(set (match_operand:MODESH 0 "push_operand") @@ -3950,18 +3952,18 > > @@ > > ] > > (const_string "*")))]) > > > > -(define_insn "*movhf_internal" > > - [(set (match_operand:HF 0 "nonimmediate_operand" > > +(define_insn "*mov<mode>_internal" > > + [(set (match_operand:HFBF 0 "nonimmediate_operand" > > "=?r,?r,?r,?m,v,v,?r,m,?v,v") > > - (match_operand:HF 1 "general_operand" > > + (match_operand:HFBF 1 "general_operand" > > "r ,F ,m ,rF,C,v, v,v,r ,m"))] > > "!(MEM_P (operands[0]) && MEM_P (operands[1])) > > && (lra_in_progress > > || reload_completed > > || !CONST_DOUBLE_P (operands[1]) > > || (TARGET_SSE2 > > - && standard_sse_constant_p (operands[1], HFmode) == 1) > > - || memory_operand (operands[0], HFmode))" > > + && standard_sse_constant_p (operands[1], <MODE>mode) == 1) > > + || memory_operand (operands[0], <MODE>mode))" > > { > > switch (get_attr_type (insn)) > > { > > diff --git a/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > > b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > > new file mode 100644 > > index 00000000000..962c8504775 > > --- /dev/null > > +++ b/gcc/testsuite/g++.target/i386/bfloat_cpp_typecheck.C > > @@ -0,0 +1,10 @@ > > +/* { dg-do assemble { target sse2} } */ > > +/* { dg-options "-msse2 -O3 --save-temps" } */ > > + > > +void foo (void) > > +{ > > + __bf16 (); /* { dg-bogus {invalid conversion to type '__bf16'} } */ > > + __bf16 a = __bf16(); /* { dg-bogus {invalid conversion to type > > +'__bf16'} } */ > > + __bf16 (0x1234); /* { dg-error {invalid conversion to type '__bf16'} > > +} */ > > + __bf16 (0.1); /* { dg-error {invalid conversion to type '__bf16'} } > > +*/ } > > diff --git a/gcc/testsuite/gcc.target/i386/bfloat16-1.c > > b/gcc/testsuite/gcc.target/i386/bfloat16-1.c > > new file mode 100644 > > index 00000000000..6aaec28efd2 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/bfloat16-1.c > > @@ -0,0 +1,12 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-msse2 -O2" } */ > > +__bf16 > > +foo (int a) > > +{ > > + union { > > + int a; > > + __bf16 b; > > + }c; > > + c.a = a; > > + return c.b; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > new file mode 100644 > > index 00000000000..612d55be826 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-1.c > > @@ -0,0 +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; > > +} > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > > b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > > new file mode 100644 > > index 00000000000..a3286e26c48 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-2.c > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-O2 -msse2 -mno-avx512f" } */ > > + > > +union flt > > +{ > > + __bf16 flt; > > + short s; > > +}; > > + > > +__bf16 > > +foo (union flt x) > > +{ > > + return x.flt; > > +} > > + > > +/* { dg-final { scan-assembler {(?n)pinsrw[\t ].*%xmm0} { target ia32 } > > +} } */ > > +/* { dg-final { scan-assembler {(?n)movd[\t ].*%xmm0} { target { ! ia32 > > +} } } } */ > > diff --git a/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c > > b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c > > new file mode 100644 > > index 00000000000..f76d5547758 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/i386/sse2-bfloat16-scalar-typecheck.c > > @@ -0,0 +1,215 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-msse2 -O2" } */ > > + > > + > > +__bf16 glob_bfloat; > > + > > +int is_an_int; > > +short is_a_short_int; > > +float is_a_float; > > +float is_a_float16; > > +double is_a_double; > > + > > +float *float_ptr; > > + > > +__bf16 foo1 (void) { return (__bf16) 0x1234; } /* { dg-error {invalid > > +conversion to type '__bf16'} } */ > > +__bf16 foo2 (void) { return (__bf16) (short) 0x1234; } /* { dg-error > > +{invalid conversion to type '__bf16'} } */ > > + > > +__bf16 footest (__bf16 scalar0) > > +{ > > + > > + /* Initialisation */ > > + > > + __bf16 scalar1_1; > > + __bf16 scalar1_2 = glob_bfloat; > > + __bf16 scalar1_3 = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ > > + __bf16 scalar1_4 = 0.1; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + __bf16 scalar1_5 = is_a_float; /* { dg-error {invalid conversion to > > + type '__bf16'} } */ > > + __bf16 scalar1_6 = is_an_int; /* { dg-error {invalid conversion to > > + type '__bf16'} } */ > > + __bf16 scalar1_7 = is_a_float16; /* { dg-error {invalid conversion to > > + type '__bf16'} } */ > > + __bf16 scalar1_8 = is_a_double; /* { dg-error {invalid conversion to > > + type '__bf16'} } */ > > + __bf16 scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion > > + to type '__bf16'} } */ > > + > > + int initi_1_1 = glob_bfloat; /* { dg-error {invalid conversion from > > + type '__bf16'} } */ float initi_1_2 = glob_bfloat; /* { dg-error > > + {invalid conversion from type '__bf16'} } */ > > + _Float16 initi_1_3 = glob_bfloat; /* { dg-error {invalid conversion > > + from type '__bf16'} } */ short initi_1_4 = glob_bfloat; /* { dg-error > > + {invalid conversion from type '__bf16'} } */ double initi_1_5 = > > + glob_bfloat; /* { dg-error {invalid conversion from type '__bf16'} } > > + */ > > + > > + __bf16 scalar2_1 = {}; /* { dg-error {empty scalar initializer} } */ > > + __bf16 scalar2_2 = { glob_bfloat }; > > + __bf16 scalar2_3 = { 0 }; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + __bf16 scalar2_4 = { 0.1 }; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + __bf16 scalar2_5 = { is_a_float }; /* { dg-error {invalid conversion > > + to type '__bf16'} } */ > > + __bf16 scalar2_6 = { is_an_int }; /* { dg-error {invalid conversion > > + to type '__bf16'} } */ > > + __bf16 scalar2_7 = { is_a_float16 }; /* { dg-error {invalid > > + conversion to type '__bf16'} } */ > > + __bf16 scalar2_8 = { is_a_double }; /* { dg-error {invalid conversion > > + to type '__bf16'} } */ > > + __bf16 scalar2_9 = { is_a_short_int }; /* { dg-error {invalid > > + conversion to type '__bf16'} } */ > > + > > + int initi_2_1 = { glob_bfloat }; /* { dg-error {invalid conversion > > + from type '__bf16'} } */ float initi_2_2 = { glob_bfloat }; /* { > > + dg-error {invalid conversion from type '__bf16'} } */ > > + _Float16 initi_2_3 = { glob_bfloat }; /* { dg-error {invalid > > + conversion from type '__bf16'} } */ short initi_2_4 = { glob_bfloat > > + }; /* { dg-error {invalid conversion from type '__bf16'} } */ double > > + initi_2_5 = { glob_bfloat }; /* { dg-error {invalid conversion from > > + type '__bf16'} } */ > > + > > + /* Assignments. */ > > + > > + glob_bfloat = glob_bfloat; > > + glob_bfloat = 0; /* { dg-error {invalid conversion to type '__bf16'} } */ > > + glob_bfloat = 0.1; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ glob_bfloat = is_a_float; /* { dg-error {invalid > > + conversion to type '__bf16'} } */ glob_bfloat = is_an_int; /* { > > + dg-error {invalid conversion to type '__bf16'} } */ glob_bfloat = > > + is_a_float16; /* { dg-error {invalid conversion to type '__bf16'} } */ > > + glob_bfloat = is_a_double; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ glob_bfloat = is_a_short_int; /* { dg-error {invalid > > + conversion to type '__bf16'} } */ > > + > > + is_an_int = glob_bfloat; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ is_a_float = glob_bfloat; /* { dg-error {invalid > > + conversion from type '__bf16'} } */ > > + is_a_float16 = glob_bfloat; /* { dg-error {invalid conversion from > > + type '__bf16'} } */ is_a_double = glob_bfloat; /* { dg-error {invalid > > + conversion from type '__bf16'} } */ is_a_short_int = glob_bfloat; /* > > + { dg-error {invalid conversion from type '__bf16'} } */ > > + > > + /* Casting. */ > > + > > + (void) glob_bfloat; > > + (__bf16) glob_bfloat; > > + > > + (int) glob_bfloat; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (float) glob_bfloat; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (_Float16) glob_bfloat; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (double) glob_bfloat; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (short) glob_bfloat; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + > > + (__bf16) is_an_int; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) is_a_float; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) is_a_float16; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) is_a_double; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) is_a_short_int; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + > > + /* Compound literals. */ > > + > > + (__bf16) {}; /* { dg-error {empty scalar initializer} } */ > > + (__bf16) { glob_bfloat }; > > + (__bf16) { 0 }; /* { dg-error {invalid conversion to type '__bf16'} } > > + */ > > + (__bf16) { 0.1 }; /* { dg-error {invalid conversion to type '__bf16'} > > + } */ > > + (__bf16) { is_a_float }; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) { is_an_int }; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) { is_a_float16 }; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) { is_a_double }; /* { dg-error {invalid conversion to type > > + '__bf16'} } */ > > + (__bf16) { is_a_short_int }; /* { dg-error {invalid conversion to > > + type '__bf16'} } */ > > + > > + (int) { glob_bfloat }; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (float) { glob_bfloat }; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (_Float16) { glob_bfloat }; /* { dg-error {invalid conversion from > > + type '__bf16'} } */ > > + (double) { glob_bfloat }; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + (short) { glob_bfloat }; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + > > + /* Arrays and Structs. */ > > + > > + typedef __bf16 array_type[2]; > > + extern __bf16 extern_array[]; > > + > > + __bf16 array[2]; > > + __bf16 zero_length_array[0]; > > + __bf16 empty_init_array[] = {}; > > + typedef __bf16 some_other_type[is_an_int]; > > + > > + struct struct1 { > > + __bf16 a; > > + }; > > + > > + union union1 { > > + __bf16 a; > > + }; > > + > > + /* Addressing and dereferencing. */ > > + > > + __bf16 *bfloat_ptr = &scalar0; > > + scalar0 = *bfloat_ptr; > > + > > + /* Pointer assignment. */ > > + > > + __bf16 *bfloat_ptr2 = bfloat_ptr; > > + __bf16 *bfloat_ptr3 = array; > > + > > + /* Pointer arithmetic. */ > > + > > + ++bfloat_ptr; > > + --bfloat_ptr; > > + bfloat_ptr++; > > + bfloat_ptr--; > > + bfloat_ptr += 1; > > + bfloat_ptr -= 1; > > + bfloat_ptr - bfloat_ptr2; > > + bfloat_ptr = &bfloat_ptr3[0]; > > + bfloat_ptr = &bfloat_ptr3[1]; > > + > > + /* Simple comparison. */ > > + scalar0 > glob_bfloat; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ glob_bfloat == scalar0; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + scalar0 > is_a_float; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ is_a_float == scalar0; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + scalar0 > 0; /* { dg-error {operation not permitted on type '__bf16'} > > + } */ > > + 0 == scalar0; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ > > + scalar0 > 0.1; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ > > + 0.1 == scalar0; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ > > + scalar0 > is_an_int; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ is_an_int == scalar0; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + > > + /* Pointer comparison. */ > > + > > + bfloat_ptr == &scalar0; > > + bfloat_ptr != &scalar0; > > + bfloat_ptr < &scalar0; > > + bfloat_ptr <= &scalar0; > > + bfloat_ptr > &scalar0; > > + bfloat_ptr >= &scalar0; > > + bfloat_ptr == bfloat_ptr2; > > + bfloat_ptr != bfloat_ptr2; > > + bfloat_ptr < bfloat_ptr2; > > + bfloat_ptr <= bfloat_ptr2; > > + bfloat_ptr > bfloat_ptr2; > > + bfloat_ptr >= bfloat_ptr2; > > + > > + /* Conditional expressions. */ > > + > > + 0 ? scalar0 : scalar0; > > + 0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + 0 ? is_a_float : scalar0; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + 0 ? scalar0 : 0; /* { dg-error {invalid conversion to type '__bf16'} > > + } */ > > + 0 ? 0 : scalar0; /* { dg-error {invalid conversion to type '__bf16'} > > + } */ > > + 0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + 0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type > > + '__bf16'} } */ > > + 0 ? bfloat_ptr : bfloat_ptr2; > > + 0 ? bfloat_ptr : float_ptr; /* { dg-warning {pointer type mismatch in > > + conditional expression} } */ > > + 0 ? float_ptr : bfloat_ptr; /* { dg-warning {pointer type mismatch in > > + conditional expression} } */ > > + > > + scalar0 ? scalar0 : scalar0; /* { dg-error {operation not permitted > > + on type '__bf16'} } */ > > + scalar0 ? is_a_float : scalar0; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + scalar0 ? scalar0 : is_a_float; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + scalar0 ? is_a_float : is_a_float; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + > > + /* Unary operators. */ > > + > > + +scalar0; /* { dg-error {operation not permitted on type '__bf16'} } > > + */ -scalar0; /* { dg-error {operation not permitted on type '__bf16'} > > + } */ ~scalar0; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ !scalar0; /* { dg-error {operation not permitted on > > + type '__bf16'} } */ *scalar0; /* { dg-error {invalid type argument of > > + unary '\*'} } */ __real scalar0; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ __imag scalar0; /* { dg-error > > + {operation not permitted on type '__bf16'} } */ ++scalar0; /* { > > + dg-error {operation not permitted on type '__bf16'} } */ --scalar0; > > + /* { dg-error {operation not permitted on type '__bf16'} } */ > > + scalar0++; /* { dg-error {operation not permitted on type '__bf16'} } > > + */ scalar0--; /* { dg-error {operation not permitted on type > > + '__bf16'} } */ > > + > > + /* Binary arithmetic operations. */ > > + > > + scalar0 = glob_bfloat + *bfloat_ptr; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + scalar0 = glob_bfloat + 0.1; /* { dg-error {operation not permitted > > + on type '__bf16'} } */ > > + scalar0 = glob_bfloat + 0; /* { dg-error {operation not permitted on > > + type '__bf16'} } */ > > + scalar0 = glob_bfloat + is_a_float; /* { dg-error {operation not > > + permitted on type '__bf16'} } */ > > + > > + return scalar0; > > +} > > + > > -- > > 2.18.2 > -- BR, Hongtao ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-08-04 4:35 UTC | newest] Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <20220726011357.12001-1-lingling.kong@intel.com> 2022-07-26 1:31 ` [PATCH] x86: Enable __bf16 type for TARGET_SSE2 and above Kong, Lingling 2022-08-03 8:40 ` Kong, Lingling 2022-08-04 4:35 ` Hongtao Liu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).