From patchwork Tue Sep 19 08:44:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jin Ma X-Patchwork-Id: 141741 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:172:b0:3f2:4152:657d with SMTP id h50csp3225446vqi; Tue, 19 Sep 2023 01:45:44 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFZfNVp3zJ0pwbNkhYzcvCXNGdjdn/XXxcbxXUtYaagiO9g4TtpdPDSl8iTnTQ12KTiKM+X X-Received: by 2002:a05:6402:1a32:b0:525:6c9f:e1a3 with SMTP id be18-20020a0564021a3200b005256c9fe1a3mr10042010edb.20.1695113143836; Tue, 19 Sep 2023 01:45:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695113143; cv=none; d=google.com; s=arc-20160816; b=mYjNjfhROlMU+MXo+6iShSI3oiYRCfWjyjrvr00tfrTFMr3gIARHdRKoXo9SvAcN93 6QpbrwsRPjzOHS9x7jkwe0p3T8XM19NS8xUnqBZ+KQuI9CYyvIQqHImzQK9GNWGfaW1+ CvtNVMtkwZj9dL4EsxSJtb251oUF4PEx9sl/wv7wEO5tNtWEzH1LGns7SRsaMwip5hpH jAz1jyBS1J26tlDlDpSof9l+HtviI+wRUiwFFBSbK8X4xxQekGuRfxgrc1roMRUOR4iH fR3vONYt5qGNdT0A1jqPWdCjR/r82BT96GL/88cH5w19Vxp1YaxdTI+a1FjYvieO/HK6 ydGg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:message-id:date:subject:cc:to:from:dmarc-filter :delivered-to; bh=uurjcW02rTfmFRJpvhCBloEmfUy0rm9F4OYEhvksC3Y=; fh=PNKHkBOXPoSDTszGHOh5AIQxdUaUJea5dXvcOFWiGwk=; b=GzP3toMZrviRvb55tl3zHqqjtCku2DnHEBAg+eudM0anYDWmOzqPMJ5L0RCbSg3GUR kQQWMcjnrl7otKvNWKbjGlZd0kDzoqXdU43MoCnsgQoilo59QKpj0Tt7LjIS5tGuZ1e4 Il5cf1aLqmTKXZMr8HyzS32tHEhq6r1pLC62RCFXR53Xx6+uLMGNjhUnCarXlS/7D9VG b6ulvfcGSmRCIYe3i1conr2UiLKb2i32L/R8op/NbGrKlslTmbPl0GPlCe6E9DbbDCD7 IZYq64lB7qOCurZjDkjydcdyECPKewCTbPSCuRZIReG6E9AOFdn3gIyVOi4cmI45zqAF uNcA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id o22-20020a056402039600b005325187f6acsi1588819edv.652.2023.09.19.01.45.43 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Sep 2023 01:45:43 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 85AFB3856DD0 for ; Tue, 19 Sep 2023 08:45:37 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out30-98.freemail.mail.aliyun.com (out30-98.freemail.mail.aliyun.com [115.124.30.98]) by sourceware.org (Postfix) with ESMTPS id E3D8C3858D32 for ; Tue, 19 Sep 2023 08:44:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E3D8C3858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.alibaba.com X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R151e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=ay29a033018046049; MF=jinma@linux.alibaba.com; NM=1; PH=DS; RN=11; SR=0; TI=SMTPD_---0VsQqiCM_1695113092; Received: from localhost.localdomain(mailfrom:jinma@linux.alibaba.com fp:SMTPD_---0VsQqiCM_1695113092) by smtp.aliyun-inc.com; Tue, 19 Sep 2023 16:44:53 +0800 From: Jin Ma To: gcc-patches@gcc.gnu.org Cc: jeffreyalaw@gmail.com, palmer@dabbelt.com, richard.sandiford@arm.com, kito.cheng@gmail.com, philipp.tomsich@vrull.eu, christoph.muellner@vrull.eu, rdapp.gcc@gmail.com, juzhe.zhong@rivai.ai, jinma.contrib@gmail.com, Jin Ma Subject: [RFC 1/2] RISC-V: Add support for _Bfloat16. Date: Tue, 19 Sep 2023 16:44:43 +0800 Message-Id: <20230919084444.2089-1-jinma@linux.alibaba.com> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 X-Spam-Status: No, score=-19.4 required=5.0 tests=BAYES_00, ENV_AND_HDR_SPF_MATCH, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, UNPARSEABLE_RELAY, URIBL_BLACK, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1777454960386971595 X-GMAIL-MSGID: 1777454960386971595 gcc/ChangeLog: * config/riscv/iterators.md (HFBF): New. * 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_block_arith_comp_libfuncs_for_mode): New. (riscv_init_libfuncs): Opening and closing some libfuncs for BFmode. * config/riscv/riscv.md (mode" ): Add BF. (truncdfbf2): New. (movhf): Support for BFmode. (mov): Ditto. (*mov_softfloat): Ditto. (fix_truncbf2): New. (fixuns_truncbf2): New. (floatbf2): New. (floatunsbf2): New. libgcc/ChangeLog: * config/riscv/sfp-machine.h (_FP_NANFRAC_B): New. (_FP_NANSIGN_B): New. * config/riscv/t-softfp32: Add support for BF libfuncs. gcc/testsuite/ChangeLog: * gcc.target/riscv/bf16_arithmetic.c: New test. * gcc.target/riscv/bf16_call.c: New test. * gcc.target/riscv/bf16_comparisons.c: New test. * gcc.target/riscv/bf16_convert-1.c: New test. * gcc.target/riscv/bf16_convert-2.c: New test. * gcc.target/riscv/bf16_convert_run.c: New test. --- gcc/config/riscv/iterators.md | 2 + gcc/config/riscv/riscv-builtins.cc | 16 ++ gcc/config/riscv/riscv-modes.def | 4 + gcc/config/riscv/riscv.cc | 93 ++++++++-- gcc/config/riscv/riscv.md | 94 ++++++++-- .../gcc.target/riscv/bf16_arithmetic.c | 36 ++++ gcc/testsuite/gcc.target/riscv/bf16_call.c | 17 ++ .../gcc.target/riscv/bf16_comparisons.c | 25 +++ .../gcc.target/riscv/bf16_convert-1.c | 39 +++++ .../gcc.target/riscv/bf16_convert-2.c | 38 ++++ .../gcc.target/riscv/bf16_convert_run.c | 163 ++++++++++++++++++ libgcc/config/riscv/sfp-machine.h | 3 + libgcc/config/riscv/t-softfp32 | 7 +- 13 files changed, 503 insertions(+), 34 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_comparisons.c create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_convert-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_convert-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/bf16_convert_run.c diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index ecf033f2fa7..73523b73fdd 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -84,6 +84,8 @@ (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")]) ;; instruction. (define_mode_attr size [(QI "b") (HI "h")]) +(define_mode_iterator HFBF [HF BF]) + ;; Mode attributes for loads. (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")]) diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc index 3fe3a89dcc2..b7bb89794f7 100644 --- a/gcc/config/riscv/riscv-builtins.cc +++ b/gcc/config/riscv/riscv-builtins.cc @@ -192,6 +192,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. */ @@ -235,6 +236,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 e3c6ccb2809..723bfaee42d 100644 --- a/gcc/config/riscv/riscv-modes.def +++ b/gcc/config/riscv/riscv-modes.def @@ -22,6 +22,10 @@ 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. */ /* Encode the ratio of SEW/LMUL into the mask types. There are the following diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 8c766e2e2be..910523ee2b9 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -8727,9 +8727,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 @@ -8750,19 +8758,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); @@ -8813,27 +8821,74 @@ 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) +{ + /* 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) { + machine_mode mode_iter; /* Half-precision 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); + riscv_block_arith_comp_libfuncs_for_mode (HFmode); - /* 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); + /* For all possible libcalls in BFmode, record NULL. */ + riscv_block_arith_comp_libfuncs_for_mode (BFmode); + FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_FLOAT) + { + set_conv_libfunc (trunc_optab, BFmode, mode_iter, NULL); + set_conv_libfunc (trunc_optab, mode_iter, BFmode, NULL); + set_conv_libfunc (sext_optab, mode_iter, BFmode, NULL); + set_conv_libfunc (sext_optab, BFmode, mode_iter, NULL); + } + + FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT) + { + set_conv_libfunc (sfix_optab, BFmode, mode_iter, NULL); + set_conv_libfunc (sfix_optab, mode_iter, BFmode, NULL); + set_conv_libfunc (ufix_optab, BFmode, mode_iter, NULL); + set_conv_libfunc (ufix_optab, mode_iter, BFmode, NULL); + + set_conv_libfunc (sfloat_optab, mode_iter, BFmode, NULL); + set_conv_libfunc (sfloat_optab, BFmode, mode_iter, NULL); + set_conv_libfunc (ufloat_optab, mode_iter, BFmode, NULL); + set_conv_libfunc (ufloat_optab, BFmode, mode_iter, NULL); + } + + /* Enable libfuncs conversion for BFmode. */ + set_conv_libfunc (sext_optab, SFmode, BFmode, "__extendbfsf2"); + set_conv_libfunc (trunc_optab, BFmode, SFmode, "__truncsfbf2"); + set_conv_libfunc (trunc_optab, BFmode, DFmode, "__truncdfbf2"); + + set_conv_libfunc (sfloat_optab, BFmode, DImode, "__floatdibf"); + set_conv_libfunc (ufloat_optab, BFmode, DImode, "__floatundibf"); + + /* 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 e00b8ee3579..5048628c784 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -189,7 +189,7 @@ (define_attr "move_type" (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, RVVMF64BI,RVVMF32BI,RVVMF16BI,RVVMF8BI,RVVMF4BI,RVVMF2BI,RVVM1BI, RVVM8QI,RVVM4QI,RVVM2QI,RVVM1QI,RVVMF2QI,RVVMF4QI,RVVMF8QI, RVVM8HI,RVVM4HI,RVVM2HI,RVVM1HI,RVVMF2HI,RVVMF4HI, @@ -1631,6 +1631,20 @@ (define_insn "truncdfhf2" [(set_attr "type" "fcvt") (set_attr "mode" "HF")]) +;; The conversion of DF to BF needs to be done with SF if there is a +;; chance to generate at least one instruction, otherwise just using +;; libfunc __truncdfbf2. +(define_expand "truncdfbf2" + [(set (match_operand:BF 0 "register_operand" "=f") + (float_truncate:BF + (match_operand:DF 1 "register_operand" " f")))] + "TARGET_DOUBLE_FLOAT || TARGET_ZDINX" + { + convert_move (operands[0], + convert_modes (SFmode, DFmode, operands[1], 0), 0); + DONE; + }) + ;; ;; .................... ;; @@ -1784,12 +1798,12 @@ (define_insn "extendhfdf2" (set_attr "mode" "DF")]) ;; 16-bit floating point moves -(define_expand "movhf" - [(set (match_operand:HF 0 "") - (match_operand:HF 1 ""))] +(define_expand "mov" + [(set (match_operand:HFBF 0 "") + (match_operand:HFBF 1 ""))] "" { - if (riscv_legitimize_move (HFmode, operands[0], operands[1])) + if (riscv_legitimize_move (mode, operands[0], operands[1])) DONE; }) @@ -1804,16 +1818,16 @@ (define_insn "*movhf_hardfloat" (set_attr "type" "fmove") (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_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 == HFmode) || (mode == BFmode)) + && (register_operand (operands[0], mode) + || reg_or_0_operand (operands[1], mode))" { return riscv_output_move (operands[0], operands[1]); } [(set_attr "move_type" "fmove,move,load,store,mtc,mfc") (set_attr "type" "fmove") - (set_attr "mode" "HF")]) + (set_attr "mode" "")]) ;; ;; .................... @@ -1858,6 +1872,62 @@ (define_insn "floatuns2" [(set_attr "type" "fcvt") (set_attr "mode" "")]) +;; The conversion of BF to SI/DI needs to be done with SF. +(define_expand "fix_truncbf2" + [(set (match_operand:GPR 0 "register_operand" "=r") + (fix:GPR + (match_operand:BF 1 "register_operand" " f")))] + "" + { + rtx op1 = gen_reg_rtx (SFmode); + convert_move (op1, operands[1], 0); + expand_fix (operands[0], op1, 0); + DONE; + }) + +(define_expand "fixuns_truncbf2" + [(set (match_operand:GPR 0 "register_operand" "=r") + (unsigned_fix:GPR + (match_operand:BF 1 "register_operand" " f")))] + "" + { + rtx op1 = gen_reg_rtx (SFmode); + convert_move (op1, operands[1], 1); + expand_fix (operands[0], op1, 1); + DONE; + }) + +;; The conversion of SI to BF needs to be done with SF. +;; The conversion of DI to BF needs to be done with libfuncs +;; __floatdibf and __floatundibf directly if there is no F +;; extension, because we have not yet enabled __floatdisf +;; and __floatundisf. +(define_expand "floatbf2" + [(set (match_operand:BF 0 "register_operand" "= f") + (float:BF + (match_operand:GPR 1 "reg_or_0_operand" " rJ")))] + "(mode == SImode) + || (mode == DImode && (TARGET_HARD_FLOAT || TARGET_ZFINX))" + { + rtx op1 = gen_reg_rtx (SFmode); + expand_float (op1, operands[1], 0); + convert_move (operands[0], op1, 0); + DONE; + }) + +(define_expand "floatunsbf2" + [(set (match_operand:BF 0 "register_operand" "= f") + (unsigned_float:BF + (match_operand:GPR 1 "reg_or_0_operand" " rJ")))] + "(mode == SImode) + || (mode == DImode && (TARGET_HARD_FLOAT || TARGET_ZFINX))" + { + rtx op1 = gen_reg_rtx (SFmode); + expand_float (op1, operands[1], 1); + convert_move (operands[0], op1, 1); + DONE; + }) + (define_insn "l2" [(set (match_operand:GPR 0 "register_operand" "=r") (unspec:GPR 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..9e67b2babc0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bf16_arithmetic.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32imac -mabi=ilp32 -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64imac -mabi=lp64 -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; + +/* Arithmetic. */ +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.14; } + +void const_sub_bf () { bf = 3.14 - bf2; } + +void bf_mul_const () { bf = bf1 *3.14; } + +void const_div_bf () { bf = 3.14 / 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" 6 } } */ +/* { dg-final { scan-assembler-times "call\t__truncdfbf2" 4 } } */ +/* { 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..01576e38ac5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bf16_call.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32imac -mabi=ilp32 -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64imac -mabi=lp64 -O" { target { rv64 } } } */ + +_Bfloat16 add (_Bfloat16 a, _Bfloat16 b) __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_comparisons.c b/gcc/testsuite/gcc.target/riscv/bf16_comparisons.c new file mode 100644 index 00000000000..ff692378c00 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bf16_comparisons.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32imac -mabi=ilp32 -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64imac -mabi=lp64 -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; + +/* Comparisons. */ +void bf_lt_bf () { bf = (bf1 < bf2) ? bf1 : bf2; } + +void bf_gt_bf () { bf = (bf1 > bf2) ? bf1 : bf2; } + +void bf_eq_bf () { bf = (bf1 == bf2) ? bf1 : bf2; } + +void bf_lt_const () { bf = (bf1 < 3.14) ? bf1 : bf2; } + +void const_gt_bf () { bf = (3.14 > bf2) ? bf1 : bf2; } + +void bf_eq_const () { bf = (bf1 == 3.14) ? bf1 : bf2; } + +/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 9 } } */ +/* { dg-final { scan-assembler-not "call\t__ltbf2" } } */ +/* { dg-final { scan-assembler-not "call\t__gtbf2" } } */ +/* { dg-final { scan-assembler-not "call\t__eqbf2" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/bf16_convert-1.c b/gcc/testsuite/gcc.target/riscv/bf16_convert-1.c new file mode 100644 index 00000000000..3b9a7434373 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bf16_convert-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; +extern _Float16 hf; +extern float sf; +extern double df; + +extern int si; +extern long long di; + +extern unsigned int usi; +extern unsigned long long udi; + +/* Fp or gp Converts to bf. */ +void hf_to_bf () { bf = hf; } /* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 } } */ +void sf_to_bf () { bf = sf; } +void df_to_bf () { bf = df; } +void si_to_bf () { bf = si; } +void di_to_bf () { bf = di; } /* { dg-final { scan-assembler-times "call\t__floatdibf" 1 { target { rv32 } } } } */ +void usi_to_bf () { bf = usi; } +void udi_to_bf () { bf = udi; } /* { dg-final { scan-assembler-times "call\t__floatundibf" 1 { target { rv32 } } } } */ +void const_to_bf () { __volatile__ const float temp = 3.14; bf = temp; } +/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 5 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 7 { target { rv64 } } } } */ + +/* Bf converts to fp or gp. */ +void bf_to_hf () { hf = bf; } /* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 } } */ +void bf_to_sf () { sf = bf; } +void bf_to_df () { df = bf; } +void bf_to_si () { si = bf; } +void bf_to_di () { di = bf; } /* { dg-final { scan-assembler-times "call\t__fixsfdi" 1 { target { rv32 } } } } */ +void bf_to_usi () { usi = bf; } +void bf_to_udi () { udi = bf; } /* { dg-final { scan-assembler-times "call\t__fixunssfdi" 1 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 4 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 6 { target { rv64 } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/bf16_convert-2.c b/gcc/testsuite/gcc.target/riscv/bf16_convert-2.c new file mode 100644 index 00000000000..912b875bdd4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bf16_convert-2.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32imac -mabi=ilp32 -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64imac -mabi=lp64 -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; +extern _Float16 hf; +extern float sf; +extern double df; + +extern int si; +extern long long di; + +extern unsigned int usi; +extern unsigned long long udi; + +/* Fp or gp Converts to bf. */ +void hf_to_bf () { bf = hf; } /* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 } } */ +void sf_to_bf () { bf = sf; } +void df_to_bf () { bf = df; } /* { dg-final { scan-assembler-times "call\t__truncdfbf2" 1 } } */ +void si_to_bf () { bf = si; } /* { dg-final { scan-assembler-times "call\t__floatsisf" 1 } } */ +void di_to_bf () { bf = di; } /* { dg-final { scan-assembler-times "call\t__floatdibf" 1 } } */ +void usi_to_bf () { bf = usi; } /* { dg-final { scan-assembler-times "call\t__floatunsisf" 1 } } */ +void udi_to_bf () { bf = udi; } /* { dg-final { scan-assembler-times "call\t__floatundibf" 1 } } */ +void const_to_bf () { __volatile__ const float temp = 3.14; bf = temp; } +/* { dg-final { scan-assembler-times "call\t__truncsfbf2" 4 } } */ + +/* Bf converts to fp or gp. */ +void bf_to_hf () { hf = bf; } /* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 } } */ +void bf_to_sf () { sf = bf; } +void bf_to_df () { df = bf; } /* { dg-final { scan-assembler-times "call\t__extendsfdf2" 1 } } */ +void bf_to_si () { si = bf; } /* { dg-final { scan-assembler-times "call\t__fixsfsi" 1 } } */ +void bf_to_di () { di = bf; } /* { dg-final { scan-assembler-times "call\t__fixsfdi" 1 } } */ +void bf_to_usi () { usi = bf; } /* { dg-final { scan-assembler-times "call\t__fixunssfsi" 1 } } */ +void bf_to_udi () { udi = bf; } /* { dg-final { scan-assembler-times "call\t__fixunssfdi" 1 } } */ +/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 4 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "call\t__extendbfsf2" 6 { target { rv64 } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/bf16_convert_run.c b/gcc/testsuite/gcc.target/riscv/bf16_convert_run.c new file mode 100644 index 00000000000..d9b1f0f6298 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/bf16_convert_run.c @@ -0,0 +1,163 @@ +/* { dg-do run } */ +/* { dg-options "-march=rv32gc -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -O" { target { rv64 } } } */ + +#include + +#define NO_INLINE __attribute__((noinline)) + +int NO_INLINE +bf16_to_int () +{ + int ret[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + _Bfloat16 a_bf16 = 1.2; + _Bfloat16 b_bf16 = 7.1; + signed char a_char = 1; + short int a_short_int = 2; + int a_int = 3; + long a_long = 4; + long long a_long_long = 5; + + a_bf16 = (_Bfloat16)a_char; + if (a_bf16 != (_Bfloat16)1) + ret[0] = 1; + + a_bf16 = (_Bfloat16)a_short_int; + if (a_bf16 != (_Bfloat16)2) + ret[1] = 1; + + a_bf16 = (_Bfloat16)a_int; + if (a_bf16 != (_Bfloat16)3) + ret[2] = 1; + + a_bf16 = (_Bfloat16)a_long; + if (a_bf16 != (_Bfloat16)4) + ret[3] = 1; + + a_bf16 = (_Bfloat16)a_long_long; + if (a_bf16 != (_Bfloat16)5) + ret[4] = 1; + + a_char = (signed char)b_bf16; + if (a_char != (signed char)7.1) + ret[5] = 1; + + a_short_int = (short int)b_bf16; + if (a_short_int != (short int)7.1) + ret[6] = 1; + + a_int = (int)b_bf16; + if (a_int != (int)7.1) + ret[7] = 1; + + a_long = (long)b_bf16; + if (a_long != (long)7.1) + ret[8] = 1; + + a_long_long = (long long)b_bf16; + if (a_long_long != (long long)7.1) + ret[9] = 1; + + if ((ret[0] == 1) || (ret[1] == 1) || (ret[2] == 1) || (ret[3] == 1) || (ret[4] == 1) || + (ret[5] == 1) || (ret[6] == 1) || (ret[7] == 1) || (ret[8] == 1) || (ret[9] == 1)) + return 1; + else + return 0; +} + +int NO_INLINE +bf16_to_uint () +{ + int ret[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + _Bfloat16 a_bf16 = 1.2; + _Bfloat16 b_bf16 = 7.1; + unsigned char a_uchar = 1; + unsigned short int a_short_uint = 2; + unsigned int a_uint = 3; + unsigned long a_ulong = 4; + unsigned long long a_ulong_ulong = 5; + + a_bf16 = (_Bfloat16)a_uchar; + if (a_bf16 != (_Bfloat16)1) + ret[0] = 1; + + a_bf16 = (_Bfloat16)a_short_uint; + if (a_bf16 != (_Bfloat16)2) + ret[1] = 1; + + a_bf16 = (_Bfloat16)a_uint; + if (a_bf16 != (_Bfloat16)3) + ret[2] = 1; + + a_bf16 = (_Bfloat16)a_ulong; + if (a_bf16 != (_Bfloat16)4) + ret[3] = 1; + + a_bf16 = (_Bfloat16)a_ulong_ulong; + if (a_bf16 != (_Bfloat16)5) + ret[4] = 1; + + a_uchar = (unsigned char)b_bf16; + if (a_uchar != (unsigned char)7.1) + ret[5] = 1; + + a_short_uint = (unsigned short int)b_bf16; + if (a_short_uint != (unsigned short int)7.1) + ret[6] = 1; + + a_uint = (unsigned int)b_bf16; + if (a_uint != (unsigned int)7.1) + ret[7] = 1; + + a_ulong = (unsigned long)b_bf16; + if (a_ulong != (unsigned long)7.1) + ret[8] = 1; + + a_ulong_ulong = (unsigned long long)b_bf16; + if (a_ulong_ulong != (unsigned long long)7.1) + ret[9] = 1; + + if ((ret[0] == 1) || (ret[1] == 1) || (ret[2] == 1) || (ret[3] == 1) || (ret[4] == 1) || + (ret[5] == 1) || (ret[6] == 1) || (ret[7] == 1) || (ret[8] == 1) || (ret[9] == 1)) + return 1; + else + return 0; +} + +int NO_INLINE +bf16_to_float () +{ + int ret[4] = {0, 0, 0, 0}; + _Bfloat16 a_bf16 = 1.2; + _Bfloat16 b_bf16 = 7.5; + float a_float = 3.7; + double a_double = 5.8; + a_bf16 = (_Bfloat16)a_float; + if (a_bf16 != ((_Bfloat16)3.7)) + ret[0] = 1; + + a_bf16 = (_Bfloat16)a_double; + if (a_bf16 != ((_Bfloat16)5.8)) + ret[1] = 1; + + a_float = (float)b_bf16; + if (a_float != (float)7.5) + ret[2] = 1; + + a_double = (double)b_bf16; + if (a_double != (double)7.5) + ret[3] = 1; + + if ((ret[0] == 1) || (ret[1] == 1) || (ret[2] == 1) || (ret[3] == 1)) + return 1; + else + return 0; +} + +int main() +{ + if (bf16_to_int () || bf16_to_uint () || bf16_to_float ()) + return 1; + else + return 0; +} diff --git a/libgcc/config/riscv/sfp-machine.h b/libgcc/config/riscv/sfp-machine.h index 38e2817bffa..6e294b38783 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..0c61f77714b 100644 --- a/libgcc/config/riscv/t-softfp32 +++ b/libgcc/config/riscv/t-softfp32 @@ -42,7 +42,8 @@ softfp_extras += divsf3 divdf3 divtf3 endif -softfp_extensions += hfsf hfdf hftf -softfp_truncations += tfhf dfhf sfhf +softfp_extensions += hfsf hfdf hftf bfsf +softfp_truncations += tfhf dfhf sfhf tfbf dfbf sfbf bfhf hfbf softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \ - floatsihf floatdihf floatunsihf floatundihf + floatsihf floatdihf floatunsihf floatundihf \ + floatdibf floatundibf From patchwork Tue Sep 19 08:46:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jin Ma X-Patchwork-Id: 141743 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:172:b0:3f2:4152:657d with SMTP id h50csp3226034vqi; Tue, 19 Sep 2023 01:47:19 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG/bugAhreezNo0ic/mJ3ifbigGpqFehyfHln0ygsK++sxyBJ9aK7TDJvu2yNiFiXpo49PW X-Received: by 2002:a17:907:a05c:b0:9ae:3c2f:5a99 with SMTP id gz28-20020a170907a05c00b009ae3c2f5a99mr91885ejc.51.1695113239608; Tue, 19 Sep 2023 01:47:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1695113239; cv=none; d=google.com; s=arc-20160816; b=Rk+uiYxQpawQH8QtRSNRr/ukdbr5Qvv11JkK0JVQUcnykFkFV7EAEn7qLJdU9ZkGW/ qJ9cJlNkuIxTM/eARmf6YoarMI0RFa6JFQ3sEkTBYrEekkMlZihSH0KIjfLMp6l/9RxX ZEWGYJGV+ldnVvjlFcRFZ4E2NI1FEoo/on1vjyuf82rYJ0xaDjfx9EtW0HODWhx4Z+3d QdA2T0WFRVjKrHqjjateXEs+0/iYBahx6JQVQ6gDQ3AVubGFcOmVIWeroUtmXYZzjspI iJW8mpczN1ycg265T2orMxv+dzZ8Y55Skscpx7CxVx7XLXh4tmUsT5yoqUHkh8BVaEPq FDmA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dmarc-filter:delivered-to; bh=YWRYIChVbX3GAnihAvKih8baCmqderf/nilh3l/Qkug=; fh=PNKHkBOXPoSDTszGHOh5AIQxdUaUJea5dXvcOFWiGwk=; b=pEw2G6zwx6TckjIofbOy5D4sbL+jO9JpiB4SMpHVDdR2mx6rslWPArT7OUy5mGY/DI 1RJ9XN2HFCg+Ofq5vPbZHSHuS+1tAOP0RH6UGklbX26VeY5TaRSx+8U17MmY3L16voDe S+ZCGGbS53cvk5v8xtnJDiE9nnfK6aUwfe3zrAaooz3c9TUniH7L/SSMo3ygN+U9tPs4 k/fK6gds39TF7zYhCft09eXUoAolX0DFvTq7Ca2CpkNdytWGtgo0c3uRSqXRPVpOPFkI 8PdnxJoFe/8CnrqtWA712Ao2htZrGbNISvmIG7Ge2dB3+gIfBpAl8uHRrnfyx+3YSuXP fCGw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id jw16-20020a17090776b000b009a210885fadsi9341083ejc.24.2023.09.19.01.47.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Sep 2023 01:47:19 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 867A7385701D for ; Tue, 19 Sep 2023 08:47:14 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out30-132.freemail.mail.aliyun.com (out30-132.freemail.mail.aliyun.com [115.124.30.132]) by sourceware.org (Postfix) with ESMTPS id C9CC43858D32 for ; Tue, 19 Sep 2023 08:46:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C9CC43858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linux.alibaba.com X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R811e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=ay29a033018046059; MF=jinma@linux.alibaba.com; NM=1; PH=DS; RN=11; SR=0; TI=SMTPD_---0VsQpctg_1695113194; Received: from localhost.localdomain(mailfrom:jinma@linux.alibaba.com fp:SMTPD_---0VsQpctg_1695113194) by smtp.aliyun-inc.com; Tue, 19 Sep 2023 16:46:35 +0800 From: Jin Ma To: gcc-patches@gcc.gnu.org Cc: jeffreyalaw@gmail.com, palmer@dabbelt.com, richard.sandiford@arm.com, kito.cheng@gmail.com, philipp.tomsich@vrull.eu, christoph.muellner@vrull.eu, rdapp.gcc@gmail.com, juzhe.zhong@rivai.ai, jinma.contrib@gmail.com, Jin Ma Subject: [RFC 2/2] RISC-V: Add 'Zfbfmin' extension. Date: Tue, 19 Sep 2023 16:46:25 +0800 Message-Id: <20230919084625.2183-1-jinma@linux.alibaba.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20230919084444.2089-1-jinma@linux.alibaba.com> References: <20230919084444.2089-1-jinma@linux.alibaba.com> MIME-Version: 1.0 X-Spam-Status: No, score=-19.4 required=5.0 tests=BAYES_00, ENV_AND_HDR_SPF_MATCH, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, UNPARSEABLE_RELAY, URIBL_BLACK, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1777455060487953282 X-GMAIL-MSGID: 1777455060487953282 This patch adds the 'Zfbfmin' extension for riscv, which is based on spec of bfloat16: https://github.com/riscv/riscv-bfloat16/commit/5578e34e15a44e9ad13246072a29f51274b4d999 The 'Zfbfmin' extension of binutils-gdb (REVIEW ONLY): https://sourceware.org/pipermail/binutils/2023-August/128773.html The 'Zfbfmin' extension of qemu: https://github.com/qemu/qemu/commit/5d1270caac2ef7b8c887d4cb5a2444ba6d237516 Because the binutils does not yet support the 'Zfbfmin' extension, test case zfbfmin_convert_run.c is invalidated with '#if 0' and '#endif'. gcc/ChangeLog: * common/config/riscv/riscv-common.cc: Add 'Zfbfmin' extension. * config/riscv/riscv-opts.h (MASK_ZFBFMIN): New. (TARGET_ZFBFMIN): New. * config/riscv/riscv.cc (riscv_output_move): Enable FMV.X.H, and FMV.H.X for 'Zfbfmin' extension. (riscv_excess_precision): Likewise. * config/riscv/riscv.md (truncsfbf2): New. (extendbfsf2): New. (*mov_hardfloat): Support for BFmode. (*mov_softfloat): Disable for BFmode when 'Zfbfmin' extension is enabled. gcc/testsuite/ChangeLog: * gcc.target/riscv/zfbfmin_arithmetic.c: New test. * gcc.target/riscv/zfbfmin_call.c: New test. * gcc.target/riscv/zfbfmin_comparisons.c: New test. * gcc.target/riscv/zfbfmin_convert.c: New test. * gcc.target/riscv/zfbfmin_convert_run.c: New test. * gcc.target/riscv/zfbfmin_fsh_and_flh.c: New test. --- gcc/common/config/riscv/riscv-common.cc | 3 + gcc/config/riscv/riscv-opts.h | 2 + gcc/config/riscv/riscv.cc | 4 +- gcc/config/riscv/riscv.md | 40 ++-- .../gcc.target/riscv/zfbfmin_arithmetic.c | 31 ++++ gcc/testsuite/gcc.target/riscv/zfbfmin_call.c | 17 ++ .../gcc.target/riscv/zfbfmin_comparisons.c | 22 +++ .../gcc.target/riscv/zfbfmin_convert.c | 38 ++++ .../gcc.target/riscv/zfbfmin_convert_run.c | 173 ++++++++++++++++++ .../gcc.target/riscv/zfbfmin_fsh_and_flh.c | 12 ++ 10 files changed, 329 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/zfbfmin_arithmetic.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfbfmin_call.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfbfmin_comparisons.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfbfmin_convert.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfbfmin_convert_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfbfmin_fsh_and_flh.c diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 9a0a68fe5db..1fcbb862aa4 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -123,6 +123,7 @@ static const riscv_implied_info_t riscv_implied_info[] = {"zfh", "zfhmin"}, {"zfhmin", "f"}, + {"zfbfmin", "f"}, {"zfa", "f"}, @@ -284,6 +285,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] = {"zfhmin", ISA_SPEC_CLASS_NONE, 1, 0}, {"zvfhmin", ISA_SPEC_CLASS_NONE, 1, 0}, {"zvfh", ISA_SPEC_CLASS_NONE, 1, 0}, + {"zfbfmin", ISA_SPEC_CLASS_NONE, 0, 8}, {"zfa", ISA_SPEC_CLASS_NONE, 0, 1}, @@ -1461,6 +1463,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = {"zfh", &gcc_options::x_riscv_zf_subext, MASK_ZFH}, {"zvfhmin", &gcc_options::x_riscv_zf_subext, MASK_ZVFHMIN}, {"zvfh", &gcc_options::x_riscv_zf_subext, MASK_ZVFH}, + {"zfbfmin", &gcc_options::x_riscv_zf_subext, MASK_ZFBFMIN}, {"zfa", &gcc_options::x_riscv_zfa_subext, MASK_ZFA}, diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index a525f679683..900a46fcae0 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -256,11 +256,13 @@ enum riscv_entity #define MASK_ZFH (1 << 1) #define MASK_ZVFHMIN (1 << 2) #define MASK_ZVFH (1 << 3) +#define MASK_ZFBFMIN (1 << 4) #define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0) #define TARGET_ZFH ((riscv_zf_subext & MASK_ZFH) != 0) #define TARGET_ZVFHMIN ((riscv_zf_subext & MASK_ZVFHMIN) != 0) #define TARGET_ZVFH ((riscv_zf_subext & MASK_ZVFH) != 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.cc b/gcc/config/riscv/riscv.cc index 910523ee2b9..6362c3f83c8 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3372,7 +3372,7 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: - if (TARGET_ZFHMIN) + if (TARGET_ZFHMIN || TARGET_ZFBFMIN) return "fmv.x.h\t%0,%1"; /* Using fmv.x.s + sign-extend to emulate fmv.x.h. */ return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16"; @@ -3428,7 +3428,7 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: - if (TARGET_ZFHMIN) + if (TARGET_ZFHMIN || TARGET_ZFBFMIN) return "fmv.h.x\t%0,%z1"; /* High 16 bits should be all-1, otherwise HW will treated as a n-bit canonical NaN, but isn't matter for softfloat. */ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 5048628c784..ef0c38cb633 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1631,14 +1631,23 @@ (define_insn "truncdfhf2" [(set_attr "type" "fcvt") (set_attr "mode" "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")]) + ;; The conversion of DF to BF needs to be done with SF if there is a -;; chance to generate at least one instruction, otherwise just using -;; libfunc __truncdfbf2. +;; chance to generate at least one instruction, whether it is 'fcvt.s.d' +;; or 'fcvt.bf16.s'. Otherwise just using libfunc __truncdfbf2. (define_expand "truncdfbf2" [(set (match_operand:BF 0 "register_operand" "=f") (float_truncate:BF (match_operand:DF 1 "register_operand" " f")))] - "TARGET_DOUBLE_FLOAT || TARGET_ZDINX" + "TARGET_DOUBLE_FLOAT || TARGET_ZDINX || TARGET_ZFBFMIN" { convert_move (operands[0], convert_modes (SFmode, DFmode, operands[1], 0), 0); @@ -1797,6 +1806,15 @@ (define_insn "extendhfdf2" [(set_attr "type" "fcvt") (set_attr "mode" "DF")]) +(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")]) + ;; 16-bit floating point moves (define_expand "mov" [(set (match_operand:HFBF 0 "") @@ -1807,21 +1825,21 @@ (define_expand "mov" DONE; }) -(define_insn "*movhf_hardfloat" - [(set (match_operand:HF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m") - (match_operand:HF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))] - "TARGET_ZFHMIN - && (register_operand (operands[0], HFmode) - || reg_or_0_operand (operands[1], HFmode))" +(define_insn "*mov_hardfloat" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m") + (match_operand:HFBF 1 "move_operand" " f,zfli,G,m,f,G,*r,*f,*G*r,*m,*r"))] + "((TARGET_ZFHMIN && mode == HFmode) || (TARGET_ZFBFMIN && mode == BFmode)) + && (register_operand (operands[0], mode) + || reg_or_0_operand (operands[1], mode))" { return riscv_output_move (operands[0], operands[1]); } [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") (set_attr "type" "fmove") - (set_attr "mode" "HF")]) + (set_attr "mode" "")]) (define_insn "*mov_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 == HFmode) || (mode == BFmode)) + "!((TARGET_ZFHMIN && mode == HFmode) || (TARGET_ZFBFMIN && mode == BFmode)) && (register_operand (operands[0], mode) || reg_or_0_operand (operands[1], mode))" { return riscv_output_move (operands[0], operands[1]); } diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin_arithmetic.c b/gcc/testsuite/gcc.target/riscv/zfbfmin_arithmetic.c new file mode 100644 index 00000000000..529e9b40daa --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin_arithmetic.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zfbfmin -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zfbfmin -mabi=lp64d -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; + +/* Arithmetic. */ +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.14; } + +void const_sub_bf () { bf = 3.14 - bf2; } + +void bf_mul_const () { bf = bf1 *3.14; } + +void const_div_bf () { bf = 3.14 / bf2; } + +void bf_inc () { ++bf; } + +void bf_dec () { --bf; } + +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 14 } } */ +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 10 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin_call.c b/gcc/testsuite/gcc.target/riscv/zfbfmin_call.c new file mode 100644 index 00000000000..6cda430020e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin_call.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zfbfmin -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zfbfmin -mabi=lp64d -O" { target { rv64 } } } */ + +_Bfloat16 add (_Bfloat16 a, _Bfloat16 b) __attribute__ ((noinline)); +_Bfloat16 add (_Bfloat16 a, _Bfloat16 b) +{ + return a + b; +} + +_Bfloat16 foo(_Bfloat16 a, _Bfloat16 b) +{ + return add (a, b); +} + +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 2 } } */ +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin_comparisons.c b/gcc/testsuite/gcc.target/riscv/zfbfmin_comparisons.c new file mode 100644 index 00000000000..3dd2874a8bd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin_comparisons.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zfbfmin -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zfbfmin -mabi=lp64d -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; + +/* Comparisons. */ +void bf_lt_bf () { bf = (bf1 < bf2) ? bf1 : bf2; } + +void bf_gt_bf () { bf = (bf1 > bf2) ? bf1 : bf2; } + +void bf_eq_bf () { bf = (bf1 == bf2) ? bf1 : bf2; } + +void bf_lt_const () { bf = (bf1 < 3.14) ? bf1 : bf2; } + +void const_gt_bf () { bf = (3.14 > bf2) ? bf1 : bf2; } + +void bf_eq_const () { bf = (bf1 == 3.14) ? bf1 : bf2; } + +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 9 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin_convert.c b/gcc/testsuite/gcc.target/riscv/zfbfmin_convert.c new file mode 100644 index 00000000000..b9b2a1ca6b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin_convert.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zfbfmin -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zfbfmin -mabi=lp64d -O" { target { rv64 } } } */ + +extern _Bfloat16 bf; +extern _Bfloat16 bf1; +extern _Bfloat16 bf2; +extern _Float16 hf; +extern float sf; +extern double df; + +extern int si; +extern long long di; + +extern unsigned int usi; +extern unsigned long long udi; + +/* Fp or gp Converts to bf. */ +void hf_to_bf () { bf = hf; } /* { dg-final { scan-assembler-times "call\t__trunchfbf2" 1 } } */ +void sf_to_bf () { bf = sf; } +void df_to_bf () { bf = df; } +void si_to_bf () { bf = si; } +void di_to_bf () { bf = di; } /* { dg-final { scan-assembler-times "call\t__floatdibf" 1 { target { rv32 } } } } */ +void usi_to_bf () { bf = usi; } +void udi_to_bf () { bf = udi; } /* { dg-final { scan-assembler-times "call\t__floatundibf" 1 { target { rv32 } } } } */ +void const_to_bf () { __volatile__ const float temp = 3.14; bf = temp; } +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 5 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "fcvt.bf16.s" 7 { target { rv64 } } } } */ + +/* Bf converts to fp or gp. */ +void bf_to_hf () { hf = bf; } /* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 } } */ +void bf_to_sf () { sf = bf; } +void bf_to_df () { df = bf; } +void bf_to_si () { si = bf; } +void bf_to_di () { di = bf; } +void bf_to_usi () { usi = bf; } +void bf_to_udi () { udi = bf; } +/* { dg-final { scan-assembler-times "fcvt.s.bf16" 7 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin_convert_run.c b/gcc/testsuite/gcc.target/riscv/zfbfmin_convert_run.c new file mode 100644 index 00000000000..e97c71b8595 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin_convert_run.c @@ -0,0 +1,173 @@ +/* { dg-do run } */ +/* { dg-options "-march=rv32gc_zfbfmin -mabi=ilp32d -O" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zfbfmin -mabi=lp64d -O" { target { rv64 } } } */ + +/* Need to wait for binutils and qemu or other emulators or hardware to support + zfbfmin extensions. */ +#if 0 +#include + +#define NO_INLINE __attribute__((noinline)) + +int NO_INLINE +bf16_to_int () +{ + int ret[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + _Bfloat16 a_bf16 = 1.2; + _Bfloat16 b_bf16 = 7.1; + signed char a_char = 1; + short int a_short_int = 2; + int a_int = 3; + long a_long = 4; + long long a_long_long = 5; + + a_bf16 = (_Bfloat16)a_char; + if (a_bf16 != (_Bfloat16)1) + ret[0] = 1; + + a_bf16 = (_Bfloat16)a_short_int; + if (a_bf16 != (_Bfloat16)2) + ret[1] = 1; + + a_bf16 = (_Bfloat16)a_int; + if (a_bf16 != (_Bfloat16)3) + ret[2] = 1; + + a_bf16 = (_Bfloat16)a_long; + if (a_bf16 != (_Bfloat16)4) + ret[3] = 1; + + a_bf16 = (_Bfloat16)a_long_long; + if (a_bf16 != (_Bfloat16)5) + ret[4] = 1; + + a_char = (signed char)b_bf16; + if (a_char != (signed char)7.1) + ret[5] = 1; + + a_short_int = (short int)b_bf16; + if (a_short_int != (short int)7.1) + ret[6] = 1; + + a_int = (int)b_bf16; + if (a_int != (int)7.1) + ret[7] = 1; + + a_long = (long)b_bf16; + if (a_long != (long)7.1) + ret[8] = 1; + + a_long_long = (long long)b_bf16; + if (a_long_long != (long long)7.1) + ret[9] = 1; + + if ((ret[0] == 1) || (ret[1] == 1) || (ret[2] == 1) || (ret[3] == 1) || (ret[4] == 1) || + (ret[5] == 1) || (ret[6] == 1) || (ret[7] == 1) || (ret[8] == 1) || (ret[9] == 1)) + return 1; + else + return 0; +} + +int NO_INLINE +bf16_to_uint () +{ + int ret[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + _Bfloat16 a_bf16 = 1.2; + _Bfloat16 b_bf16 = 7.1; + unsigned char a_uchar = 1; + unsigned short int a_short_uint = 2; + unsigned int a_uint = 3; + unsigned long a_ulong = 4; + unsigned long long a_ulong_ulong = 5; + + a_bf16 = (_Bfloat16)a_uchar; + if (a_bf16 != (_Bfloat16)1) + ret[0] = 1; + + a_bf16 = (_Bfloat16)a_short_uint; + if (a_bf16 != (_Bfloat16)2) + ret[1] = 1; + + a_bf16 = (_Bfloat16)a_uint; + if (a_bf16 != (_Bfloat16)3) + ret[2] = 1; + + a_bf16 = (_Bfloat16)a_ulong; + if (a_bf16 != (_Bfloat16)4) + ret[3] = 1; + + a_bf16 = (_Bfloat16)a_ulong_ulong; + if (a_bf16 != (_Bfloat16)5) + ret[4] = 1; + + a_uchar = (unsigned char)b_bf16; + if (a_uchar != (unsigned char)7.1) + ret[5] = 1; + + a_short_uint = (unsigned short int)b_bf16; + if (a_short_uint != (unsigned short int)7.1) + ret[6] = 1; + + a_uint = (unsigned int)b_bf16; + if (a_uint != (unsigned int)7.1) + ret[7] = 1; + + a_ulong = (unsigned long)b_bf16; + if (a_ulong != (unsigned long)7.1) + ret[8] = 1; + + a_ulong_ulong = (unsigned long long)b_bf16; + if (a_ulong_ulong != (unsigned long long)7.1) + ret[9] = 1; + + if ((ret[0] == 1) || (ret[1] == 1) || (ret[2] == 1) || (ret[3] == 1) || (ret[4] == 1) || + (ret[5] == 1) || (ret[6] == 1) || (ret[7] == 1) || (ret[8] == 1) || (ret[9] == 1)) + return 1; + else + return 0; +} + +int NO_INLINE +bf16_to_float () +{ + int ret[4] = {0, 0, 0, 0}; + _Bfloat16 a_bf16 = 1.2; + _Bfloat16 b_bf16 = 7.5; + float a_float = 3.7; + double a_double = 5.8; + a_bf16 = (_Bfloat16)a_float; + if (a_bf16 != ((_Bfloat16)3.7)) + ret[0] = 1; + + a_bf16 = (_Bfloat16)a_double; + if (a_bf16 != ((_Bfloat16)5.8)) + ret[1] = 1; + + a_float = (float)b_bf16; + if (a_float != (float)7.5) + ret[2] = 1; + + a_double = (double)b_bf16; + if (a_double != (double)7.5) + ret[3] = 1; + + if ((ret[0] == 1) || (ret[1] == 1) || (ret[2] == 1) || (ret[3] == 1)) + return 1; + else + return 0; +} + +int main() +{ + if (bf16_to_int () || bf16_to_uint () || bf16_to_float ()) + return 1; + else + return 0; +} +#else +int main() +{ + return 0; +} +#endif + diff --git a/gcc/testsuite/gcc.target/riscv/zfbfmin_fsh_and_flh.c b/gcc/testsuite/gcc.target/riscv/zfbfmin_fsh_and_flh.c new file mode 100644 index 00000000000..0255f27f3ba --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfbfmin_fsh_and_flh.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc_zfbfmin -mabi=ilp32d -O2" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc_zfbfmin -mabi=lp64d -O2" { target { rv64 } } } */ + +void +foo (int a, _Bfloat16 *b) +{ + *b += a; +} + +/* { dg-final { scan-assembler-times "fsh\t" 1 } } */ +/* { dg-final { scan-assembler-times "flh\t" 1 } } */