diff mbox series

[NOT,CODE,REVIEW,v3,1/1,RISC-V] Add support for _Bfloat16

Message ID 20240506003845.70280-2-zengxiao@eswincomputing.com
State New
Headers show
Series Add support for _Bfloat16 | expand

Commit Message

Xiao Zeng May 6, 2024, 12:38 a.m. UTC
1 At point <https://github.com/riscv/riscv-bfloat16>,
  BF16 has already been completed "post public review".

2 LLVM has also added support for RISCV BF16 in
  <https://reviews.llvm.org/D151313> and
  <https://reviews.llvm.org/D150929>.

3 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.

Below test are passed for this patch
    * The riscv fully regression test.

gcc/ChangeLog:

	* config/riscv/iterators.md: New mode iterator HFBF.
	* config/riscv/riscv-builtins.cc (riscv_init_builtin_types):
	Initialize data type _Bfloat16.
	* config/riscv/riscv-modes.def (FLOAT_MODE): New.
	(ADJUST_FLOAT_FORMAT): New.
	* config/riscv/riscv.cc (riscv_mangle_type): Support for BFmode.
	(riscv_scalar_mode_supported_p): Ditto.
	(riscv_libgcc_floating_mode_supported_p): Ditto.
	(riscv_init_libfuncs): Set the conversion method for BFmode and
	HFmode.
	(riscv_block_arith_comp_libfuncs_for_mode): Set the arithmetic
	and comparison libfuncs for the mode.
	* config/riscv/riscv.md (mode" ): Add BF.
	(movhf): Support for BFmode.
	(mov<mode>): Ditto.
	(*movhf_softfloat): Ditto.
	(*mov<mode>_softfloat): Ditto.

libgcc/ChangeLog:

	* config/riscv/sfp-machine.h (_FP_NANFRAC_B): New.
	(_FP_NANSIGN_B): Ditto.
	* config/riscv/t-softfp32: Add support for BF16 libfuncs.
	* config/riscv/t-softfp64: Ditto.
	* soft-fp/floatsibf.c: For si -> bf16.
	* soft-fp/floatunsibf.c: For unsi -> bf16.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/bf16_arithmetic.c: New test.
	* gcc.target/riscv/bf16_call.c: New test.
	* gcc.target/riscv/bf16_comparison.c: New test.
	* gcc.target/riscv/bf16_float_libcall_convert.c: New test.
	* gcc.target/riscv/bf16_integer_libcall_convert.c: New test.

Co-authored-by: Jin Ma <jinma@linux.alibaba.com>
---
 gcc/config/riscv/iterators.md                 |  2 +
 gcc/config/riscv/riscv-builtins.cc            | 16 ++++
 gcc/config/riscv/riscv-modes.def              |  3 +
 gcc/config/riscv/riscv.cc                     | 64 ++++++++++-----
 gcc/config/riscv/riscv.md                     | 24 +++---
 .../gcc.target/riscv/bf16_arithmetic.c        | 42 ++++++++++
 gcc/testsuite/gcc.target/riscv/bf16_call.c    | 12 +++
 .../gcc.target/riscv/bf16_comparison.c        | 36 +++++++++
 .../riscv/bf16_float_libcall_convert.c        | 57 +++++++++++++
 .../riscv/bf16_integer_libcall_convert.c      | 81 +++++++++++++++++++
 libgcc/config/riscv/sfp-machine.h             |  3 +
 libgcc/config/riscv/t-softfp32                | 10 ++-
 libgcc/config/riscv/t-softfp64                |  3 +-
 libgcc/soft-fp/floatsibf.c                    | 45 +++++++++++
 libgcc/soft-fp/floatunsibf.c                  | 45 +++++++++++
 15 files changed, 407 insertions(+), 36 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_call.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_comparison.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_float_libcall_convert.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_integer_libcall_convert.c
 create mode 100644 libgcc/soft-fp/floatsibf.c
 create mode 100644 libgcc/soft-fp/floatunsibf.c

Comments

Jeff Law May 6, 2024, 9:40 p.m. UTC | #1
On 5/5/24 6:38 PM, Xiao Zeng wrote:
> 1 At point <https://github.com/riscv/riscv-bfloat16>,
>    BF16 has already been completed "post public review".
> 
> 2 LLVM has also added support for RISCV BF16 in
>    <https://reviews.llvm.org/D151313> and
>    <https://reviews.llvm.org/D150929>.
> 
> 3 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.
> 
> Below test are passed for this patch
>      * The riscv fully regression test.
> 
> gcc/ChangeLog:
> 
> 	* config/riscv/iterators.md: New mode iterator HFBF.
> 	* config/riscv/riscv-builtins.cc (riscv_init_builtin_types):
> 	Initialize data type _Bfloat16.
> 	* config/riscv/riscv-modes.def (FLOAT_MODE): New.
> 	(ADJUST_FLOAT_FORMAT): New.
> 	* config/riscv/riscv.cc (riscv_mangle_type): Support for BFmode.
> 	(riscv_scalar_mode_supported_p): Ditto.
> 	(riscv_libgcc_floating_mode_supported_p): Ditto.
> 	(riscv_init_libfuncs): Set the conversion method for BFmode and
> 	HFmode.
> 	(riscv_block_arith_comp_libfuncs_for_mode): Set the arithmetic
> 	and comparison libfuncs for the mode.
> 	* config/riscv/riscv.md (mode" ): Add BF.
> 	(movhf): Support for BFmode.
> 	(mov<mode>): Ditto.
> 	(*movhf_softfloat): Ditto.
> 	(*mov<mode>_softfloat): Ditto.
> 
> libgcc/ChangeLog:
> 
> 	* config/riscv/sfp-machine.h (_FP_NANFRAC_B): New.
> 	(_FP_NANSIGN_B): Ditto.
> 	* config/riscv/t-softfp32: Add support for BF16 libfuncs.
> 	* config/riscv/t-softfp64: Ditto.
> 	* soft-fp/floatsibf.c: For si -> bf16.
> 	* soft-fp/floatunsibf.c: For unsi -> bf16.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/riscv/bf16_arithmetic.c: New test.
> 	* gcc.target/riscv/bf16_call.c: New test.
> 	* gcc.target/riscv/bf16_comparison.c: New test.
> 	* gcc.target/riscv/bf16_float_libcall_convert.c: New test.
> 	* gcc.target/riscv/bf16_integer_libcall_convert.c: New test.
Given we were only looking to have the CI system check the formatting 
nit and that has passed.  I've pushed this to the trunk.

jeff
Andreas Schwab May 14, 2024, 8:05 a.m. UTC | #2
This breaks libstdc++-abi/abi_check.

3 incompatible symbols 
0
_ZTIPKDF16b
typeinfo for std::bfloat16_t const*
version status: incompatible
CXXABI_1.3.14
type: object
type size: 32
status: added


1
_ZTIPDF16b
typeinfo for std::bfloat16_t*
version status: incompatible
CXXABI_1.3.14
type: object
type size: 32
status: added


2
_ZTIDF16b
typeinfo for std::bfloat16_t
version status: incompatible
CXXABI_1.3.14
type: object
type size: 16
status: added
Kito Cheng May 16, 2024, 8:55 a.m. UTC | #3
Hi Xiao Zeng:

Just wondering why use _Bfloat16 rather than __bf16? you mention
__bf16 in comment, but implementation use _Bfloat16? I would like to
use __bf16 to make it consistent between LLVM and psABI if possible :)
Xiao Zeng May 16, 2024, 9:25 a.m. UTC | #4
2024-05-16 16:55  Kito Cheng <kito.cheng@gmail.com> wrote:
>
>Hi Xiao Zeng:
>
>Just wondering why use _Bfloat16 rather than __bf16? you mention
>__bf16 in comment, but implementation use _Bfloat16?
Obviously, this is a mistake.
This patch has spanned a considerable amount of time locally.

I will submit a new patch to correct it.
> I would like to use __bf16 to make it consistent between LLVM and psABI if possible :)
Thanks Kito for pointing out this point. Meanwhile, due to my issue, I did not see
Andreas Schwab's email. He had already sent me an email earlier, pointing out the existing issues.
<https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651529.html>

By the way, if I don't reply to the email in a timely manner, it must be my problem.
Please send me another email to remind me.
I will reset the email to avoid missing any emails

Thanks
Xiao Zeng
diff mbox series

Patch

diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 75e119e407a..32e1b140305 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -75,6 +75,8 @@ 
 ;; Iterator for floating-point modes that can be loaded into X registers.
 (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
 
+;; Iterator for floating-point modes of BF16
+(define_mode_iterator HFBF [HF BF])
 
 ;; -------------------------------------------------------------------
 ;; Mode attributes
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index d457e306dd1..4c08834288a 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -230,6 +230,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.  */
 
@@ -273,6 +274,21 @@  riscv_init_builtin_types (void)
   if (!maybe_get_identifier ("_Float16"))
     lang_hooks.types.register_builtin_type (riscv_float16_type_node,
 					    "_Float16");
+
+  /* Provide the _Bfloat16 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 ("_Bfloat16"))
+    lang_hooks.types.register_builtin_type (riscv_bfloat16_type_node,
+					    "_Bfloat16");
 }
 
 /* Implement TARGET_INIT_BUILTINS.  */
diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def
index bdce89b17aa..6de4e440298 100644
--- a/gcc/config/riscv/riscv-modes.def
+++ b/gcc/config/riscv/riscv-modes.def
@@ -21,6 +21,9 @@  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);
+/* Reuse definition from arm.  */
+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 44945d47fd6..d19fd273afc 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -10132,9 +10132,17 @@  riscv_asan_shadow_offset (void)
 static const char *
 riscv_mangle_type (const_tree type)
 {
-  /* Half-precision float, _Float16 is "DF16_".  */
+  /* Half-precision float, _Float16 is "DF16_" and _Bfloat16 is "DF16b".  */
   if (SCALAR_FLOAT_TYPE_P (type) && TYPE_PRECISION (type) == 16)
-    return "DF16_";
+    {
+      if (TYPE_MODE (type) == HFmode)
+	return "DF16_";
+
+      if (TYPE_MODE (type) == BFmode)
+	return "DF16b";
+
+      gcc_unreachable ();
+    }
 
   /* Mangle all vector type for vector extension.  */
   /* The mangle name follows the rule of RVV LLVM
@@ -10155,19 +10163,20 @@  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);
@@ -10218,27 +10227,42 @@  riscv_floatn_mode (int n, bool extended)
   return default_floatn_mode (n, extended);
 }
 
+/* Record that we have no arithmetic or comparison libfuncs for
+   machine_mode MODE.  */
 static void
-riscv_init_libfuncs (void)
+riscv_block_arith_comp_libfuncs_for_mode (machine_mode mode)
 {
-  /* Half-precision float operations.  The compiler handles all operations
-     with NULL libfuncs by converting to SFmode.  */
+  /* Half-precision float or Brain float operations.  The compiler handles all
+     operations with NULL libfuncs by converting to SFmode.  */
 
   /* Arithmetic.  */
-  set_optab_libfunc (add_optab, HFmode, NULL);
-  set_optab_libfunc (sdiv_optab, HFmode, NULL);
-  set_optab_libfunc (smul_optab, HFmode, NULL);
-  set_optab_libfunc (neg_optab, HFmode, NULL);
-  set_optab_libfunc (sub_optab, HFmode, NULL);
+  set_optab_libfunc (add_optab, mode, NULL);
+  set_optab_libfunc (sdiv_optab, mode, NULL);
+  set_optab_libfunc (smul_optab, mode, NULL);
+  set_optab_libfunc (neg_optab, mode, NULL);
+  set_optab_libfunc (sub_optab, mode, NULL);
 
   /* Comparisons.  */
-  set_optab_libfunc (eq_optab, HFmode, NULL);
-  set_optab_libfunc (ne_optab, HFmode, NULL);
-  set_optab_libfunc (lt_optab, HFmode, NULL);
-  set_optab_libfunc (le_optab, HFmode, NULL);
-  set_optab_libfunc (ge_optab, HFmode, NULL);
-  set_optab_libfunc (gt_optab, HFmode, NULL);
-  set_optab_libfunc (unord_optab, HFmode, NULL);
+  set_optab_libfunc (eq_optab, mode, NULL);
+  set_optab_libfunc (ne_optab, mode, NULL);
+  set_optab_libfunc (lt_optab, mode, NULL);
+  set_optab_libfunc (le_optab, mode, NULL);
+  set_optab_libfunc (ge_optab, mode, NULL);
+  set_optab_libfunc (gt_optab, mode, NULL);
+  set_optab_libfunc (unord_optab, mode, NULL);
+}
+
+static void
+riscv_init_libfuncs (void)
+{
+  riscv_block_arith_comp_libfuncs_for_mode (HFmode);
+  riscv_block_arith_comp_libfuncs_for_mode (BFmode);
+
+  /* Convert between BFmode and HFmode using only trunc libfunc if needed.  */
+  set_conv_libfunc (sext_optab, BFmode, HFmode, "__trunchfbf2");
+  set_conv_libfunc (sext_optab, HFmode, BFmode, "__truncbfhf2");
+  set_conv_libfunc (trunc_optab, BFmode, HFmode, "__trunchfbf2");
+  set_conv_libfunc (trunc_optab, HFmode, BFmode, "__truncbfhf2");
 }
 
 #if CHECKING_P
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index d4676507b45..24558682eb8 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -196,7 +196,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,HF,BF,SF,DF,TF,
   RVVMF64BI,RVVMF32BI,RVVMF16BI,RVVMF8BI,RVVMF4BI,RVVMF2BI,RVVM1BI,
   RVVM8QI,RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI,
   RVVM8HI,RVVM4HI,RVVM2HI,RVVM1HI,RVVMF2HI,RVVMF4HI,
@@ -1887,12 +1887,12 @@ 
    (set_attr "mode" "DF")])
 
 ;; 16-bit floating point moves
-(define_expand "movhf"
-  [(set (match_operand:HF 0 "")
-	(match_operand:HF 1 ""))]
+(define_expand "mov<mode>"
+  [(set (match_operand:HFBF 0 "")
+	(match_operand:HFBF 1 ""))]
   ""
 {
-  if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
+  if (riscv_legitimize_move (<MODE>mode, operands[0], operands[1]))
     DONE;
 })
 
@@ -1907,16 +1907,16 @@ 
    (set_attr "type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
    (set_attr "mode" "HF")])
 
-(define_insn "*movhf_softfloat"
-  [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
-	(match_operand:HF 1 "move_operand"         " f,Gr,m,r,*r,*f"))]
-  "!TARGET_ZFHMIN
-   && (register_operand (operands[0], HFmode)
-       || reg_or_0_operand (operands[1], HFmode))"
+(define_insn "*mov<mode>_softfloat"
+  [(set (match_operand:HFBF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
+	(match_operand:HFBF 1 "move_operand"	     " f,Gr,m,r,*r,*f"))]
+  "((!TARGET_ZFHMIN && <MODE>mode == HFmode) || (<MODE>mode == BFmode))
+   && (register_operand (operands[0], <MODE>mode)
+       || reg_or_0_operand (operands[1], <MODE>mode))"
   { return riscv_output_move (operands[0], operands[1]); }
   [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
    (set_attr "type" "fmove,move,load,store,mtc,mfc")
-   (set_attr "mode" "HF")])
+   (set_attr "mode" "<MODE>")])
 
 (define_insn "*movhf_softfloat_boxing"
   [(set (match_operand:HF 0 "register_operand"            "=f")
diff --git a/gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c b/gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c
new file mode 100644
index 00000000000..9e485051260
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c
@@ -0,0 +1,42 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
+/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
+
+/* 1) bf -> sf          (call      __extendbfsf2)  */
+/* 2) sf1 [+|-|*|/] sf2 (call      __[add|sub|mul|div]sf3)  */
+/* 3) sf -> bf          (call      __truncsfbf2)  */
+extern _Bfloat16 bf;
+extern _Bfloat16 bf1;
+extern _Bfloat16 bf2;
+
+void bf_add_bf () { bf = bf1 + bf2; }
+
+void bf_sub_bf () { bf = bf1 - bf2; }
+
+void bf_mul_bf () { bf = bf1 * bf2; }
+
+void bf_div_bf () { bf = bf1 / bf2; }
+
+void bf_add_const () { bf = bf1 + 3.14f; }
+
+void const_sub_bf () { bf = 3.14f - bf2; }
+
+void bf_mul_const () { bf = bf1 * 3.14f; }
+
+void const_div_bf () { bf = 3.14f / bf2; }
+
+void bf_inc () { ++bf; }
+
+void bf_dec () { --bf; }
+
+/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 16 } } */
+/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 10 } } */
+/* { dg-final { scan-assembler-times "call\t__addsf3" 3 } } */
+/* { dg-final { scan-assembler-times "call\t__subsf3" 3 } } */
+/* { dg-final { scan-assembler-times "call\t__mulsf3" 2 } } */
+/* { dg-final { scan-assembler-times "call\t__divsf3" 2 } } */
+
+/* { dg-final { scan-assembler-not "call\t__addbf3" } } */
+/* { dg-final { scan-assembler-not "call\t__subbf3" } } */
+/* { dg-final { scan-assembler-not "call\t__mulbf3" } } */
+/* { dg-final { scan-assembler-not "call\t__divbf3" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/bf16_call.c b/gcc/testsuite/gcc.target/riscv/bf16_call.c
new file mode 100644
index 00000000000..29f67719999
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bf16_call.c
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
+/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
+
+/* 1) bf -> sf (call      __extendbfsf2)  */
+/* 2) sf -> bf (call      __truncsfbf2)  */
+__attribute__ ((noinline)) _Bfloat16 add (_Bfloat16 a, _Bfloat16 b) { return a + b; }
+
+_Bfloat16 test(_Bfloat16 a, _Bfloat16 b) { return add (a, b); }
+
+/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 2 } } */
+/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/bf16_comparison.c b/gcc/testsuite/gcc.target/riscv/bf16_comparison.c
new file mode 100644
index 00000000000..69db803f403
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bf16_comparison.c
@@ -0,0 +1,36 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
+/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
+
+/* 1) bf -> sf               (call	__extendbfsf2)  */
+/* 2) sf1 [<|<=|>|>=|==] sf2 (call	__[lt|le|gt|ge|eq]sf2)  */
+extern _Bfloat16 bf;
+extern _Bfloat16 bf1;
+extern _Bfloat16 bf2;
+
+void bf_lt_bf () { bf = (bf1 < bf2) ? bf1 : bf2; }
+
+void bf_le_bf () { bf = (bf1 <= bf2) ? bf1 : bf2; }
+
+void bf_gt_bf () { bf = (bf1 > bf2) ? bf1 : bf2; }
+
+void bf_ge_bf () { bf = (bf1 >= bf2) ? bf1 : bf2; }
+
+void bf_eq_bf () { bf = (bf1 == bf2) ? bf1 : bf2; }
+
+void bf_lt_const () { bf = (bf1 < 3.14f) ? bf1 : bf2; }
+
+void bf_le_const () { bf = (bf1 <= 3.14f) ? bf1 : bf2; }
+
+void const_gt_bf () { bf = (3.14f > bf2) ? bf1 : bf2; }
+
+void const_ge_bf () { bf = (3.14f >= bf2) ? bf1 : bf2; }
+
+void bf_eq_const () { bf = (bf1 == 3.14f) ? bf1 : bf2; }
+
+/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 15 } } */
+/* { dg-final { scan-assembler-not "call\t__ltbf2" } } */
+/* { dg-final { scan-assembler-not "call\t__lebf2" } } */
+/* { dg-final { scan-assembler-not "call\t__gtbf2" } } */
+/* { dg-final { scan-assembler-not "call\t__gebf2" } } */
+/* { dg-final { scan-assembler-not "call\t__eqbf2" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/bf16_float_libcall_convert.c b/gcc/testsuite/gcc.target/riscv/bf16_float_libcall_convert.c
new file mode 100644
index 00000000000..ba6c6460bc2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bf16_float_libcall_convert.c
@@ -0,0 +1,57 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
+/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
+
+
+/* 1) float       -> BF16
+ *    hf/sf/df/tf -> bf                   (call   __trunc[h|s|d|t]fbf2)
+*/
+
+/* 2) BF16        -> float
+ *    bf          -> hf == sf -> hf       (call   __truncsfhf2)
+ *    bf          -> sf                   (call   __extendbfsf2)
+ *    bf          -> df == bf -> sf -> df (call   __extendbfsf2 && __extendsfdf2)
+ *    bf          -> tf == bf -> sf -> tf (call   __extendbfsf2 && __extendsftf2)
+*/
+
+extern   _Bfloat16 bf;
+extern   _Float16  hf;
+extern      float  sf;
+extern      double df;
+extern long double tf;
+
+void hf_to_bf () { bf = hf; }
+void bf_to_hf () { hf = bf; }
+
+void sf_to_bf () { bf = sf; }
+void bf_to_sf () { sf = bf; }
+
+void df_to_bf () { bf = df; } 
+void bf_to_df () { df = bf; }
+
+void tf_to_bf () { bf = tf; }
+void bf_to_tf () { tf = bf; }
+
+/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 3 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 3 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__extendsfdf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__extendsfdf2" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__extendsftf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__extendsftf2" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__truncdfbf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__truncdfbf2" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__trunctfbf2" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__trunctfbf2" 1 { target { rv64 } } } } */
diff --git a/gcc/testsuite/gcc.target/riscv/bf16_integer_libcall_convert.c b/gcc/testsuite/gcc.target/riscv/bf16_integer_libcall_convert.c
new file mode 100644
index 00000000000..ad714253a4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/bf16_integer_libcall_convert.c
@@ -0,0 +1,81 @@ 
+/* { dg-do compile } */
+/* { dg-options "-march=rv32i -mabi=ilp32 -O" { target { rv32 } } } */
+/* { dg-options "-march=rv64i -mabi=lp64 -O" { target { rv64 } } } */
+
+/* 1) Integer     -> BF16 
+ *    qi/hi/si    -> bf (call	__floatsibf) 
+ *    uqi/uhi/usi -> bf (call	__floatunsibf)  
+ *    di/ti       -> bf (call	__float[d|t]ibf)
+ *    udi/uti     -> bf (call	__floatun[d|t]ibf)
+*/
+
+/* 2) BF16        -> Integer
+ *    bf          -> qi/hi/si    (call   __fixsfsi)
+ *    bf          -> uqi/uhi/usi (call   __fixunssfsi)
+ *    bf          -> di/ti       (call   __fixsf[d|t]i)
+ *    bf          -> udi/uti     (call   __fixunssf[d|t]i)
+*/
+
+extern _Bfloat16 bf;
+
+extern   signed char       qi;
+extern unsigned char      uqi;
+extern   signed short      hi;
+extern unsigned short     uhi;
+extern   signed int        si;
+extern unsigned int       usi;
+extern   signed long long  di;
+extern unsigned long long udi;
+
+void qi_to_bf ()  { bf = qi; }
+void uqi_to_bf () { bf = uqi; }
+void bf_to_qi ()  { qi = bf; }
+void bf_to_uqi () { uqi = bf; }
+
+void hi_to_bf ()  { bf = hi; }
+void uhi_to_bf () { bf = uhi; }
+void bf_to_hi ()  { hi = bf; }
+void bf_to_uhi () { uhi = bf; }
+
+void si_to_bf ()  { bf = si; }
+void usi_to_bf () { bf = usi; }
+void bf_to_si ()  { si = bf; }
+void bf_to_usi () { usi = bf; }
+
+void di_to_bf ()  { bf = di; }
+void udi_to_bf () { bf = udi; }
+void bf_to_di ()  { di = bf; }
+void bf_to_udi () { udi = bf; }
+
+#if __riscv_xlen == 64
+extern   signed __int128   ti; 
+extern unsigned __int128  uti; 
+void ti_to_bf ()  { bf = ti; }  /* { dg-final { scan-assembler-times "call\t__floattibf" 1 { target { rv64 } } } } */
+void uti_to_bf () { bf = uti; } /* { dg-final { scan-assembler-times "call\t__floatuntibf" 1 { target { rv64 } } } } */
+void bf_to_ti ()  { ti = bf; }  /* { dg-final { scan-assembler-times "call\t__fixsfti" 1 { target { rv64 } } } } */
+void bf_to_uti () { uti = bf; } /* { dg-final { scan-assembler-times "call\t__fixunssfti" 1 { target { rv64 } } } } */
+#endif
+
+/* { dg-final { scan-assembler-times "call\t__fixsfsi" 3 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__fixsfsi" 3 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__fixsfdi" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__fixsfdi" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__fixunssfsi" 3 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__fixunssfsi" 3 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__fixunssfdi" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__fixunssfdi" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__floatsibf" 3 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__floatsibf" 3 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__floatdibf" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__floatdibf" 1 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__floatunsibf" 3 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__floatunsibf" 3 { target { rv64 } } } } */
+
+/* { dg-final { scan-assembler-times "call\t__floatundibf" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "call\t__floatundibf" 1 { target { rv64 } } } } */
diff --git a/libgcc/config/riscv/sfp-machine.h b/libgcc/config/riscv/sfp-machine.h
index 0ad97081e88..9d3552ce48f 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 1a3b1caa6b0..da55eb348c1 100644
--- a/libgcc/config/riscv/t-softfp32
+++ b/libgcc/config/riscv/t-softfp32
@@ -42,7 +42,11 @@  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 \
+		      tfbf dfbf sfbf \
+		      hfbf bfhf
 softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \
-                 floatsihf floatdihf floatunsihf floatundihf
+		 floatsihf floatdihf floatunsihf floatundihf \
+		 floatsibf floatdibf floatunsibf floatundibf
diff --git a/libgcc/config/riscv/t-softfp64 b/libgcc/config/riscv/t-softfp64
index c87d242d5c3..936e58e6cb1 100644
--- a/libgcc/config/riscv/t-softfp64
+++ b/libgcc/config/riscv/t-softfp64
@@ -1,4 +1,5 @@ 
 include $(srcdir)/config/riscv/t-softfp32
 
 softfp_int_modes += ti
-softfp_extras += fixhfti fixunshfti floattihf floatuntihf
+softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
+		 floattibf floatuntibf
diff --git a/libgcc/soft-fp/floatsibf.c b/libgcc/soft-fp/floatsibf.c
new file mode 100644
index 00000000000..0cb05e58fc1
--- /dev/null
+++ b/libgcc/soft-fp/floatsibf.c
@@ -0,0 +1,45 @@ 
+/* Software floating-point emulation.
+   Convert a 32bit signed integer to bfloat16
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "brain.h"
+
+BFtype
+__floatsibf (SItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_B (A);
+  BFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_B (A, i, SI_BITS, USItype);
+  FP_PACK_RAW_B (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/floatunsibf.c b/libgcc/soft-fp/floatunsibf.c
new file mode 100644
index 00000000000..cd8c4bc8839
--- /dev/null
+++ b/libgcc/soft-fp/floatunsibf.c
@@ -0,0 +1,45 @@ 
+/* Software floating-point emulation.
+   Convert a 32bit unsigned integer to bfloat16
+   Copyright (C) 2007-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "brain.h"
+
+BFtype
+__floatunsibf (USItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_B (A);
+  BFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_B (A, i, SI_BITS, USItype);
+  FP_PACK_RAW_B (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}