mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-26 21:06:57 +08:00
[RISC-V] Add support for _Bfloat16
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>
This commit is contained in:
parent
6ffea3e373
commit
8c7cee80eb
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -10188,9 +10188,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
|
||||
@ -10211,19 +10219,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);
|
||||
@ -10274,27 +10283,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_block_arith_comp_libfuncs_for_mode (machine_mode mode)
|
||||
{
|
||||
/* 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, 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, 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)
|
||||
{
|
||||
/* Half-precision float operations. The compiler handles all operations
|
||||
with NULL libfuncs by converting to SFmode. */
|
||||
riscv_block_arith_comp_libfuncs_for_mode (HFmode);
|
||||
riscv_block_arith_comp_libfuncs_for_mode (BFmode);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
/* 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
|
||||
|
@ -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")
|
||||
|
42
gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c
Normal file
42
gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c
Normal file
@ -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" } } */
|
12
gcc/testsuite/gcc.target/riscv/bf16_call.c
Normal file
12
gcc/testsuite/gcc.target/riscv/bf16_call.c
Normal file
@ -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 } } */
|
36
gcc/testsuite/gcc.target/riscv/bf16_comparison.c
Normal file
36
gcc/testsuite/gcc.target/riscv/bf16_comparison.c
Normal file
@ -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" } } */
|
57
gcc/testsuite/gcc.target/riscv/bf16_float_libcall_convert.c
Normal file
57
gcc/testsuite/gcc.target/riscv/bf16_float_libcall_convert.c
Normal file
@ -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 } } } } */
|
@ -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 } } } } */
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
45
libgcc/soft-fp/floatsibf.c
Normal file
45
libgcc/soft-fp/floatsibf.c
Normal file
@ -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;
|
||||
}
|
45
libgcc/soft-fp/floatunsibf.c
Normal file
45
libgcc/soft-fp/floatunsibf.c
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user