From patchwork Thu Jul 7 08:52:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kito Cheng X-Patchwork-Id: 55815 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 29A45385624C for ; Thu, 7 Jul 2022 08:53:01 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by sourceware.org (Postfix) with ESMTPS id A7C753857B92 for ; Thu, 7 Jul 2022 08:52:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org A7C753857B92 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pg1-x52c.google.com with SMTP id e132so17272190pgc.5 for ; Thu, 07 Jul 2022 01:52:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g1uT42hUKRo+UlwNNAvPYviuvc2VAjWADo34jaXIqgI=; b=D7P/WUNAPuWEV0mWaiaiY10DLcTSuW3dincojKdQydmjvJCV6X9xbSS75/+woy7Fti 9Bc281s4KADfpKxVDLZKzeIbp72Dn72JjYeMlY2cdyv+xYjQH2G/FyeF8tjWpOH+44/h IFikgEZ6+EmHe4fqj/qqnpcXnNQlOjpZOMil2DyOcKTjnKQrm86SCBGOOdFQUT1Qe6Nm kvBJeytrhv/z2V/Q3sZ7gcLU8Sx7IraGbAefGz39q2CYTozFzsvb4MSVo5C2gVQQD40h iAVEXYCsLveLkgKfi8YNVfcbqFQBYCntzmTrSdsng+pcsJAOAiqnI8e62/8AN4Yb6QRk fB7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g1uT42hUKRo+UlwNNAvPYviuvc2VAjWADo34jaXIqgI=; b=Xlgi0Skl+3MFxhb83Q+GnPu7NrUVsCPNVLrW3SlFtdBHR+G+/+Nzql2Oa3IOMktsgw MSUTn7tXkSyS9SQjRxOUvH2FN34YIgl7R86YH1qfLTYm9T89Uowj74INVl/7g4wdd5aU kflDjEeF4M8HglxM5Dptng6JW1le1TzdkYa5zu2rnAgFAHDGZbZ99k/ZngF7CblBl99G H5qtkNxq39gsABBqCy4wV0GYuAA9UoCf8Ev8pWqrVdTLUcQMDHaHGwmljR0ALKujhUze RTedWOH2w/D/u9nU7sd0LXD5+8TPLi12Bv/XWT3jpDJalUIsePMvLhhoj3YKmDq18Ly0 ajIg== X-Gm-Message-State: AJIora9gx91o5mdJGD9NCdeXP6hwk77o9J4U7hfj5+z+Ou8TFAUJRDTG l4mn5kZL32qyRY/4wSeqwUBADeKkqE7rEg== X-Google-Smtp-Source: AGRyM1tpmmliu1Ws9NsHl5CSGK5MRpuupGjj+vfDQmMcbJhKTnFPYKMjFbGMTNq5zDkkO1BV59WPRg== X-Received: by 2002:a17:902:da91:b0:16a:4760:a4c1 with SMTP id j17-20020a170902da9100b0016a4760a4c1mr52072935plx.75.1657183958352; Thu, 07 Jul 2022 01:52:38 -0700 (PDT) Received: from hsinchu02.internal.sifive.com (59-124-168-89.hinet-ip.hinet.net. [59.124.168.89]) by smtp.gmail.com with ESMTPSA id l6-20020a170903120600b0016a0bf0ce32sm18224665plh.70.2022.07.07.01.52.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Jul 2022 01:52:38 -0700 (PDT) From: Kito Cheng To: gcc-patches@gcc.gnu.org, kito.cheng@gmail.com, jim.wilson.gcc@gmail.com, palmer@dabbelt.com, andrew@sifive.com, juzhe.zhong@rivai.ai Subject: [PATCH 1/2] RISC-V: Support _Float16 type. Date: Thu, 7 Jul 2022 16:52:30 +0800 Message-Id: <20220707085231.68930-2-kito.cheng@sifive.com> X-Mailer: git-send-email 2.34.0 In-Reply-To: <20220707085231.68930-1-kito.cheng@sifive.com> References: <20220707085231.68930-1-kito.cheng@sifive.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URIBL_BLACK 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kito Cheng Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" RISC-V decide use _Float16 as primary IEEE half precision type, and this already become part of psABI, this patch has added folloing support for _Float16: - Soft-float support for _Float16. - Make sure _Float16 available on C++ mode. - Name mangling for _Float16 on C++ mode. gcc/ChangeLog * config/riscv/riscv-builtins.cc: include stringpool.h (riscv_float16_type_node): New. (riscv_init_builtin_types): Ditto. (riscv_init_builtins): Call riscv_init_builtin_types. * config/riscv/riscv-modes.def (HF): New. * gcc/config/riscv/riscv.cc (riscv_output_move): Handle HFmode. (riscv_mangle_type): New. (riscv_scalar_mode_supported_p): Ditto. (riscv_libgcc_floating_mode_supported_p): Ditto. (riscv_excess_precision): Ditto. (riscv_floatn_mode): Ditto. (riscv_init_libfuncs): Ditto. (TARGET_MANGLE_TYPE): Ditto. (TARGET_SCALAR_MODE_SUPPORTED_P): Ditto. (TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Ditto. (TARGET_INIT_LIBFUNCS): Ditto. (TARGET_C_EXCESS_PRECISION): Ditto. (TARGET_FLOATN_MODE): Ditto. * gcc/config/riscv/riscv.md (mode): Add HF. (softload): Add HF. (softstore): Ditto. (fmt): Ditto. (UNITMODE): Ditto. (movhf): New. (*movhf_softfloat): New. libgcc/ChangeLog: * config/riscv/sfp-machine.h (_FP_NANFRAC_H): New. (_FP_NANFRAC_H): Ditto. (_FP_NANSIGN_H): Ditto. * config/riscv/t-softfp32 (softfp_extensions): Add HF related routines. (softfp_truncations): Ditto. (softfp_extras): Ditto. * config/riscv/t-softfp64 (softfp_extras): Add HF related routines. gcc/testsuite/ChangeLog: * gcc/testsuite/g++.target/riscv/_Float16.C: New. * gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c: Ditto. * gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c: Ditto. * gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c: Ditto. * gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c: Ditto. * gcc/testsuite/gcc.target/riscv/_Float16.c: Ditto. --- gcc/config/riscv/riscv-builtins.cc | 24 +++ gcc/config/riscv/riscv-modes.def | 1 + gcc/config/riscv/riscv.cc | 171 ++++++++++++++++-- gcc/config/riscv/riscv.md | 30 ++- gcc/testsuite/g++.target/riscv/_Float16.C | 18 ++ .../gcc.target/riscv/_Float16-soft-1.c | 9 + .../gcc.target/riscv/_Float16-soft-2.c | 13 ++ .../gcc.target/riscv/_Float16-soft-3.c | 12 ++ .../gcc.target/riscv/_Float16-soft-4.c | 12 ++ gcc/testsuite/gcc.target/riscv/_Float16.c | 19 ++ libgcc/config/riscv/sfp-machine.h | 3 + libgcc/config/riscv/t-softfp32 | 5 + libgcc/config/riscv/t-softfp64 | 1 + 13 files changed, 300 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.target/riscv/_Float16.C create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16.c diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc index 1218fdfc67d..3009311604d 100644 --- a/gcc/config/riscv/riscv-builtins.cc +++ b/gcc/config/riscv/riscv-builtins.cc @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "recog.h" #include "diagnostic-core.h" #include "stor-layout.h" +#include "stringpool.h" #include "expr.h" #include "langhooks.h" @@ -160,6 +161,8 @@ static GTY(()) int riscv_builtin_decl_index[NUM_INSN_CODES]; #define GET_BUILTIN_DECL(CODE) \ riscv_builtin_decls[riscv_builtin_decl_index[(CODE)]] +tree riscv_float16_type_node = NULL_TREE; + /* Return the function type associated with function prototype TYPE. */ static tree @@ -185,11 +188,32 @@ riscv_build_function_type (enum riscv_function_type type) return types[(int) type]; } +static void +riscv_init_builtin_types (void) +{ + /* Provide the _Float16 type and float16_type_node if needed. */ + if (!float16_type_node) + { + riscv_float16_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (riscv_float16_type_node) = 16; + SET_TYPE_MODE (riscv_float16_type_node, HFmode); + layout_type (riscv_float16_type_node); + } + else + riscv_float16_type_node = float16_type_node; + + if (!maybe_get_identifier ("_Float16")) + lang_hooks.types.register_builtin_type (riscv_float16_type_node, + "_Float16"); +} + /* Implement TARGET_INIT_BUILTINS. */ void riscv_init_builtins (void) { + riscv_init_builtin_types (); + for (size_t i = 0; i < ARRAY_SIZE (riscv_builtins); i++) { const struct riscv_builtin_description *d = &riscv_builtins[i]; diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def index 653228409a4..5cf2fc8e9e6 100644 --- a/gcc/config/riscv/riscv-modes.def +++ b/gcc/config/riscv/riscv-modes.def @@ -19,4 +19,5 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ +FLOAT_MODE (HF, 2, ieee_half_format); FLOAT_MODE (TF, 16, ieee_quad_format); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 2e83ca07394..491e1aaf8c0 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -2269,11 +2269,13 @@ riscv_output_move (rtx dest, rtx src) enum rtx_code dest_code, src_code; machine_mode mode; bool dbl_p; + unsigned width; dest_code = GET_CODE (dest); src_code = GET_CODE (src); mode = GET_MODE (dest); dbl_p = (GET_MODE_SIZE (mode) == 8); + width = GET_MODE_SIZE (mode); if (dbl_p && riscv_split_64bit_move_p (dest, src)) return "#"; @@ -2281,10 +2283,19 @@ riscv_output_move (rtx dest, rtx src) if (dest_code == REG && GP_REG_P (REGNO (dest))) { if (src_code == REG && FP_REG_P (REGNO (src))) - return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.w\t%0,%1"; + switch (width) + { + case 2: + /* 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"; + case 4: + return "fmv.x.s\t%0,%1"; + case 8: + return "fmv.x.d\t%0,%1"; + } if (src_code == MEM) - switch (GET_MODE_SIZE (mode)) + switch (width) { case 1: return "lbu\t%0,%1"; case 2: return "lhu\t%0,%1"; @@ -2326,18 +2337,24 @@ riscv_output_move (rtx dest, rtx src) return "mv\t%0,%z1"; if (FP_REG_P (REGNO (dest))) - { - if (!dbl_p) - return "fmv.w.x\t%0,%z1"; - if (TARGET_64BIT) - return "fmv.d.x\t%0,%z1"; - /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ - gcc_assert (src == CONST0_RTX (mode)); - return "fcvt.d.w\t%0,x0"; - } + switch (width) + { + case 2: + /* High 16 bits should be all-1, otherwise HW will treated + as a n-bit canonical NaN, but isn't matter for softfloat. */ + return "fmv.s.x\t%0,%1"; + case 4: + return "fmv.s.x\t%0,%z1"; + case 8: + if (TARGET_64BIT) + return "fmv.d.x\t%0,%z1"; + /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ + gcc_assert (src == CONST0_RTX (mode)); + return "fcvt.d.w\t%0,x0"; + } } if (dest_code == MEM) - switch (GET_MODE_SIZE (mode)) + switch (width) { case 1: return "sb\t%z1,%0"; case 2: return "sh\t%z1,%0"; @@ -2348,7 +2365,15 @@ riscv_output_move (rtx dest, rtx src) if (src_code == REG && FP_REG_P (REGNO (src))) { if (dest_code == REG && FP_REG_P (REGNO (dest))) - return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1"; + switch (width) + { + case 2: + return "fmv.s\t%0,%1"; + case 4: + return "fmv.s\t%0,%1"; + case 8: + return "fmv.d\t%0,%1"; + } if (dest_code == MEM) return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0"; @@ -5611,6 +5636,107 @@ riscv_asan_shadow_offset (void) return TARGET_64BIT ? (HOST_WIDE_INT_1 << 29) : 0; } +/* Implement TARGET_MANGLE_TYPE. */ + +static const char * +riscv_mangle_type (const_tree type) +{ + /* Half-precision float. */ + if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16) + return "Dh"; + + /* Use the default mangling. */ + return NULL; +} + +/* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ + +static bool +riscv_scalar_mode_supported_p (scalar_mode mode) +{ + if (mode == HFmode) + 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. */ + +static bool +riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode) +{ + if (mode == HFmode) + return true; + else + return default_libgcc_floating_mode_supported_p (mode); +} + +/* Set the value of FLT_EVAL_METHOD. + ISO/IEC TS 18661-3 defines two values that we'd like to make use of: + + 0: evaluate all operations and constants, whose semantic type has at + most the range and precision of type float, to the range and + precision of float; evaluate all other operations and constants to + the range and precision of the semantic type; + + N, where _FloatN is a supported interchange floating type + evaluate all operations and constants, whose semantic type has at + most the range and precision of _FloatN type, to the range and + precision of the _FloatN type; evaluate all other operations and + constants to the range and precision of the semantic type; + + If we have the zfh extensions then we support _Float16 in native + precision, so we should set this to 16. */ +static enum flt_eval_method +riscv_excess_precision (enum excess_precision_type type) +{ + switch (type) + { + case EXCESS_PRECISION_TYPE_FAST: + case EXCESS_PRECISION_TYPE_STANDARD: + return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT; + case EXCESS_PRECISION_TYPE_IMPLICIT: + return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16; + default: + gcc_unreachable (); + } + return FLT_EVAL_METHOD_UNPREDICTABLE; +} + +/* Implement TARGET_FLOATN_MODE. */ +static opt_scalar_float_mode +riscv_floatn_mode (int n, bool extended) +{ + if (!extended && n == 16) + return HFmode; + + return default_floatn_mode (n, extended); +} + +static void +riscv_init_libfuncs (void) +{ + /* 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); + + /* 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); +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -5794,6 +5920,25 @@ riscv_asan_shadow_offset (void) #undef TARGET_NEW_ADDRESS_PROFITABLE_P #define TARGET_NEW_ADDRESS_PROFITABLE_P riscv_new_address_profitable_p +#undef TARGET_MANGLE_TYPE +#define TARGET_MANGLE_TYPE riscv_mangle_type + +#undef TARGET_SCALAR_MODE_SUPPORTED_P +#define TARGET_SCALAR_MODE_SUPPORTED_P riscv_scalar_mode_supported_p + +#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P +#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \ + riscv_libgcc_floating_mode_supported_p + +#undef TARGET_INIT_LIBFUNCS +#define TARGET_INIT_LIBFUNCS riscv_init_libfuncs + +#undef TARGET_C_EXCESS_PRECISION +#define TARGET_C_EXCESS_PRECISION riscv_excess_precision + +#undef TARGET_FLOATN_MODE +#define TARGET_FLOATN_MODE riscv_floatn_mode + #undef TARGET_ASAN_SHADOW_OFFSET #define TARGET_ASAN_SHADOW_OFFSET riscv_asan_shadow_offset diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 308b64dd30d..88ef18aecb9 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -133,7 +133,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,SF,DF,TF" +(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF" (const_string "unknown")) ;; True if the main data type is twice the size of a word. @@ -323,20 +323,20 @@ (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF " (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")]) ;; Mode attribute for FP loads into integer registers. -(define_mode_attr softload [(SF "lw") (DF "ld")]) +(define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")]) ;; Instruction names for stores. (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")]) ;; Instruction names for FP stores from integer registers. -(define_mode_attr softstore [(SF "sw") (DF "sd")]) +(define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")]) ;; This attribute gives the best constraint to use for registers of ;; a given mode. (define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) ;; This attribute gives the format suffix for floating-point operations. -(define_mode_attr fmt [(SF "s") (DF "d")]) +(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")]) ;; This attribute gives the integer suffix for floating-point conversions. (define_mode_attr ifmt [(SI "w") (DI "l")]) @@ -346,7 +346,7 @@ (define_mode_attr amo [(SI "w") (DI "d")]) ;; This attribute gives the upper-case mode name for one unit of a ;; floating-point mode. -(define_mode_attr UNITMODE [(SF "SF") (DF "DF")]) +(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")]) ;; This attribute gives the integer mode that has half the size of ;; the controlling mode. @@ -1448,6 +1448,26 @@ (define_insn "extendsfdf2" [(set_attr "type" "fcvt") (set_attr "mode" "DF")]) +;; 16-bit floating point moves +(define_expand "movhf" + [(set (match_operand:HF 0 "") + (match_operand:HF 1 ""))] + "" +{ + if (riscv_legitimize_move (HFmode, operands[0], operands[1])) + DONE; +}) + + +(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"))] + "(register_operand (operands[0], HFmode) + || reg_or_0_operand (operands[1], HFmode))" + { return riscv_output_move (operands[0], operands[1]); } + [(set_attr "move_type" "fmove,move,load,store,mtc,mfc") + (set_attr "mode" "HF")]) + ;; ;; .................... ;; diff --git a/gcc/testsuite/g++.target/riscv/_Float16.C b/gcc/testsuite/g++.target/riscv/_Float16.C new file mode 100644 index 00000000000..b97d1fbcf1c --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/_Float16.C @@ -0,0 +1,18 @@ +/* { dg-do compile } */ + +_Float16 x; + +_Float16 foo1 (_Float16 a, _Float16 b) +{ + return a + b; +} + +_Float16 foo2 (_Float16 a, _Float16 b) +{ + return a * b; +} + +int foo3 (_Float16 a, _Float16 b) +{ + return a > b; +} diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c new file mode 100644 index 00000000000..0622588fdb9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if -mabi=lp64f -O" } */ + +_Float16 test_soft_move (_Float16 a, _Float16 b) +{ + return b; +} + +/* { dg-final { scan-assembler-not "fmv.h" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c new file mode 100644 index 00000000000..3d37823fa4d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if -mabi=lp64f -O" } */ + +_Float16 test_soft_add (_Float16 a, _Float16 b) +{ + /* Make sure __addhf3 not invoked here. */ + /* { dg-final { scan-assembler-times "call\t__extendhfsf2" 2 } } */ + return a + b; + /* { dg-final { scan-assembler-not "call\t__addhf3" } } */ + /* { dg-final { scan-assembler-times "fadd.s" 1 } } */ + /* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 } } */ +} + diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c new file mode 100644 index 00000000000..ecce364e310 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if -mabi=lp64f -O" } */ + +int test_soft_compare (_Float16 a, _Float16 b) +{ + /* Make sure __gthf2 not invoked here. */ + /* { dg-final { scan-assembler-times "call\t__extendhfsf2" 2 } } */ + return a > b; + /* { dg-final { scan-assembler-not "call\t__gthf2" } } */ + /* { dg-final { scan-assembler-times "fgt.s" 1 } } */ +} + diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c new file mode 100644 index 00000000000..ce4bc7a6a5d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i -mabi=lp64 -O" } */ + +int test_soft_compare (_Float16 a, _Float16 b) +{ + /* Make sure __gthf2 not invoked here. */ + /* { dg-final { scan-assembler-times "call\t__extendhfsf2" 2 } } */ + return a > b; + /* { dg-final { scan-assembler-not "call\t__gthf2" } } */ + /* { dg-final { scan-assembler-times "call\t__gtsf2" 1 } } */ +} + diff --git a/gcc/testsuite/gcc.target/riscv/_Float16.c b/gcc/testsuite/gcc.target/riscv/_Float16.c new file mode 100644 index 00000000000..cc131fd3e2c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +_Float16 x; + +_Float16 foo1 (_Float16 a, _Float16 b) +{ + return a + b; +} + +_Float16 foo2 (_Float16 a, _Float16 b) +{ + return a * b; +} + +int foo3 (_Float16 a, _Float16 b) +{ + return a > b; +} diff --git a/libgcc/config/riscv/sfp-machine.h b/libgcc/config/riscv/sfp-machine.h index 27fbe6e84d6..b2901f0b1fd 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_H _FP_QNANBIT_H #define _FP_NANFRAC_S _FP_QNANBIT_S #define _FP_NANFRAC_D _FP_QNANBIT_D, 0 #define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 @@ -63,6 +64,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_H _FP_QNANBIT_H #define _FP_NANFRAC_S _FP_QNANBIT_S #define _FP_NANFRAC_D _FP_QNANBIT_D #define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 @@ -80,6 +82,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__))); #define CMPtype __gcc_CMPtype +#define _FP_NANSIGN_H 0 #define _FP_NANSIGN_S 0 #define _FP_NANSIGN_D 0 #define _FP_NANSIGN_Q 0 diff --git a/libgcc/config/riscv/t-softfp32 b/libgcc/config/riscv/t-softfp32 index 59be1df827e..55261f98383 100644 --- a/libgcc/config/riscv/t-softfp32 +++ b/libgcc/config/riscv/t-softfp32 @@ -41,3 +41,8 @@ else softfp_extras := divsf3 divdf3 divtf3 endif + +softfp_extensions += hfsf hfdf hftf +softfp_truncations += tfhf dfhf sfhf +softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \ + floatsihf floatdihf floatunsihf floatundihf diff --git a/libgcc/config/riscv/t-softfp64 b/libgcc/config/riscv/t-softfp64 index 75870951202..c87d242d5c3 100644 --- a/libgcc/config/riscv/t-softfp64 +++ b/libgcc/config/riscv/t-softfp64 @@ -1,3 +1,4 @@ include $(srcdir)/config/riscv/t-softfp32 softfp_int_modes += ti +softfp_extras += fixhfti fixunshfti floattihf floatuntihf From patchwork Thu Jul 7 08:52:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kito Cheng X-Patchwork-Id: 55816 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0EFC3385B839 for ; Thu, 7 Jul 2022 08:54:07 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-x531.google.com (mail-pg1-x531.google.com [IPv6:2607:f8b0:4864:20::531]) by sourceware.org (Postfix) with ESMTPS id F09BC3858D32 for ; Thu, 7 Jul 2022 08:53:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F09BC3858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=sifive.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=sifive.com Received: by mail-pg1-x531.google.com with SMTP id i190so4674201pge.7 for ; Thu, 07 Jul 2022 01:53:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sifive.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cLVw4kdPCZa/xLMG5u6vYXHg81rzi7YhOnqB/G9h5V0=; b=PLlrG1hXzf93Al2wH1hsCqcTEvNHaUjkkbXZjTaWVmBHD5mYlOSHNWioW9tsPY+nNG F1x/2/dWQ0uQqZZ5iyzXDRQbq/A7YVOi6IUdekX0Rlfg22vEy6RDoDsQkco4LpvPZBcI Ptsil4lGYETdR9Wm0LH/+wDwLCWWFPeeXPBM2Y1dYXkKx3Gcaj7Q3L/HL2EI7c0LgxoE ePhZu3a21k/TIf50/Kkd94WRN7ukOjrIoKwkus4a/2j9xMxbsewEYR9JPGD0Gz2lcxfA fw3zC+qOkcbWQ1bykrjZ6q1w7oE902P08DaCBtVZBpL0wS3NlIUGPX+XQ49Nmi8SnmQP dXPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cLVw4kdPCZa/xLMG5u6vYXHg81rzi7YhOnqB/G9h5V0=; b=O5C9y1s+6TV9dcgD2v9UlXn0GshCoZvEheC0QKDveWchX7KlTlj8PxW9zIUWqbanCd lwfrlZREFPhN1STTsh/V4Nj2NKlhkMiMtzXZfNDmiQQqGDxe60zQaRlawUi20sKt87HI CNf+N1lnMdvrSrXbMaMLzrA7aerXlsHpbq7A1A2S1QcfNDmG75UjodlXK10vXWxsbEeM t2eojyJrB6XFo1JahcTkVHHVxdQz6AsTYTSShw+0PPGNWMssB3lvvuO8Wpmbf4MD0U5R Ysfk4O2QrrYsReoE6pyiSEk62sD4i1jG07OS6kCws0egqle40t5xZoSLfUrvuvmlTq6u BoBA== X-Gm-Message-State: AJIora+RzojpqvBO9iMoGmUhYABfZTR2kJJs+PFvqTaagvVjEW7r6sA6 jKWgtS/UkzdkgEZ37mO1Om94YJn0X5apZQ== X-Google-Smtp-Source: AGRyM1ta5+tdCxUdMezAdIwloMqjajbpYdmlQg04w4EUPGZkSXiY7sN1P0peCpUhq4Q5eKgD2vjHnw== X-Received: by 2002:a17:902:e94c:b0:16b:fe90:2f65 with SMTP id b12-20020a170902e94c00b0016bfe902f65mr9804503pll.111.1657184027516; Thu, 07 Jul 2022 01:53:47 -0700 (PDT) Received: from hsinchu02.internal.sifive.com (59-124-168-89.hinet-ip.hinet.net. [59.124.168.89]) by smtp.gmail.com with ESMTPSA id l6-20020a170903120600b0016a0bf0ce32sm18224665plh.70.2022.07.07.01.53.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Jul 2022 01:53:47 -0700 (PDT) From: Kito Cheng To: gcc-patches@gcc.gnu.org, kito.cheng@gmail.com, jim.wilson.gcc@gmail.com, palmer@dabbelt.com, andrew@sifive.com, juzhe.zhong@rivai.ai Subject: [PATCH 2/2] RISC-V: Support zfh and zfhmin extension Date: Thu, 7 Jul 2022 16:52:31 +0800 Message-Id: <20220707085231.68930-3-kito.cheng@sifive.com> X-Mailer: git-send-email 2.34.0 In-Reply-To: <20220707085231.68930-1-kito.cheng@sifive.com> References: <20220707085231.68930-1-kito.cheng@sifive.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URIBL_BLACK 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kito Cheng Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Zfh and Zfhmin are extensions for IEEE half precision, both are ratified in Jan. 2022[1]: - Zfh has full set of operation like F or D for single or double precision. - Zfhmin has only provide minimal support for half precision operation, like conversion, load, store and move instructions. [1] https://github.com/riscv/riscv-isa-manual/commit/b35a54079e0da11740ce5b1e6db999d1d5172768 gcc/ChangeLog: * common/config/riscv/riscv-common.cc (riscv_implied_info): Add zfh and zfhmin. (riscv_ext_version_table): Ditto. (riscv_ext_flag_table): Ditto. * config/riscv/riscv-opts.h (MASK_ZFHMIN): New. (MASK_ZFH): Ditto. (TARGET_ZFHMIN): Ditto. (TARGET_ZFH): Ditto. * config/riscv/riscv.cc (riscv_output_move): Handle HFmode move for zfh and zfhmin. (riscv_emit_float_compare): Handle HFmode. * config/riscv/riscv.md (ANYF): Add HF. (SOFTF): Add HF. (load): Ditto. (store): Ditto. (truncsfhf2): New. (truncdfhf2): Ditto. (extendhfsf2): Ditto. (extendhfdf2): Ditto. (*movhf_hardfloat): Ditto. (*movhf_softfloat): Make sure not ZFHMIN. * config/riscv/riscv.opt (riscv_zf_subext): New. gcc/testsuite/ChangeLog: * gcc.target/riscv/_Float16-zfh-1.c: New. * gcc.target/riscv/_Float16-zfh-2.c: Ditto. * gcc.target/riscv/_Float16-zfh-3.c: Ditto. * gcc.target/riscv/_Float16-zfhmin-1.c: Ditto. * gcc.target/riscv/_Float16-zfhmin-2.c: Ditto. * gcc.target/riscv/_Float16-zfhmin-3.c: Ditto. * gcc.target/riscv/arch-16.c: Ditto. * gcc.target/riscv/arch-17.c: Ditto. * gcc.target/riscv/predef-21.c: Ditto. * gcc.target/riscv/predef-22.c: Ditto. --- gcc/common/config/riscv/riscv-common.cc | 8 +++ gcc/config/riscv/riscv-opts.h | 6 ++ gcc/config/riscv/riscv.cc | 34 ++++++++++- gcc/config/riscv/riscv.md | 59 +++++++++++++++++-- gcc/config/riscv/riscv.opt | 3 + .../gcc.target/riscv/_Float16-zfh-1.c | 8 +++ .../gcc.target/riscv/_Float16-zfh-2.c | 8 +++ .../gcc.target/riscv/_Float16-zfh-3.c | 8 +++ .../gcc.target/riscv/_Float16-zfhmin-1.c | 9 +++ .../gcc.target/riscv/_Float16-zfhmin-2.c | 9 +++ .../gcc.target/riscv/_Float16-zfhmin-3.c | 9 +++ gcc/testsuite/gcc.target/riscv/arch-16.c | 5 ++ gcc/testsuite/gcc.target/riscv/arch-17.c | 5 ++ gcc/testsuite/gcc.target/riscv/predef-21.c | 59 +++++++++++++++++++ gcc/testsuite/gcc.target/riscv/predef-22.c | 59 +++++++++++++++++++ 15 files changed, 280 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/arch-16.c create mode 100644 gcc/testsuite/gcc.target/riscv/arch-17.c create mode 100644 gcc/testsuite/gcc.target/riscv/predef-21.c create mode 100644 gcc/testsuite/gcc.target/riscv/predef-22.c diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 0e5be2ce105..4ee1b3198c5 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -96,6 +96,9 @@ static const riscv_implied_info_t riscv_implied_info[] = {"zvl32768b", "zvl16384b"}, {"zvl65536b", "zvl32768b"}, + {"zfh", "zfhmin"}, + {"zfhmin", "f"}, + {NULL, NULL} }; @@ -193,6 +196,9 @@ static const struct riscv_ext_version riscv_ext_version_table[] = {"zvl32768b", ISA_SPEC_CLASS_NONE, 1, 0}, {"zvl65536b", ISA_SPEC_CLASS_NONE, 1, 0}, + {"zfh", ISA_SPEC_CLASS_NONE, 1, 0}, + {"zfhmin", ISA_SPEC_CLASS_NONE, 1, 0}, + /* Terminate the list. */ {NULL, ISA_SPEC_CLASS_NONE, 0, 0} }; @@ -1148,6 +1154,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = {"zvl32768b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32768B}, {"zvl65536b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL65536B}, + {"zfhmin", &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN}, + {"zfh", &gcc_options::x_riscv_zf_subext, MASK_ZFH}, {NULL, NULL, 0} }; diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 1e153b3a6e7..85e869e62e3 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -153,6 +153,12 @@ enum stack_protector_guard { #define TARGET_ZICBOM ((riscv_zicmo_subext & MASK_ZICBOM) != 0) #define TARGET_ZICBOP ((riscv_zicmo_subext & MASK_ZICBOP) != 0) +#define MASK_ZFHMIN (1 << 0) +#define MASK_ZFH (1 << 1) + +#define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0) +#define TARGET_ZFH ((riscv_zf_subext & MASK_ZFH) != 0) + /* Bit of riscv_zvl_flags will set contintuly, N-1 bit will set if N-bit is set, e.g. MASK_ZVL64B has set then MASK_ZVL32B is set, so we can use popcount to caclulate the minimal VLEN. */ diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 491e1aaf8c0..b445d39c294 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -2286,6 +2286,8 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: + if (TARGET_ZFHMIN) + 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"; case 4: @@ -2340,6 +2342,8 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: + if (TARGET_ZFHMIN) + 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. */ return "fmv.s.x\t%0,%1"; @@ -2368,6 +2372,8 @@ riscv_output_move (rtx dest, rtx src) switch (width) { case 2: + if (TARGET_ZFH) + return "fmv.h\t%0,%1"; return "fmv.s\t%0,%1"; case 4: return "fmv.s\t%0,%1"; @@ -2375,13 +2381,30 @@ riscv_output_move (rtx dest, rtx src) return "fmv.d\t%0,%1"; } + if (dest_code == MEM) - return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0"; + switch (width) + { + case 2: + return "fsh\t%1,%0"; + case 4: + return "fsw\t%1,%0"; + case 8: + return "fsd\t%1,%0"; + } } if (dest_code == REG && FP_REG_P (REGNO (dest))) { if (src_code == MEM) - return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1"; + switch (width) + { + case 2: + return "flh\t%0,%1"; + case 4: + return "flw\t%0,%1"; + case 8: + return "fld\t%0,%1"; + } } gcc_unreachable (); } @@ -2658,6 +2681,10 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) emit_insn (gen_f##CMP##_quietdfdi4 (*op0, cmp_op0, cmp_op1)); \ else if (GET_MODE (cmp_op0) == DFmode) \ emit_insn (gen_f##CMP##_quietdfsi4 (*op0, cmp_op0, cmp_op1)); \ + else if (GET_MODE (cmp_op0) == HFmode && TARGET_64BIT) \ + emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1)); \ + else if (GET_MODE (cmp_op0) == HFmode) \ + emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1)); \ else \ gcc_unreachable (); \ *op1 = const0_rtx; \ @@ -5695,7 +5722,8 @@ riscv_excess_precision (enum excess_precision_type type) { case EXCESS_PRECISION_TYPE_FAST: case EXCESS_PRECISION_TYPE_STANDARD: - return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT; + return (TARGET_ZFH ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 + : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT); case EXCESS_PRECISION_TYPE_IMPLICIT: return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16; default: diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 88ef18aecb9..ab5f8f819a6 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -306,17 +306,18 @@ (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")]) ;; Iterator for hardware-supported floating-point modes. (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT") - (DF "TARGET_DOUBLE_FLOAT")]) + (DF "TARGET_DOUBLE_FLOAT") + (HF "TARGET_ZFH")]) ;; Iterator for floating-point modes that can be loaded into X registers. -(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")]) +(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")]) ;; This attribute gives the length suffix for a sign- or zero-extension ;; instruction. (define_mode_attr size [(QI "b") (HI "h")]) ;; Mode attributes for loads. -(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")]) +(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")]) ;; Instruction names for integer loads that aren't explicitly sign or zero ;; extended. See riscv_output_move and LOAD_EXTEND_OP. @@ -326,7 +327,7 @@ (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")]) (define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")]) ;; Instruction names for stores. -(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")]) +(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")]) ;; Instruction names for FP stores from integer registers. (define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")]) @@ -1322,6 +1323,24 @@ (define_insn "truncdfsf2" [(set_attr "type" "fcvt") (set_attr "mode" "SF")]) +(define_insn "truncsfhf2" + [(set (match_operand:HF 0 "register_operand" "=f") + (float_truncate:HF + (match_operand:SF 1 "register_operand" " f")))] + "TARGET_ZFHMIN" + "fcvt.h.s\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "HF")]) + +(define_insn "truncdfhf2" + [(set (match_operand:HF 0 "register_operand" "=f") + (float_truncate:HF + (match_operand:DF 1 "register_operand" " f")))] + "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT" + "fcvt.h.d\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "HF")]) + ;; ;; .................... ;; @@ -1439,6 +1458,15 @@ (define_insn_and_split "*extend2" [(set_attr "move_type" "shift_shift,load") (set_attr "mode" "SI")]) +(define_insn "extendhfsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (float_extend:SF + (match_operand:HF 1 "register_operand" " f")))] + "TARGET_ZFHMIN" + "fcvt.s.h\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "SF")]) + (define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF @@ -1448,6 +1476,15 @@ (define_insn "extendsfdf2" [(set_attr "type" "fcvt") (set_attr "mode" "DF")]) +(define_insn "extendhfdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (float_extend:DF + (match_operand:HF 1 "register_operand" " f")))] + "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT" + "fcvt.d.h\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "DF")]) + ;; 16-bit floating point moves (define_expand "movhf" [(set (match_operand:HF 0 "") @@ -1458,12 +1495,22 @@ (define_expand "movhf" DONE; }) +(define_insn "*movhf_hardfloat" + [(set (match_operand:HF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m") + (match_operand:HF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))] + "TARGET_ZFHMIN + && (register_operand (operands[0], HFmode) + || reg_or_0_operand (operands[1], HFmode))" + { return riscv_output_move (operands[0], operands[1]); } + [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") + (set_attr "mode" "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"))] - "(register_operand (operands[0], HFmode) - || reg_or_0_operand (operands[1], HFmode))" + "!TARGET_ZFHMIN + && (register_operand (operands[0], HFmode) + || reg_or_0_operand (operands[1], HFmode))" { return riscv_output_move (operands[0], operands[1]); } [(set_attr "move_type" "fmove,move,load,store,mtc,mfc") (set_attr "mode" "HF")]) diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 9e9fe6d8ccd..fbca91b956c 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -212,6 +212,9 @@ int riscv_zvl_flags TargetVariable int riscv_zicmo_subext +TargetVariable +int riscv_zf_subext + Enum Name(isa_spec_class) Type(enum riscv_isa_spec_class) Supported ISA specs (for use with the -misa-spec= option): diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c new file mode 100644 index 00000000000..98908dccbb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */ + +_Float16 foo1 (_Float16 a, _Float16 b) +{ + /* { dg-final { scan-assembler-times "fmv.h" 1 } } */ + return b; +} diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c new file mode 100644 index 00000000000..58bfa6b4198 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */ + +_Float16 foo1 (_Float16 a, _Float16 b) +{ + /* { dg-final { scan-assembler-times "fadd.h" 1 } } */ + return a + b; +} diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c new file mode 100644 index 00000000000..128b4e53f27 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */ + +int foo1 (_Float16 a, _Float16 b) +{ + /* { dg-final { scan-assembler-times "fgt.h" 1 } } */ + return a > b; +} diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c new file mode 100644 index 00000000000..631a049f52f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */ + +_Float16 foo1 (_Float16 a, _Float16 b) +{ + /* { dg-final { scan-assembler-not "fmv.h" } } */ + /* { dg-final { scan-assembler-times "fmv.s" 1 } } */ + return b; +} diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c new file mode 100644 index 00000000000..06c85eb797d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */ + +_Float16 foo1 (_Float16 a, _Float16 b) +{ + /* { dg-final { scan-assembler-not "fadd.h" } } */ + /* { dg-final { scan-assembler-times "fadd.s" 1 } } */ + return a + b; +} diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c new file mode 100644 index 00000000000..28960d60245 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */ + +int foo1 (_Float16 a, _Float16 b) +{ + /* { dg-final { scan-assembler-not "fgt.h" } } */ + /* { dg-final { scan-assembler-times "fgt.s" 1 } } */ + return a > b; +} diff --git a/gcc/testsuite/gcc.target/riscv/arch-16.c b/gcc/testsuite/gcc.target/riscv/arch-16.c new file mode 100644 index 00000000000..14b40ae9a5a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-16.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv32gcv_zfh -mabi=ilp32 -mcmodel=medlow" } */ +int foo() +{ +} diff --git a/gcc/testsuite/gcc.target/riscv/arch-17.c b/gcc/testsuite/gcc.target/riscv/arch-17.c new file mode 100644 index 00000000000..3d3275e44a5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-17.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv32gcv_zfhmin -mabi=ilp32 -mcmodel=medlow" } */ +int foo() +{ +} diff --git a/gcc/testsuite/gcc.target/riscv/predef-21.c b/gcc/testsuite/gcc.target/riscv/predef-21.c new file mode 100644 index 00000000000..a171b3b83af --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/predef-21.c @@ -0,0 +1,59 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64i_zfh -mabi=lp64f -mcmodel=medlow -misa-spec=20191213" } */ + +int main () { + +#ifndef __riscv_arch_test +#error "__riscv_arch_test" +#endif + +#if __riscv_xlen != 64 +#error "__riscv_xlen" +#endif + +#if !defined(__riscv_i) +#error "__riscv_i" +#endif + +#if defined(__riscv_c) +#error "__riscv_c" +#endif + +#if defined(__riscv_e) +#error "__riscv_e" +#endif + +#if defined(__riscv_a) +#error "__riscv_a" +#endif + +#if defined(__riscv_m) +#error "__riscv_m" +#endif + +#if !defined(__riscv_f) +#error "__riscv_f" +#endif + +#if defined(__riscv_d) +#error "__riscv_d" +#endif + +#if defined(__riscv_v) +#error "__riscv_v" +#endif + +#if !defined(__riscv_zfh) +#error "__riscv_zfh" +#endif + +#if !defined(__riscv_zfhmin) +#error "__riscv_zfhmin" +#endif + +#if !defined(__riscv_zicsr) +#error "__riscv_zicsr" +#endif + + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/predef-22.c b/gcc/testsuite/gcc.target/riscv/predef-22.c new file mode 100644 index 00000000000..ad1896573ce --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/predef-22.c @@ -0,0 +1,59 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64i_zfhmin -mabi=lp64f -mcmodel=medlow -misa-spec=20191213" } */ + +int main () { + +#ifndef __riscv_arch_test +#error "__riscv_arch_test" +#endif + +#if __riscv_xlen != 64 +#error "__riscv_xlen" +#endif + +#if !defined(__riscv_i) +#error "__riscv_i" +#endif + +#if defined(__riscv_c) +#error "__riscv_c" +#endif + +#if defined(__riscv_e) +#error "__riscv_e" +#endif + +#if defined(__riscv_a) +#error "__riscv_a" +#endif + +#if defined(__riscv_m) +#error "__riscv_m" +#endif + +#if !defined(__riscv_f) +#error "__riscv_f" +#endif + +#if defined(__riscv_d) +#error "__riscv_d" +#endif + +#if defined(__riscv_v) +#error "__riscv_v" +#endif + +#if defined(__riscv_zfh) +#error "__riscv_zfh" +#endif + +#if !defined(__riscv_zfhmin) +#error "__riscv_zfhmin" +#endif + +#if !defined(__riscv_zicsr) +#error "__riscv_zicsr" +#endif + + return 0; +}