x86_64/i686/AArch64 has for a few months working std::bfloat16_t support, __bf16 there is no longer a storage only type, but can be used for arithmetics and is supported in libgcc and libstdc++. The patch adds similar support for RISC-V. __bf16 has been merged in psABI. The compiler handles all operations with __bf16 by converting to SFmode.
gcc/ChangeLog: * config/riscv/iterators.md (ld):Add BFmode in iterators. (sd):Ditto. * config/riscv/riscv-builtins.cc (riscv_init_builtin_types):Add bfloat16_type_node in riscv. * config/riscv/riscv-modes.def (FLOAT_MODE):Add BFmode in FLOAT_MODE. (ADJUST_FLOAT_FORMAT):Ditto. * config/riscv/riscv.cc (riscv_mangle_type):Add DF16b in mangle. (riscv_scalar_mode_supported_p):Add BFmode in scalar_float_mode. (riscv_libgcc_floating_mode_supported_p):Support BFmode in libgcc. * config/riscv/riscv.md (mode" ):Support BFmode in machine description. (movbf): Support BFmode in softfloat. (*movbf_softfloat):Ditto. libgcc/ChangeLog: * config/riscv/sfp-machine.h (_FP_NANFRAC_B):Define. (_FP_NANSIGN_B): * config/riscv/t-softfp32:Add trunc{tfbf dfbf sfbf hfbf}, extendbfsf, floatdibf, floatundibf. * config/riscv/t-softfp64:Add floattibf, floatuntibf. gcc/testsuite/ChangeLog: * gcc.target/riscv/__bf16-soft.c: New test. --- gcc/config/riscv/iterators.md | 4 ++-- gcc/config/riscv/riscv-builtins.cc | 16 +++++++++++++++ gcc/config/riscv/riscv-modes.def | 2 ++ gcc/config/riscv/riscv.cc | 12 ++++++++--- gcc/config/riscv/riscv.md | 21 +++++++++++++++++++- gcc/testsuite/gcc.target/riscv/__bf16-soft.c | 12 +++++++++++ libgcc/config/riscv/sfp-machine.h | 3 +++ libgcc/config/riscv/t-softfp32 | 7 ++++--- libgcc/config/riscv/t-softfp64 | 2 +- 9 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/__bf16-soft.c diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index d374a10810c..c9148028ea3 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -87,13 +87,13 @@ (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")]) ;; Mode attribute for FP loads into integer registers. -(define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")]) +(define_mode_attr softload [(BF "lh") (HF "lh") (SF "lw") (DF "ld")]) ;; Instruction names for stores. (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")]) ;; Instruction names for FP stores from integer registers. -(define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")]) +(define_mode_attr softstore [(BF "sh") (HF "sh") (SF "sw") (DF "sd")]) ;; This attribute gives the best constraint to use for registers of ;; a given mode. diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc index 79681d75962..398247a0ccb 100644 --- a/gcc/config/riscv/riscv-builtins.cc +++ b/gcc/config/riscv/riscv-builtins.cc @@ -194,6 +194,7 @@ static GTY(()) int riscv_builtin_decl_index[NUM_INSN_CODES]; riscv_builtin_decls[riscv_builtin_decl_index[(CODE)]] tree riscv_float16_type_node = NULL_TREE; +tree riscv_bfloat16_type_node = NULL_TREE; /* Return the function type associated with function prototype TYPE. */ @@ -237,6 +238,21 @@ riscv_init_builtin_types (void) if (!maybe_get_identifier ("_Float16")) lang_hooks.types.register_builtin_type (riscv_float16_type_node, "_Float16"); + + /* Provide the __bf16 type and bfloat16_type_node if needed. */ + if (!bfloat16_type_node) + { + riscv_bfloat16_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (riscv_bfloat16_type_node) = 16; + SET_TYPE_MODE (riscv_bfloat16_type_node, BFmode); + layout_type (riscv_bfloat16_type_node); + } + else + riscv_bfloat16_type_node = bfloat16_type_node; + + if (!maybe_get_identifier ("__bf16")) + lang_hooks.types.register_builtin_type (riscv_bfloat16_type_node, + "__bf16"); } /* Implement TARGET_INIT_BUILTINS. */ diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def index 19a4f9fb3db..4bb03307840 100644 --- a/gcc/config/riscv/riscv-modes.def +++ b/gcc/config/riscv/riscv-modes.def @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see FLOAT_MODE (HF, 2, ieee_half_format); FLOAT_MODE (TF, 16, ieee_quad_format); +FLOAT_MODE (BF, 2, 0); +ADJUST_FLOAT_FORMAT (BF, &arm_bfloat_half_format); /* Vector modes. */ diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index e5ae4e81b7a..d5b1350d4bf 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -7155,8 +7155,14 @@ static const char * riscv_mangle_type (const_tree type) { /* Half-precision float, _Float16 is "DF16_". */ - if (SCALAR_FLOAT_TYPE_P (type) && TYPE_PRECISION (type) == 16) + /* Bfloat, __bf16 is "DF16b" */ + if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16) + { + if (TYPE_MODE (type) == BFmode) + return "DF16b"; + else return "DF16_"; + } /* Mangle all vector type for vector extension. */ /* The mangle name follows the rule of RVV LLVM @@ -7177,7 +7183,7 @@ riscv_mangle_type (const_tree type) static bool riscv_scalar_mode_supported_p (scalar_mode mode) { - if (mode == HFmode) + if (mode == HFmode || mode == BFmode) return true; else return default_scalar_mode_supported_p (mode); @@ -7189,7 +7195,7 @@ riscv_scalar_mode_supported_p (scalar_mode mode) static bool riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode) { - if (mode == HFmode) + if (mode == HFmode || BFmode) return true; else return default_libgcc_floating_mode_supported_p (mode); diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index d8e935cb934..77b52862bbd 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -169,7 +169,7 @@ (const_string "unknown")) ;; Main data type used by the insn -(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF, +(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,BF,HF,SF,DF,TF, VNx1BI,VNx2BI,VNx4BI,VNx8BI,VNx16BI,VNx32BI,VNx64BI,VNx128BI, VNx1QI,VNx2QI,VNx4QI,VNx8QI,VNx16QI,VNx32QI,VNx64QI,VNx128QI, VNx1HI,VNx2HI,VNx4HI,VNx8HI,VNx16HI,VNx32HI,VNx64HI, @@ -1744,6 +1744,25 @@ [(set_attr "move_type" "fmove,move,load,store,mtc,mfc") (set_attr "mode" "HF")]) +;; 16-bit bfloating point moves +(define_expand "movbf" + [(set (match_operand:BF 0 "") + (match_operand:BF 1 ""))] + "" +{ + if (riscv_legitimize_move (BFmode, operands[0], operands[1])) + DONE; +}) + +(define_insn "*movbf_softfloat" + [(set (match_operand:BF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r") + (match_operand:BF 1 "move_operand" " f,Gr,m,r,*r,*f"))] + "(register_operand (operands[0], BFmode) + || reg_or_0_operand (operands[1], BFmode))" + { return riscv_output_move (operands[0], operands[1]); } + [(set_attr "move_type" "fmove,move,load,store,mtc,mfc") + (set_attr "mode" "BF")]) + ;; ;; .................... ;; diff --git a/gcc/testsuite/gcc.target/riscv/__bf16-soft.c b/gcc/testsuite/gcc.target/riscv/__bf16-soft.c new file mode 100644 index 00000000000..eca98a799d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/__bf16-soft.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if -mabi=lp64f -O" } */ + +__bf16 test_soft_add (__bf16 a, __bf16 b) +{ + /* Make sure fadd.s invoked here. */ + /* { dg-final { scan-assembler-times "call\t__extendbfsf2" 2 } } */ + return a + b; + /* { dg-final { scan-assembler-times "fadd.s" 1 } } */ + /* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 } } */ +} + diff --git a/libgcc/config/riscv/sfp-machine.h b/libgcc/config/riscv/sfp-machine.h index ded594d75d8..2ed7cbf3a30 100644 --- a/libgcc/config/riscv/sfp-machine.h +++ b/libgcc/config/riscv/sfp-machine.h @@ -41,6 +41,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) +#define _FP_NANFRAC_B _FP_QNANBIT_B #define _FP_NANFRAC_H _FP_QNANBIT_H #define _FP_NANFRAC_S _FP_QNANBIT_S #define _FP_NANFRAC_D _FP_QNANBIT_D, 0 @@ -64,6 +65,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) +#define _FP_NANFRAC_B _FP_QNANBIT_B #define _FP_NANFRAC_H _FP_QNANBIT_H #define _FP_NANFRAC_S _FP_QNANBIT_S #define _FP_NANFRAC_D _FP_QNANBIT_D @@ -82,6 +84,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); #define CMPtype __gcc_CMPtype +#define _FP_NANSIGN_B 0 #define _FP_NANSIGN_H 0 #define _FP_NANSIGN_S 0 #define _FP_NANSIGN_D 0 diff --git a/libgcc/config/riscv/t-softfp32 b/libgcc/config/riscv/t-softfp32 index 55261f98383..25ac9f07541 100644 --- a/libgcc/config/riscv/t-softfp32 +++ b/libgcc/config/riscv/t-softfp32 @@ -42,7 +42,8 @@ softfp_extras := divsf3 divdf3 divtf3 endif -softfp_extensions += hfsf hfdf hftf -softfp_truncations += tfhf dfhf sfhf +softfp_extensions += hfsf hfdf hftf bfsf +softfp_truncations += tfhf dfhf sfhf hfbf sfbf dfbf tfbf softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \ - floatsihf floatdihf floatunsihf floatundihf + floatsihf floatdihf floatunsihf floatundihf \ + floatdibf floatundibf diff --git a/libgcc/config/riscv/t-softfp64 b/libgcc/config/riscv/t-softfp64 index c87d242d5c3..6f8c21352b6 100644 --- a/libgcc/config/riscv/t-softfp64 +++ b/libgcc/config/riscv/t-softfp64 @@ -1,4 +1,4 @@ include $(srcdir)/config/riscv/t-softfp32 softfp_int_modes += ti -softfp_extras += fixhfti fixunshfti floattihf floatuntihf +softfp_extras += fixhfti fixunshfti floattihf floatuntihf floattibf floatuntibf -- 2.34.1