[RFC] RISC-V: Support risc-v bfloat16 This patch support bfloat16 in riscv like x86_64 and arm.

Message ID 20230307091204.1498-1-shihua@iscas.ac.cn
State Changes Requested, archived
Delegated to: Kito Cheng
Headers
Series [RFC] RISC-V: Support risc-v bfloat16 This patch support bfloat16 in riscv like x86_64 and arm. |

Commit Message

Liao Shihua March 7, 2023, 9:12 a.m. UTC
  According to https://github.com/riscv/riscv-bfloat16 , zfbfmin extension depends on zfh/zfhmin extension.

   According to the discussion https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/367, this use __bf16 and use DF16b in riscv_mangle_type like x86.


gcc\ChangeLog:

        * common/config/riscv/riscv-common.cc: Add ZFBFMIN extension.
        * config/riscv/iterators.md (TARGET_ZFHMIN):Add iterator BF.
        (fld):Likewise.
        (ld):Likewise
        (fsd):Likewise
        (sd):Likewise
        (d):Likewise
        (DF):Likewise
        * config/riscv/riscv-builtins.cc (riscv_init_builtin_types): Add bfloat16 type in riscv .
        (riscv_fp16_builtin_type):Likewise
        (riscv_bf16_builtin_type):Likewise
        * config/riscv/riscv-modes.def (FLOAT_MODE):Likewise
        (ADJUST_FLOAT_FORMAT):Likewise
        * config/riscv/riscv-opts.h (MASK_ZFBFMIN):Add ZFBFMIN extension.
        (TARGET_ZFBFMIN):
        * config/riscv/riscv-vector-switch.def (ENTRY):
        * config/riscv/riscv.cc (riscv_emit_float_compare):Add bfloat16 type in riscv .
        (riscv_mangle_type):
        (riscv_scalar_mode_supported_p):
        (riscv_libgcc_floating_mode_supported_p):
        (riscv_init_libfuncs):
        * config/riscv/riscv.md (mode" ):Add bfloat16 type in riscv .
        (truncdfhf2):
        (truncsfbf2):
        (truncdf<BFHF:mode>2):
        (extendbfsf2):
        (extendhfdf2):
        (extend<BFHF:mode>df2):
        (movbf):
        (*movbf_hardfloat):
        (*movbf_softfloat):

libgcc\ChangeLog:

        * config/riscv/sfp-machine.h (_FP_NANFRAC_B):Add bfloat16 type in riscv .
        (_FP_NANSIGN_B):
        * config/riscv/t-softfp32:

---
 gcc/common/config/riscv/riscv-common.cc  |  4 ++
 gcc/config/riscv/iterators.md            | 21 +++++---
 gcc/config/riscv/riscv-builtins.cc       | 29 +++++++++-
 gcc/config/riscv/riscv-modes.def         |  2 +
 gcc/config/riscv/riscv-opts.h            |  2 +
 gcc/config/riscv/riscv-vector-switch.def |  4 +-
 gcc/config/riscv/riscv.cc                | 37 +++++++++++--
 gcc/config/riscv/riscv.md                | 69 ++++++++++++++++++++----
 libgcc/config/riscv/sfp-machine.h        |  3 ++
 libgcc/config/riscv/t-softfp32           |  8 +--
 10 files changed, 150 insertions(+), 29 deletions(-)
  

Comments

Kito Cheng April 25, 2023, 1:23 p.m. UTC | #1
Hi ShiHua:

Thanks for your contribution to the zfbfmin extension :)

General comments:
- Add zfbfmin to riscv_ext_version_table
- Add test case to verify the -march is accepted.
- Add testcase to test argument passing.
- Add testcase for operations.
- Add testcase for compares.

> +(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"))]
> +  "!TARGET_ZFHMIN

Should be TARGET_ZFBFMIN?

> @@ -3192,7 +3192,11 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
>        else if (GET_MODE (cmp_op0) == HFmode && TARGET_64BIT)           \
>         emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1));   \
>        else if (GET_MODE (cmp_op0) == HFmode)                           \
> -       emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1));   \
> +       emit_insn (gen_f##CMP##_quietbfsi4 (*op0, cmp_op0, cmp_op1));   \
> +      else if (GET_MODE (cmp_op0) == BFmode && TARGET_64BIT)           \
> +       emit_insn (gen_f##CMP##_quietbfdi4 (*op0, cmp_op0, cmp_op1));   \
> +      else if (GET_MODE (cmp_op0) == BFmode)                           \
> +       emit_insn (gen_f##CMP##_quietbfsi4 (*op0, cmp_op0, cmp_op1));   \
>        else                                                             \
>         gcc_unreachable ();                                             \
>        *op1 = const0_rtx;                                               \

Do we really need this? I thought we'll always promote to SF before
they compare?
  
Jin Ma June 1, 2023, 6:51 a.m. UTC | #2
hi, 

Are there any new developments about Zfb? Are there any plans to implement
the Zvfbfmin and Zvfbfwma expansion? I see that Zfb is being reviewed in
llvm, maybe we should do the same on gcc.

Ref: https://reviews.llvm.org/D151313
     https://reviews.llvm.org/D150929
  
juzhe.zhong@rivai.ai June 1, 2023, 7:01 a.m. UTC | #3
I plan to implement BF16 vector in GCC but still waiting for ISA ratified since GCC policy doesn't allow un-ratified ISA.

Currently, we are working on INT8,INT16,INT32,INT64,FP16,FP32,FP64 auto-vectorizaiton.
It should very simple BF16 in current vector framework in GCC.

Thanks.


juzhe.zhong@rivai.ai
 
From: Li, Pan2
Date: 2023-06-01 14:57
To: juzhe.zhong@rivai.ai
Subject: FW: [RFC] RISC-V: Support risc-v bfloat16 This patch support bfloat16 in riscv like x86_64 and arm.
FYI.
 
-----Original Message-----
From: Gcc-patches <gcc-patches-bounces+pan2.li=intel.com@gcc.gnu.org> On Behalf Of Jin Ma via Gcc-patches
Sent: Thursday, June 1, 2023 2:51 PM
To: gcc-patches@gcc.gnu.org
Cc: shihua@iscas.ac.cn; kito.cheng@gmail.com; Jin Ma <jinma@linux.alibaba.com>
Subject: [RFC] RISC-V: Support risc-v bfloat16 This patch support bfloat16 in riscv like x86_64 and arm.
 
hi, 
 
Are there any new developments about Zfb? Are there any plans to implement the Zvfbfmin and Zvfbfwma expansion? I see that Zfb is being reviewed in llvm, maybe we should do the same on gcc.
 
Ref: https://reviews.llvm.org/D151313
     https://reviews.llvm.org/D150929
  
Liao Shihua June 1, 2023, 9:07 a.m. UTC | #4
Hi, Ma Jin

     1. There are few developments since May in GCC because the spec of 
Zfbf <https://github.com/riscv/riscv-bfloat16> is constantly changing.

     2. We (PLCT lab) will implement Zvfbfmin and Zvfbfwma after Zvfh 
has been merged in GCC.

     3. I will send a patch to support bfloat16_t in RISC-V port, but 
Zfbf extension's patch will be sent after it released.

Liao Shihua

在 2023/6/1 14:51, Jin Ma 写道:
> hi,
>
> Are there any new developments about Zfb? Are there any plans to implement
> the Zvfbfmin and Zvfbfwma expansion? I see that Zfb is being reviewed in
> llvm, maybe we should do the same on gcc.
>
> Ref:https://reviews.llvm.org/D151313
>       https://reviews.llvm.org/D150929
  
Jeff Law June 1, 2023, 4:48 p.m. UTC | #5
On 6/1/23 01:01, juzhe.zhong@rivai.ai wrote:
> I plan to implement BF16 vector in GCC but still waiting for ISA 
> ratified since GCC policy doesn't allow un-ratified ISA.
Right.  So those specs need to move along further before we can start 
integrating code.

> 
> Currently, we are working on INT8,INT16,INT32,INT64,FP16,FP32,FP64 
> auto-vectorizaiton.
> It should very simple BF16 in current vector framework in GCC.
In prior architectures I've worked on the bulk of BF16 work was just 
adding additional entries to existing iterators.  So I agree, it should 
be very simple :-)

Jeff
  
Palmer Dabbelt June 1, 2023, 4:56 p.m. UTC | #6
On Thu, 01 Jun 2023 09:48:47 PDT (-0700), jeffreyalaw@gmail.com wrote:
>
>
> On 6/1/23 01:01, juzhe.zhong@rivai.ai wrote:
>> I plan to implement BF16 vector in GCC but still waiting for ISA
>> ratified since GCC policy doesn't allow un-ratified ISA.
> Right.  So those specs need to move along further before we can start
> integrating code.
>
>>
>> Currently, we are working on INT8,INT16,INT32,INT64,FP16,FP32,FP64
>> auto-vectorizaiton.
>> It should very simple BF16 in current vector framework in GCC.
> In prior architectures I've worked on the bulk of BF16 work was just
> adding additional entries to existing iterators.  So I agree, it should
> be very simple :-)

We should also have someone who's a bit more plugged in to floating 
point check to make sure the RISC-V bfloat16 semantics match IEEE.  I 
don't see any issues, but I'm not really a FP person so I'm not sure.  
There were certainly a lot of subtlies for the other FP bits, so even if 
the implementation just plumbs straight through IMO it's worth checking.

We have one FP person at Rivos, I can try and rope him in if you want?  
Happy to have someone else do it, though, as he's usually pretty busy ;)
  
Philipp Tomsich June 1, 2023, 4:59 p.m. UTC | #7
On Thu, 1 Jun 2023 at 18:49, Jeff Law via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
>
>
> On 6/1/23 01:01, juzhe.zhong@rivai.ai wrote:
> > I plan to implement BF16 vector in GCC but still waiting for ISA
> > ratified since GCC policy doesn't allow un-ratified ISA.
> Right.  So those specs need to move along further before we can start
> integrating code.

Doesn't our policy require specs to only pass the FREEZE milestone
(i.e., the requirement for public review) before we can start
integrating them?
This should give us at least a 6 week (minimum 30 days public-review
plus 2 weeks for the TSC vote to send this up for ratification)
headstart on ratification (with the small risk of minor changes
required due to review comments) to start integrating support for new
extensions.

Best,
Philipp.

p.s.: Just for reference, the RISC-V Lifecycle Guide (defining these
milestones in specification development) is linked from
https://wiki.riscv.org/ for details.


> >
> > Currently, we are working on INT8,INT16,INT32,INT64,FP16,FP32,FP64
> > auto-vectorizaiton.
> > It should very simple BF16 in current vector framework in GCC.
> In prior architectures I've worked on the bulk of BF16 work was just
> adding additional entries to existing iterators.  So I agree, it should
> be very simple :-)
>
> Jeff
>
  
Jeff Law June 1, 2023, 5:53 p.m. UTC | #8
On 6/1/23 10:56, Palmer Dabbelt wrote:
> On Thu, 01 Jun 2023 09:48:47 PDT (-0700), jeffreyalaw@gmail.com wrote:
>>
>>
>> On 6/1/23 01:01, juzhe.zhong@rivai.ai wrote:
>>> I plan to implement BF16 vector in GCC but still waiting for ISA
>>> ratified since GCC policy doesn't allow un-ratified ISA.
>> Right.  So those specs need to move along further before we can start
>> integrating code.
>>
>>>
>>> Currently, we are working on INT8,INT16,INT32,INT64,FP16,FP32,FP64
>>> auto-vectorizaiton.
>>> It should very simple BF16 in current vector framework in GCC.
>> In prior architectures I've worked on the bulk of BF16 work was just
>> adding additional entries to existing iterators.  So I agree, it should
>> be very simple :-)
> 
> We should also have someone who's a bit more plugged in to floating 
> point check to make sure the RISC-V bfloat16 semantics match IEEE.  I 
> don't see any issues, but I'm not really a FP person so I'm not sure. 
> There were certainly a lot of subtlies for the other FP bits, so even if 
> the implementation just plumbs straight through IMO it's worth checking.
> 
> We have one FP person at Rivos, I can try and rope him in if you want? 
> Happy to have someone else do it, though, as he's usually pretty busy ;)
I don't really have an FP expert here.  I can't honestly pretend to be 
one myself.

jeff
  
Jin Ma June 15, 2023, 7:51 a.m. UTC | #9
> diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
> index ebc1ed7d7e4..2b3ff1f5b8e 100644
> --- a/gcc/common/config/riscv/riscv-common.cc
> +++ b/gcc/common/config/riscv/riscv-common.cc
> @@ -102,6 +102,8 @@ static const riscv_implied_info_t riscv_implied_info[] =
> {"zvl32768b", "zvl16384b"},
> {"zvl65536b", "zvl32768b"},
> 
> + {"zfbfmin", "zfhmin"},
> +
> {"zfh", "zfhmin"},
> {"zfhmin", "f"},
> 
> @@ -1239,6 +1241,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
> {"zvl16384b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL16384B},
> {"zvl32768b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32768B},
> {"zvl65536b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL65536B},
> + 
> + {"zfbfmin", &gcc_options::x_riscv_zf_subext, MASK_ZFBFMIN},
> 
> {"zfhmin", &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN},
> {"zfh", &gcc_options::x_riscv_zf_subext, MASK_ZFH},
As kito says, there is no version information for the extension.
> diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
> index 5b70ab20758..6349f032bc8 100644
> --- a/gcc/config/riscv/iterators.md
> +++ b/gcc/config/riscv/iterators.md
> @@ -61,10 +61,15 @@
> ;; Iterator for hardware-supported floating-point modes.
> (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT || TARGET_ZFINX")
> (DF "TARGET_DOUBLE_FLOAT || TARGET_ZDINX")
> - (HF "TARGET_ZFH || TARGET_ZHINX")])
> + (HF "TARGET_ZFH || TARGET_ZHINX") 
> + (BF "TARGET_ZFBFMIN")])
> +
> +;; Iterator for HImode constant generation.
> +(define_mode_iterator BFHF [BF HF])
> 
> ;; Iterator for floating-point modes that can be loaded into X registers.
> -(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
> +(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")
> + (BF "TARGET_ZFBFMIN")])
> 
> 
> ;; -------------------------------------------------------------------
> @@ -76,27 +81,27 @@
> (define_mode_attr size [(QI "b") (HI "h")])
> 
> ;; Mode attributes for loads.
> -(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")])
> +(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (BF "flh") (HF "flh") (SF "flw") (DF "fld")])
> 
> ;; Instruction names for integer loads that aren't explicitly sign or zero
> ;; extended. See riscv_output_move and LOAD_EXTEND_OP.
> (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")])
> +(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (BF "fsh") (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.
> (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
> 
> ;; This attribute gives the format suffix for floating-point operations.
> -(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")])
> +(define_mode_attr fmt [(BF "h") (HF "h") (SF "s") (DF "d")])
> 
> ;; This attribute gives the integer suffix for floating-point conversions.
> (define_mode_attr ifmt [(SI "w") (DI "l")])
> @@ -106,7 +111,7 @@
> 
> ;; This attribute gives the upper-case mode name for one unit of a
> ;; floating-point mode.
> -(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")])
> +(define_mode_attr UNITMODE [(BF "BF") (HF "HF") (SF "SF") (DF "DF")])
> 
> ;; This attribute gives the integer mode that has half the size of
> ;; the controlling mode.
> diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
> index 25ca407f9a9..e0c6f6834a5 100644
> --- a/gcc/config/riscv/riscv-builtins.cc
> +++ b/gcc/config/riscv/riscv-builtins.cc
> @@ -163,6 +163,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. */
> 
> @@ -190,7 +191,7 @@ riscv_build_function_type (enum riscv_function_type type)
> }
> 
> static void
> -riscv_init_builtin_types (void)
> +riscv_fp16_builtin_type (void)
> {
> /* Provide the _Float16 type and float16_type_node if needed. */
> if (!float16_type_node)
> @@ -208,6 +209,32 @@ riscv_init_builtin_types (void)
> "_Float16");
> }
> 
> +static void
> +riscv_bf16_builtin_type (void)
> +{
> + /* 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");
> +}
> +
> +static void
> +riscv_init_builtin_types (void)
> +{
> + riscv_fp16_builtin_type ();
> + riscv_bf16_builtin_type ();
> +}
> +
> /* Implement TARGET_INIT_BUILTINS. */
> 
> void
> diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def
> index d5305efa8a6..93c22b09ed7 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-opts.h b/gcc/config/riscv/riscv-opts.h
> index ff398c0a2ae..e5791019912 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -168,9 +168,11 @@ enum stack_protector_guard {
> 
> #define MASK_ZFHMIN (1 << 0)
> #define MASK_ZFH (1 << 1)
> +#define MASK_ZFBFMIN (1 << 2)
> 
> #define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0)
> #define TARGET_ZFH ((riscv_zf_subext & MASK_ZFH) != 0)
> +#define TARGET_ZFBFMIN ((riscv_zf_subext & MASK_ZFBFMIN) != 0)
> 
> #define MASK_ZMMUL (1 << 0)
> #define TARGET_ZMMUL ((riscv_zm_subext & MASK_ZMMUL) != 0)
> diff --git a/gcc/config/riscv/riscv-vector-switch.def b/gcc/config/riscv/riscv-vector-switch.def
> index 8e4aed40338..8808d0f9b44 100644
> --- a/gcc/config/riscv/riscv-vector-switch.def
> +++ b/gcc/config/riscv/riscv-vector-switch.def
> @@ -75,7 +75,7 @@ n = SEW/LMUL
> |Types|n=1 |n=2 |n=4 |n=8 |n=16 |n=32 |n=64|
> |bool |VNx32BI|VNx16BI|VNx8BI|VNx4BI|VNx2BI|VNx1BI|N/A |
> 
> -TODO: FP16 vector needs support of 'zvfh', we don't support it yet. */
> +TODO: FP16 vector needs support of 'zvfh' and 'zvfbfmin', we don't support it yet. */
> 
> /* Return 'REQUIREMENT' for machine_mode 'MODE'.
> For example: 'MODE' = VNx64BImode needs TARGET_MIN_VLEN > 32. */
> @@ -120,7 +120,7 @@ ENTRY (VNx4HI, true, LMUL_2, 8, LMUL_1, 16)
> ENTRY (VNx2HI, true, LMUL_1, 16, LMUL_F2, 32)
> ENTRY (VNx1HI, true, LMUL_F2, 32, LMUL_F4, 64)
> 
> -/* TODO:Disable all FP16 vector, enable them when 'zvfh' is supported. */
> +/* TODO:Disable all FP16 vector, enable them when 'zvfh' and 'zvfbfmin' is supported. */
> ENTRY (VNx32HF, false, LMUL_RESERVED, 0, LMUL_8, 2)
> ENTRY (VNx16HF, false, LMUL_8, 2, LMUL_4, 4)
> ENTRY (VNx8HF, false, LMUL_4, 4, LMUL_2, 8)
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index f11b7949a49..2ddbdfa424a 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -3192,7 +3192,11 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
> else if (GET_MODE (cmp_op0) == HFmode && TARGET_64BIT) \
> emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1)); \
> else if (GET_MODE (cmp_op0) == HFmode) \
> - emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1)); \
> + emit_insn (gen_f##CMP##_quietbfsi4 (*op0, cmp_op0, cmp_op1)); \
> + else if (GET_MODE (cmp_op0) == BFmode && TARGET_64BIT) \
> + emit_insn (gen_f##CMP##_quietbfdi4 (*op0, cmp_op0, cmp_op1)); \
> + else if (GET_MODE (cmp_op0) == BFmode) \
> + emit_insn (gen_f##CMP##_quietbfsi4 (*op0, cmp_op0, cmp_op1)); \
> else \
> gcc_unreachable (); \
> *op1 = const0_rtx; \
> @@ -6699,7 +6703,13 @@ riscv_mangle_type (const_tree type)
> {
> /* Half-precision float, _Float16 is "DF16_". */
> if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16)
> - return "DF16_";
> + {
> + if (TYPE_MAIN_VARIANT (type) == float16_type_node)
> + return "DF16_";
The conditions here are very likely to be false, even if "TYPE_MODE (type) == HFmode",
there may be a risk of ICE, I'm not sure.
> + 
> + if (TYPE_MODE (type) == BFmode)
> + return "DF16b";
> + } 
> 
> /* Mangle all vector type for vector extension. */
> /* The mangle name follows the rule of RVV LLVM
> @@ -6720,19 +6730,19 @@ 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);
> }
> 
> /* Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P - return TRUE
> - if MODE is HFmode, and punt to the generic implementation otherwise. */
> + if MODE is HFmode or BFmode, and punt to the generic implementation otherwise. */
> 
> static bool
> riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode)
> {
> - if (mode == HFmode)
> + if (mode == HFmode || mode == BFmode)
> return true;
> else
> return default_libgcc_floating_mode_supported_p (mode);
> @@ -6804,6 +6814,23 @@ riscv_init_libfuncs (void)
> set_optab_libfunc (ge_optab, HFmode, NULL);
> set_optab_libfunc (gt_optab, HFmode, NULL);
> set_optab_libfunc (unord_optab, HFmode, NULL);
> +
> + /* Bfloat16*/
> + /* Arithmetic. */
> + set_optab_libfunc (add_optab, BFmode, NULL);
> + set_optab_libfunc (sdiv_optab, BFmode, NULL);
> + set_optab_libfunc (smul_optab, BFmode, NULL);
> + set_optab_libfunc (neg_optab, BFmode, NULL);
> + set_optab_libfunc (sub_optab, BFmode, NULL);
> +
> + /* Comparisons. */
> + set_optab_libfunc (eq_optab, BFmode, NULL);
> + set_optab_libfunc (ne_optab, BFmode, NULL);
> + set_optab_libfunc (lt_optab, BFmode, NULL);
> + set_optab_libfunc (le_optab, BFmode, NULL);
> + set_optab_libfunc (ge_optab, BFmode, NULL);
> + set_optab_libfunc (gt_optab, BFmode, NULL);
> + set_optab_libfunc (unord_optab, BFmode, NULL);
> }
> 
> #if CHECKING_P
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 05924e9bbf1..89b10bada5e 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -158,7 +158,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,
> VNx1QI,VNx2QI,VNx4QI,VNx8QI,VNx16QI,VNx32QI,VNx64QI,
> VNx1HI,VNx2HI,VNx4HI,VNx8HI,VNx16HI,VNx32HI,
> @@ -1330,15 +1330,25 @@
> [(set_attr "type" "fcvt")
> (set_attr "mode" "HF")])
> 
> -(define_insn "truncdfhf2"
> - [(set (match_operand:HF 0 "register_operand" "=f")
> - (float_truncate:HF
> +(define_insn "truncsfbf2"
> + [(set (match_operand:BF 0 "register_operand" "=f")
> + (float_truncate:BF
> + (match_operand:SF 1 "register_operand" " f")))]
> + "TARGET_ZFBFMIN"
> + "fcvt.bf16.s\t%0,%1"
> + [(set_attr "type" "fcvt")
> + (set_attr "mode" "BF")])
> +
> +(define_insn "truncdf<BFHF:mode>2"
> + [(set (match_operand:BFHF 0 "register_operand" "=f")
> + (float_truncate:BFHF
> (match_operand:DF 1 "register_operand" " f")))]
> "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
> - (TARGET_ZHINXMIN && TARGET_ZDINX)"
> + (TARGET_ZHINXMIN && TARGET_ZDINX) || 
> + (TARGET_ZFBFMIN && TARGET_DOUBLE_FLOAT)"
> "fcvt.h.d\t%0,%1"
> [(set_attr "type" "fcvt")
> - (set_attr "mode" "HF")])
> + (set_attr "mode" "<BFHF:MODE>")])
> 
This may not be correct, because when double is converted to__bf16, it
should be converted to float first and then to__bf16. Right?
> ;;
> ;; ....................
> @@ -1466,6 +1476,15 @@
> [(set_attr "type" "fcvt")
> (set_attr "mode" "SF")])
> 
> +(define_insn "extendbfsf2"
> + [(set (match_operand:SF 0 "register_operand" "=f")
> + (float_extend:SF
> + (match_operand:BF 1 "register_operand" " f")))]
> + "TARGET_ZFBFMIN"
> + "fcvt.s.bf16\t%0,%1"
> + [(set_attr "type" "fcvt")
> + (set_attr "mode" "SF")])
> +
> (define_insn "extendsfdf2"
> [(set (match_operand:DF 0 "register_operand" "=f")
> (float_extend:DF
> @@ -1475,15 +1494,16 @@
> [(set_attr "type" "fcvt")
> (set_attr "mode" "DF")])
> 
> -(define_insn "extendhfdf2"
> +(define_insn "extend<BFHF:mode>df2"
> [(set (match_operand:DF 0 "register_operand" "=f")
> (float_extend:DF
> - (match_operand:HF 1 "register_operand" " f")))]
> + (match_operand:BFHF 1 "register_operand" " f")))]
> "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
> - (TARGET_ZHINXMIN && TARGET_ZDINX)"
> + (TARGET_ZHINXMIN && TARGET_ZDINX) ||
> + (TARGET_ZFBFMIN && TARGET_DOUBLE_FLOAT)"
> "fcvt.d.h\t%0,%1"
> [(set_attr "type" "fcvt")
> - (set_attr "mode" "DF")])
> + (set_attr "mode" "<BFHF:MODE>")])
> 
Same problem with truncdfbf2.
> ;; 16-bit floating point moves
> (define_expand "movhf"
> @@ -1515,6 +1535,35 @@
> [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
> (set_attr "mode" "HF")])
> 
> +(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_hardfloat"
> + [(set (match_operand:BF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m")
> + (match_operand:BF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
> + "TARGET_ZFBFMIN
> + && (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,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
> + (set_attr "mode" "BF")])
> +
> +(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"))]
> + "!TARGET_ZFHMIN
> + && (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")])
> +
Maybe merge with movhf, movhf_hardfloat and *movhf_softfloat?
> ;;
> ;; ....................
> ;;
> 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..dc85ff79c1c 100644
> --- a/libgcc/config/riscv/t-softfp32
> +++ b/libgcc/config/riscv/t-softfp32
> @@ -42,7 +42,9 @@ softfp_extras := divsf3 divdf3 divtf3
> 
> endif
> 
> -softfp_extensions += hfsf hfdf hftf
> -softfp_truncations += tfhf dfhf sfhf
> +softfp_extensions += hfsf hfdf hftf bfsf bfdf bftf
bfdf and bftf do not seem to be implemented
> +softfp_truncations += tfhf dfhf sfhf tfbf dfbf sfhf
sfhf repeat, the last one should be sfbf
hfbf may also be required?
> softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \
> - floatsihf floatdihf floatunsihf floatundihf
> + floatsihf floatdihf floatunsihf floatundihf \
> + fixbfsi fixbfdi fixunsbfsi fixunsbfdi \
> + floatsibf floatdibf floatunsibf floatundibf
 fixbfsi, fixbfdi, fixunsbfsi, fixunsbfdi, floatsibf and floatunsibf do
 not seem to be implemented.
  
Jin Ma June 15, 2023, 9:52 a.m. UTC | #10
> diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
> index 5b70ab20758..6349f032bc8 100644
> --- a/gcc/config/riscv/iterators.md
> +++ b/gcc/config/riscv/iterators.md
> @@ -61,10 +61,15 @@
>  ;; Iterator for hardware-supported floating-point modes.
>  (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT || TARGET_ZFINX")
>         (DF "TARGET_DOUBLE_FLOAT || TARGET_ZDINX")
> -       (HF "TARGET_ZFH || TARGET_ZHINX")])
> +       (HF "TARGET_ZFH || TARGET_ZHINX") 
> +    (BF "TARGET_ZFBFMIN")])
> +
> +;; Iterator for HImode constant generation.
> +(define_mode_iterator BFHF [BF HF])
>  
>  ;; Iterator for floating-point modes that can be loaded into X registers.
> -(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
> +(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")
> +    (BF "TARGET_ZFBFMIN")])
>  
>  
>  ;; -------------------------------------------------------------------
> @@ -76,27 +81,27 @@
>  (define_mode_attr size [(QI "b") (HI "h")])
>  
>  ;; Mode attributes for loads.
> -(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")])
> +(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (BF "flh") (HF "flh") (SF "flw") (DF "fld")])
>  
>  ;; Instruction names for integer loads that aren't explicitly sign or zero
>  ;; extended.  See riscv_output_move and LOAD_EXTEND_OP.
>  (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")])
> +(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (BF "fsh") (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.
>  (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
>  
>  ;; This attribute gives the format suffix for floating-point operations.
> -(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")])
> +(define_mode_attr fmt [(BF "h") (HF "h") (SF "s") (DF "d")])
>  
>  ;; This attribute gives the integer suffix for floating-point conversions.
>  (define_mode_attr ifmt [(SI "w") (DI "l")])
> @@ -106,7 +111,7 @@
>  
>  ;; This attribute gives the upper-case mode name for one unit of a
>  ;; floating-point mode.
> -(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")])
> +(define_mode_attr UNITMODE [(BF "BF") (HF "HF") (SF "SF") (DF "DF")])
>  

There are also some problems here, which cannot be simply handled like HF. 
Many instructions support HF but do not support BF. For example, fadd.h
can be used for HF but cannot be used for BF. 

I guess it may need to be converted to SF first, then fadd.s, and finally
converted to BF.  I'm not so sure.
  
Jeff Law June 17, 2023, 3:31 p.m. UTC | #11
On 6/15/23 03:52, Jin Ma wrote:

>>   
> 
> There are also some problems here, which cannot be simply handled like HF.
> Many instructions support HF but do not support BF. For example, fadd.h
> can be used for HF but cannot be used for BF.
> 
> I guess it may need to be converted to SF first, then fadd.s, and finally
> converted to BF.  I'm not so sure.
Right.  This is relatively common.

jeff
  

Patch

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index ebc1ed7d7e4..2b3ff1f5b8e 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -102,6 +102,8 @@  static const riscv_implied_info_t riscv_implied_info[] =
   {"zvl32768b", "zvl16384b"},
   {"zvl65536b", "zvl32768b"},
 
+  {"zfbfmin", "zfhmin"},
+
   {"zfh", "zfhmin"},
   {"zfhmin", "f"},
   
@@ -1239,6 +1241,8 @@  static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"zvl16384b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL16384B},
   {"zvl32768b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32768B},
   {"zvl65536b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL65536B},
+  
+  {"zfbfmin",    &gcc_options::x_riscv_zf_subext, MASK_ZFBFMIN},
 
   {"zfhmin",    &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN},
   {"zfh",       &gcc_options::x_riscv_zf_subext, MASK_ZFH},
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 5b70ab20758..6349f032bc8 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -61,10 +61,15 @@ 
 ;; Iterator for hardware-supported floating-point modes.
 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT || TARGET_ZFINX")
 			    (DF "TARGET_DOUBLE_FLOAT || TARGET_ZDINX")
-			    (HF "TARGET_ZFH || TARGET_ZHINX")])
+			    (HF "TARGET_ZFH || TARGET_ZHINX") 
+				(BF "TARGET_ZFBFMIN")])
+
+;; Iterator for HImode constant generation.
+(define_mode_iterator BFHF [BF HF])
 
 ;; Iterator for floating-point modes that can be loaded into X registers.
-(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
+(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")
+				(BF "TARGET_ZFBFMIN")])
 
 
 ;; -------------------------------------------------------------------
@@ -76,27 +81,27 @@ 
 (define_mode_attr size [(QI "b") (HI "h")])
 
 ;; Mode attributes for loads.
-(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")])
+(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (BF "flh") (HF "flh") (SF "flw") (DF "fld")])
 
 ;; Instruction names for integer loads that aren't explicitly sign or zero
 ;; extended.  See riscv_output_move and LOAD_EXTEND_OP.
 (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")])
+(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (BF "fsh") (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.
 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
 
 ;; This attribute gives the format suffix for floating-point operations.
-(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")])
+(define_mode_attr fmt [(BF "h") (HF "h") (SF "s") (DF "d")])
 
 ;; This attribute gives the integer suffix for floating-point conversions.
 (define_mode_attr ifmt [(SI "w") (DI "l")])
@@ -106,7 +111,7 @@ 
 
 ;; This attribute gives the upper-case mode name for one unit of a
 ;; floating-point mode.
-(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")])
+(define_mode_attr UNITMODE [(BF "BF") (HF "HF") (SF "SF") (DF "DF")])
 
 ;; This attribute gives the integer mode that has half the size of
 ;; the controlling mode.
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 25ca407f9a9..e0c6f6834a5 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -163,6 +163,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.  */
 
@@ -190,7 +191,7 @@  riscv_build_function_type (enum riscv_function_type type)
 }
 
 static void
-riscv_init_builtin_types (void)
+riscv_fp16_builtin_type (void)
 {
   /* Provide the _Float16 type and float16_type_node if needed.  */
   if (!float16_type_node)
@@ -208,6 +209,32 @@  riscv_init_builtin_types (void)
 					    "_Float16");
 }
 
+static void
+riscv_bf16_builtin_type (void)
+{
+  /* 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");
+}
+
+static void
+riscv_init_builtin_types (void)
+{
+  riscv_fp16_builtin_type ();
+  riscv_bf16_builtin_type ();
+}
+
 /* Implement TARGET_INIT_BUILTINS.  */
 
 void
diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def
index d5305efa8a6..93c22b09ed7 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-opts.h b/gcc/config/riscv/riscv-opts.h
index ff398c0a2ae..e5791019912 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -168,9 +168,11 @@  enum stack_protector_guard {
 
 #define MASK_ZFHMIN   (1 << 0)
 #define MASK_ZFH      (1 << 1)
+#define MASK_ZFBFMIN  (1 << 2)
 
 #define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0)
 #define TARGET_ZFH    ((riscv_zf_subext & MASK_ZFH) != 0)
+#define TARGET_ZFBFMIN  ((riscv_zf_subext & MASK_ZFBFMIN) != 0)
 
 #define MASK_ZMMUL      (1 << 0)
 #define TARGET_ZMMUL    ((riscv_zm_subext & MASK_ZMMUL) != 0)
diff --git a/gcc/config/riscv/riscv-vector-switch.def b/gcc/config/riscv/riscv-vector-switch.def
index 8e4aed40338..8808d0f9b44 100644
--- a/gcc/config/riscv/riscv-vector-switch.def
+++ b/gcc/config/riscv/riscv-vector-switch.def
@@ -75,7 +75,7 @@  n = SEW/LMUL
 |Types|n=1    |n=2    |n=4   |n=8   |n=16  |n=32  |n=64|
 |bool |VNx32BI|VNx16BI|VNx8BI|VNx4BI|VNx2BI|VNx1BI|N/A |
 
-TODO: FP16 vector needs support of 'zvfh', we don't support it yet.  */
+TODO: FP16 vector needs support of 'zvfh' and 'zvfbfmin', we don't support it yet.  */
 
 /* Return 'REQUIREMENT' for machine_mode 'MODE'.
    For example: 'MODE' = VNx64BImode needs TARGET_MIN_VLEN > 32.  */
@@ -120,7 +120,7 @@  ENTRY (VNx4HI, true, LMUL_2, 8, LMUL_1, 16)
 ENTRY (VNx2HI, true, LMUL_1, 16, LMUL_F2, 32)
 ENTRY (VNx1HI, true, LMUL_F2, 32, LMUL_F4, 64)
 
-/* TODO:Disable all FP16 vector, enable them when 'zvfh' is supported.  */
+/* TODO:Disable all FP16 vector, enable them when 'zvfh' and 'zvfbfmin' is supported.  */
 ENTRY (VNx32HF, false, LMUL_RESERVED, 0, LMUL_8, 2)
 ENTRY (VNx16HF, false, LMUL_8, 2, LMUL_4, 4)
 ENTRY (VNx8HF, false, LMUL_4, 4, LMUL_2, 8)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index f11b7949a49..2ddbdfa424a 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3192,7 +3192,11 @@  riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
       else if (GET_MODE (cmp_op0) == HFmode && TARGET_64BIT)		\
 	emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1));	\
       else if (GET_MODE (cmp_op0) == HFmode)				\
-	emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1));	\
+	emit_insn (gen_f##CMP##_quietbfsi4 (*op0, cmp_op0, cmp_op1));	\
+      else if (GET_MODE (cmp_op0) == BFmode && TARGET_64BIT)		\
+	emit_insn (gen_f##CMP##_quietbfdi4 (*op0, cmp_op0, cmp_op1));	\
+      else if (GET_MODE (cmp_op0) == BFmode)				\
+	emit_insn (gen_f##CMP##_quietbfsi4 (*op0, cmp_op0, cmp_op1));	\
       else								\
 	gcc_unreachable ();						\
       *op1 = const0_rtx;						\
@@ -6699,7 +6703,13 @@  riscv_mangle_type (const_tree type)
 {
   /* Half-precision float, _Float16 is "DF16_".  */
   if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16)
-    return "DF16_";
+  {
+    if (TYPE_MAIN_VARIANT (type) == float16_type_node)
+	return "DF16_";
+    
+    if (TYPE_MODE (type) == BFmode)
+	return "DF16b";
+  } 
 
   /* Mangle all vector type for vector extension.  */
   /* The mangle name follows the rule of RVV LLVM
@@ -6720,19 +6730,19 @@  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);
 }
 
 /* Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P - return TRUE
-   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+   if MODE is HFmode or BFmode, and punt to the generic implementation otherwise.  */
 
 static bool
 riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 {
-  if (mode == HFmode)
+  if (mode == HFmode || mode == BFmode)
     return true;
   else
     return default_libgcc_floating_mode_supported_p (mode);
@@ -6804,6 +6814,23 @@  riscv_init_libfuncs (void)
   set_optab_libfunc (ge_optab, HFmode, NULL);
   set_optab_libfunc (gt_optab, HFmode, NULL);
   set_optab_libfunc (unord_optab, HFmode, NULL);
+
+  /* Bfloat16*/
+  /* Arithmetic.  */
+  set_optab_libfunc (add_optab, BFmode, NULL);
+  set_optab_libfunc (sdiv_optab, BFmode, NULL);
+  set_optab_libfunc (smul_optab, BFmode, NULL);
+  set_optab_libfunc (neg_optab, BFmode, NULL);
+  set_optab_libfunc (sub_optab, BFmode, NULL);
+
+  /* Comparisons.  */
+  set_optab_libfunc (eq_optab, BFmode, NULL);
+  set_optab_libfunc (ne_optab, BFmode, NULL);
+  set_optab_libfunc (lt_optab, BFmode, NULL);
+  set_optab_libfunc (le_optab, BFmode, NULL);
+  set_optab_libfunc (ge_optab, BFmode, NULL);
+  set_optab_libfunc (gt_optab, BFmode, NULL);
+  set_optab_libfunc (unord_optab, BFmode, NULL);
 }
 
 #if CHECKING_P
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 05924e9bbf1..89b10bada5e 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -158,7 +158,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,
   VNx1QI,VNx2QI,VNx4QI,VNx8QI,VNx16QI,VNx32QI,VNx64QI,
   VNx1HI,VNx2HI,VNx4HI,VNx8HI,VNx16HI,VNx32HI,
@@ -1330,15 +1330,25 @@ 
   [(set_attr "type" "fcvt")
    (set_attr "mode" "HF")])
 
-(define_insn "truncdfhf2"
-  [(set (match_operand:HF     0 "register_operand" "=f")
-       (float_truncate:HF
+(define_insn "truncsfbf2"
+  [(set (match_operand:BF     0 "register_operand" "=f")
+       (float_truncate:BF
+           (match_operand:SF 1 "register_operand" " f")))]
+  "TARGET_ZFBFMIN"
+  "fcvt.bf16.s\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "BF")])
+
+(define_insn "truncdf<BFHF:mode>2"
+  [(set (match_operand:BFHF     0 "register_operand" "=f")
+       (float_truncate:BFHF
            (match_operand:DF 1 "register_operand" " f")))]
   "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
-   (TARGET_ZHINXMIN && TARGET_ZDINX)"
+   (TARGET_ZHINXMIN && TARGET_ZDINX) || 
+   (TARGET_ZFBFMIN && TARGET_DOUBLE_FLOAT)"
   "fcvt.h.d\t%0,%1"
   [(set_attr "type" "fcvt")
-   (set_attr "mode" "HF")])
+   (set_attr "mode" "<BFHF:MODE>")])
 
 ;;
 ;;  ....................
@@ -1466,6 +1476,15 @@ 
   [(set_attr "type" "fcvt")
    (set_attr "mode" "SF")])
 
+(define_insn "extendbfsf2"
+  [(set (match_operand:SF     0 "register_operand" "=f")
+       (float_extend:SF
+           (match_operand:BF 1 "register_operand" " f")))]
+  "TARGET_ZFBFMIN"
+  "fcvt.s.bf16\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "SF")])
+
 (define_insn "extendsfdf2"
   [(set (match_operand:DF     0 "register_operand" "=f")
 	(float_extend:DF
@@ -1475,15 +1494,16 @@ 
   [(set_attr "type" "fcvt")
    (set_attr "mode" "DF")])
 
-(define_insn "extendhfdf2"
+(define_insn "extend<BFHF:mode>df2"
   [(set (match_operand:DF     0 "register_operand" "=f")
        (float_extend:DF
-           (match_operand:HF 1 "register_operand" " f")))]
+           (match_operand:BFHF 1 "register_operand" " f")))]
   "(TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT) ||
-   (TARGET_ZHINXMIN && TARGET_ZDINX)"
+   (TARGET_ZHINXMIN && TARGET_ZDINX) ||
+   (TARGET_ZFBFMIN && TARGET_DOUBLE_FLOAT)"
   "fcvt.d.h\t%0,%1"
   [(set_attr "type" "fcvt")
-   (set_attr "mode" "DF")])
+   (set_attr "mode" "<BFHF:MODE>")])
 
 ;; 16-bit floating point moves
 (define_expand "movhf"
@@ -1515,6 +1535,35 @@ 
   [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
    (set_attr "mode" "HF")])
 
+(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_hardfloat"
+  [(set (match_operand:BF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  *r,*r,*m")
+	(match_operand:BF 1 "move_operand"         " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
+  "TARGET_ZFBFMIN
+   && (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,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+   (set_attr "mode" "BF")])
+
+(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"))]
+  "!TARGET_ZFHMIN
+   && (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/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..dc85ff79c1c 100644
--- a/libgcc/config/riscv/t-softfp32
+++ b/libgcc/config/riscv/t-softfp32
@@ -42,7 +42,9 @@  softfp_extras := divsf3 divdf3 divtf3
 
 endif
 
-softfp_extensions += hfsf hfdf hftf
-softfp_truncations += tfhf dfhf sfhf
+softfp_extensions += hfsf hfdf hftf bfsf bfdf bftf
+softfp_truncations += tfhf dfhf sfhf tfbf dfbf sfhf
 softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \
-                 floatsihf floatdihf floatunsihf floatundihf
+                 floatsihf floatdihf floatunsihf floatundihf \
+                 fixbfsi fixbfdi fixunsbfsi fixunsbfdi \
+                 floatsibf floatdibf floatunsibf floatundibf