From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id 7D3AB3858D20 for ; Fri, 5 May 2023 15:13:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7D3AB3858D20 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=dabbelt.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=dabbelt.com Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-6435bbedb4fso2178043b3a.3 for ; Fri, 05 May 2023 08:13:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dabbelt-com.20221208.gappssmtp.com; s=20221208; t=1683299580; x=1685891580; h=content-transfer-encoding:mime-version:message-id:to:from:cc :in-reply-to:subject:date:from:to:cc:subject:date:message-id :reply-to; bh=rbNQ4rlJdROEIVQ89rW55QOssGvtGTx2H15sWwCJK7k=; b=I7AKzA44KjwfyHIjJxOJuakIy+k8+K0tTb4nCdEKz9vID4PRx0QtajOtQuKabdep8B g+Wtj3vqyrgEiNO+b32TtTx+FVRNziZSNUT7ruP3NataNTFJuL2vg0rUTnvI07yWYuUm OWRSYxI0R2ubKe26S3/WVlfuwyZYz7wGpJoy44D+URkPzSSYNQtid9dmf58X5/joHP4D ffYNRiHOvQujiXvFFDkw9L5fxgMueyAXykpJ3ztkl2KLNBPkgGinibxi8QeKTgc0rLi0 zu4XaQKGFEUjaarVH7/WnNhg9AxXb4Qzk4SWeQ01sqjQ+ZjTczdVbGIqugFSMpgLOgy8 CafQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1683299580; x=1685891580; h=content-transfer-encoding:mime-version:message-id:to:from:cc :in-reply-to:subject:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=rbNQ4rlJdROEIVQ89rW55QOssGvtGTx2H15sWwCJK7k=; b=g7rDnlV9s3KCPdg7C0NUesd+vSsJa+cNbtHy8q0S07tcVBiu88ouIUJJANiqMQITRq OVa2t32fB2WW3AyDrUrR+4yoHF2lwidPkVWVa0UIfbP63FuPjvDEmTv2w2U+RQ0Pi7vz cZcf6V5pZgcuEkWppulfqe1/mm/b1X3s1bs997A4YkPMb42NndoAY7/4+hmZ0tqKN1qz YZ1VRqxYXrlOr9vRjncLWL3IiDKLYKqd0Mv1Db+lz+ikbevjY+6ubHl1J2mrKTYHKLkW t5k/EVrz3WSq73Ul3zcFGFB0FdHQd7hVwl43aC0APfpU8NBDwwcJaOQgIjO8hNCjWGOZ yu5g== X-Gm-Message-State: AC+VfDzhTA7wItVMNnGpjsuaX8DvJlI+197Ls6tlhpI4jrrayV2Fczxk jChsXRljW8Sl09tKo5Edm1I7AQ== X-Google-Smtp-Source: ACHHUZ5mv8z4uvHmbYb8S2wEmrSrg4EjkLmek9/iro/O07bv3oqC8rvPE/XEaMHu5YJXkZ2QFr3lvA== X-Received: by 2002:a05:6a21:78a9:b0:f1:8f7:eeb5 with SMTP id bf41-20020a056a2178a900b000f108f7eeb5mr2219188pzc.60.1683299580054; Fri, 05 May 2023 08:13:00 -0700 (PDT) Received: from localhost ([135.180.227.0]) by smtp.gmail.com with ESMTPSA id d23-20020aa78697000000b00640f895fde9sm1744026pfo.214.2023.05.05.08.12.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 May 2023 08:12:59 -0700 (PDT) Date: Fri, 05 May 2023 08:12:59 -0700 (PDT) X-Google-Original-Date: Fri, 05 May 2023 08:12:55 PDT (-0700) Subject: Re: [PATCH v8] RISC-V: Add the 'zfa' extension, version 0.2. In-Reply-To: CC: jinma@linux.alibaba.com, gcc-patches@gcc.gnu.org, jeffreyalaw@gmail.com, kito.cheng@sifive.com, Kito Cheng , ijinma@yeah.net From: Palmer Dabbelt To: christoph.muellner@vrull.eu Message-ID: Mime-Version: 1.0 (MHng) Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, 05 May 2023 08:04:53 PDT (-0700), christoph.muellner@vrull.eu wrote: > What I forgot to mention: > Zfa is frozen and in public review: > https://groups.google.com/a/groups.riscv.org/g/isa-dev/c/SED4ntBkabg Thanks, I'd also forgot to send that out ;). I think the only blocker here on the specification side is the assembly format for FLI? It looks like the feedback on has been pretty minor so far. It'd be nice to have the docs lined up before we merge, but we could always just call it a GNU extension -- we've already got a lot of that in assembler land, so I don't think it's that big of a deal. > > On Fri, May 5, 2023 at 5:03 PM Christoph Müllner > wrote: >> >> On Wed, Apr 19, 2023 at 11:58 AM Jin Ma wrote: >> > >> > This patch adds the 'Zfa' extension for riscv, which is based on: >> > https://github.com/riscv/riscv-isa-manual/commits/zfb >> > https://github.com/riscv/riscv-isa-manual/commit/1f038182810727f5feca311072e630d6baac51da >> > >> > The binutils-gdb for 'Zfa' extension: >> > https://github.com/a4lg/binutils-gdb/commits/riscv-zfa >> > >> > What needs special explanation is: >> > 1, The immediate number of the instructions FLI.H/S/D is represented in the assembly as a >> > floating-point value, with scientific counting when rs1 is 1,2, and decimal numbers for >> > the rest. >> > >> > Related llvm link: >> > https://reviews.llvm.org/D145645 >> > Related discussion link: >> > https://github.com/riscv/riscv-isa-manual/issues/980 >> > >> > 2, According to riscv-spec, "The FCVTMO D.W.D instruction was added principally to >> > accelerate the processing of JavaScript Numbers.", so it seems that no implementation >> > is required. >> > >> > 3, The instructions FMINM and FMAXM correspond to C23 library function fminimum and fmaximum. >> > Therefore, this patch has simply implemented the pattern of fminm3 and >> > fmaxm3 to prepare for later. >> > >> > gcc/ChangeLog: >> > >> > * common/config/riscv/riscv-common.cc: Add zfa extension version. >> > * config/riscv/constraints.md (Zf): Constrain the floating point number that the >> > instructions FLI.H/S/D can load. >> > ((TARGET_XTHEADFMV || TARGET_ZFA) ? FP_REGS : NO_REGS): enable FMVP.D.X and FMVH.X.D. >> > * config/riscv/iterators.md (ceil): New. >> > * config/riscv/riscv-protos.h (riscv_float_const_rtx_index_for_fli): New. >> > * config/riscv/riscv.cc (find_index_in_array): New. >> > (riscv_float_const_rtx_index_for_fli): Get the index of the floating-point number that >> > the instructions FLI.H/S/D can mov. >> > (riscv_cannot_force_const_mem): If instruction FLI.H/S/D can be used, memory is not applicable. >> > (riscv_const_insns): The cost of FLI.H/S/D is 3. >> > (riscv_legitimize_const_move): Likewise. >> > (riscv_split_64bit_move_p): If instruction FLI.H/S/D can be used, no split is required. >> > (riscv_output_move): Output the mov instructions in zfa extension. >> > (riscv_print_operand): Output the floating-point value of the FLI.H/S/D immediate in assembly >> > (riscv_secondary_memory_needed): Likewise. >> > * config/riscv/riscv.h (GP_REG_RTX_P): New. >> > * config/riscv/riscv.md (fminm3): New. >> > >> > gcc/testsuite/ChangeLog: >> > >> > * gcc.target/riscv/zfa-fleq-fltq-rv32.c: New test. >> > * gcc.target/riscv/zfa-fleq-fltq.c: New test. >> > * gcc.target/riscv/zfa-fli-rv32.c: New test. >> > * gcc.target/riscv/zfa-fli-zfh-rv32.c: New test. >> > * gcc.target/riscv/zfa-fli-zfh.c: New test. >> > * gcc.target/riscv/zfa-fli.c: New test. >> > * gcc.target/riscv/zfa-fmovh-fmovp-rv32.c: New test. >> > * gcc.target/riscv/zfa-fround-rv32.c: New test. >> > * gcc.target/riscv/zfa-fround.c: New test. >> > --- >> > gcc/common/config/riscv/riscv-common.cc | 4 + >> > gcc/config/riscv/constraints.md | 11 +- >> > gcc/config/riscv/iterators.md | 5 + >> > gcc/config/riscv/riscv-opts.h | 3 + >> > gcc/config/riscv/riscv-protos.h | 1 + >> > gcc/config/riscv/riscv.cc | 168 +++++++++++++++++- >> > gcc/config/riscv/riscv.h | 1 + >> > gcc/config/riscv/riscv.md | 112 +++++++++--- >> > .../gcc.target/riscv/zfa-fleq-fltq-rv32.c | 19 ++ >> > .../gcc.target/riscv/zfa-fleq-fltq.c | 19 ++ >> > gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c | 79 ++++++++ >> > .../gcc.target/riscv/zfa-fli-zfh-rv32.c | 41 +++++ >> > gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c | 41 +++++ >> > gcc/testsuite/gcc.target/riscv/zfa-fli.c | 79 ++++++++ >> > .../gcc.target/riscv/zfa-fmovh-fmovp-rv32.c | 10 ++ >> > .../gcc.target/riscv/zfa-fround-rv32.c | 42 +++++ >> > gcc/testsuite/gcc.target/riscv/zfa-fround.c | 42 +++++ >> > 17 files changed, 652 insertions(+), 25 deletions(-) >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c >> > create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fround.c >> > >> > diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc >> > index 309a52def75..f9fce6bcc38 100644 >> > --- a/gcc/common/config/riscv/riscv-common.cc >> > +++ b/gcc/common/config/riscv/riscv-common.cc >> > @@ -217,6 +217,8 @@ static const struct riscv_ext_version riscv_ext_version_table[] = >> > {"zfh", ISA_SPEC_CLASS_NONE, 1, 0}, >> > {"zfhmin", ISA_SPEC_CLASS_NONE, 1, 0}, >> > >> > + {"zfa", ISA_SPEC_CLASS_NONE, 0, 2}, >> > + >> > {"zmmul", ISA_SPEC_CLASS_NONE, 1, 0}, >> > >> > {"svinval", ISA_SPEC_CLASS_NONE, 1, 0}, >> > @@ -1260,6 +1262,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = >> > {"zfhmin", &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN}, >> > {"zfh", &gcc_options::x_riscv_zf_subext, MASK_ZFH}, >> > >> > + {"zfa", &gcc_options::x_riscv_zf_subext, MASK_ZFA}, >> > + >> > {"zmmul", &gcc_options::x_riscv_zm_subext, MASK_ZMMUL}, >> > >> > {"svinval", &gcc_options::x_riscv_sv_subext, MASK_SVINVAL}, >> > diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md >> > index c448e6b37e9..62d9094f966 100644 >> > --- a/gcc/config/riscv/constraints.md >> > +++ b/gcc/config/riscv/constraints.md >> > @@ -118,6 +118,13 @@ (define_constraint "T" >> > (and (match_operand 0 "move_operand") >> > (match_test "CONSTANT_P (op)"))) >> > >> > +;; Zfa constraints. >> > + >> > +(define_constraint "Zf" >> > + "A floating point number that can be loaded using instruction `fli` in zfa." >> > + (and (match_code "const_double") >> > + (match_test "(riscv_float_const_rtx_index_for_fli (op) != -1)"))) >> > + >> > ;; Vector constraints. >> > >> > (define_register_constraint "vr" "TARGET_VECTOR ? V_REGS : NO_REGS" >> > @@ -183,8 +190,8 @@ (define_memory_constraint "Wdm" >> > >> > ;; Vendor ISA extension constraints. >> > >> > -(define_register_constraint "th_f_fmv" "TARGET_XTHEADFMV ? FP_REGS : NO_REGS" >> > +(define_register_constraint "th_f_fmv" "(TARGET_XTHEADFMV || TARGET_ZFA) ? FP_REGS : NO_REGS" >> > "A floating-point register for XTheadFmv.") >> > >> > -(define_register_constraint "th_r_fmv" "TARGET_XTHEADFMV ? GR_REGS : NO_REGS" >> > +(define_register_constraint "th_r_fmv" "(TARGET_XTHEADFMV || TARGET_ZFA) ? GR_REGS : NO_REGS" >> > "An integer register for XTheadFmv.") >> >> These are vendor extension constraints with the prefix "th_". >> I would avoid using them in code that targets standard extensions. >> >> I see two ways here: >> a) Create two new constraints at the top of the file. E.g.: >> - "F" - "A floating-point register (no fall-back for Zfinx)" and >> - "rF" - "A integer register in case FP registers are available". >> b) Move to top and rename these two constraints (and adjust >> movdf_hardfloat_rv32 accordingly) >> >> I would prefer b) and would even go so far, that I would do this in a >> separate commit that >> comes before the Zfa support patch. >> >> >> I've applied the patch on top of today's master (with --3way) and >> successfully tested it: >> Tested-by: Christoph Müllner >> >> > diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md >> > index 9b767038452..c81b08e3cc5 100644 >> > --- a/gcc/config/riscv/iterators.md >> > +++ b/gcc/config/riscv/iterators.md >> > @@ -288,3 +288,8 @@ (define_int_iterator QUIET_COMPARISON [UNSPEC_FLT_QUIET UNSPEC_FLE_QUIET]) >> > (define_int_attr quiet_pattern [(UNSPEC_FLT_QUIET "lt") (UNSPEC_FLE_QUIET "le")]) >> > (define_int_attr QUIET_PATTERN [(UNSPEC_FLT_QUIET "LT") (UNSPEC_FLE_QUIET "LE")]) >> > >> > +(define_int_iterator ROUND [UNSPEC_ROUND UNSPEC_FLOOR UNSPEC_CEIL UNSPEC_BTRUNC UNSPEC_ROUNDEVEN UNSPEC_NEARBYINT]) >> > +(define_int_attr round_pattern [(UNSPEC_ROUND "round") (UNSPEC_FLOOR "floor") (UNSPEC_CEIL "ceil") >> > + (UNSPEC_BTRUNC "btrunc") (UNSPEC_ROUNDEVEN "roundeven") (UNSPEC_NEARBYINT "nearbyint")]) >> > +(define_int_attr round_rm [(UNSPEC_ROUND "rmm") (UNSPEC_FLOOR "rdn") (UNSPEC_CEIL "rup") >> > + (UNSPEC_BTRUNC "rtz") (UNSPEC_ROUNDEVEN "rne") (UNSPEC_NEARBYINT "dyn")]) >> > \ No newline at end of file >> > diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h >> > index cf0cd669be4..87b72efd12e 100644 >> > --- a/gcc/config/riscv/riscv-opts.h >> > +++ b/gcc/config/riscv/riscv-opts.h >> > @@ -172,6 +172,9 @@ enum stack_protector_guard { >> > #define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0) >> > #define TARGET_ZFH ((riscv_zf_subext & MASK_ZFH) != 0) >> > >> > +#define MASK_ZFA (1 << 0) >> > +#define TARGET_ZFA ((riscv_zf_subext & MASK_ZFA) != 0) >> > + >> > #define MASK_ZMMUL (1 << 0) >> > #define TARGET_ZMMUL ((riscv_zm_subext & MASK_ZMMUL) != 0) >> > >> > diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h >> > index 5244e8dcbf0..e421244a06c 100644 >> > --- a/gcc/config/riscv/riscv-protos.h >> > +++ b/gcc/config/riscv/riscv-protos.h >> > @@ -38,6 +38,7 @@ enum riscv_symbol_type { >> > /* Routines implemented in riscv.cc. */ >> > extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx); >> > extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *); >> > +extern int riscv_float_const_rtx_index_for_fli (rtx); >> > extern int riscv_regno_mode_ok_for_base_p (int, machine_mode, bool); >> > extern int riscv_address_insns (rtx, machine_mode, bool); >> > extern int riscv_const_insns (rtx); >> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc >> > index cdb47e81e7c..faffedffe97 100644 >> > --- a/gcc/config/riscv/riscv.cc >> > +++ b/gcc/config/riscv/riscv.cc >> > @@ -799,6 +799,116 @@ static int riscv_symbol_insns (enum riscv_symbol_type type) >> > } >> > } >> > >> > +/* Immediate values loaded by the FLI.S instruction in Chapter 25 of the latest RISC-V ISA >> > + Manual draft. For details, please see: >> > + https://github.com/riscv/riscv-isa-manual/releases/tag/draft-20221217-cb3b9d1 */ >> > + >> > +unsigned HOST_WIDE_INT fli_value_hf[32] = >> > +{ >> > + 0xbc00, 0x400, 0x100, 0x200, 0x1c00, 0x2000, 0x2c00, 0x3000, >> > + 0x3400, 0x3500, 0x3600, 0x3700, 0x3800, 0x3900, 0x3a00, 0x3b00, >> > + 0x3c00, 0x3d00, 0x3e00, 0x3f00, 0x4000, 0x4100, 0x4200, 0x4400, >> > + 0x4800, 0x4c00, 0x5800, 0x5c00, 0x7800, >> > + /* Only used for filling, ensuring that 29 and 30 of HF are the same. */ >> > + 0x7800, >> > + 0x7c00, 0x7e00, >> > +}; >> > + >> > +unsigned HOST_WIDE_INT fli_value_sf[32] = >> > +{ >> > + 0xbf800000, 0x00800000, 0x37800000, 0x38000000, 0x3b800000, 0x3c000000, 0x3d800000, 0x3e000000, >> > + 0x3e800000, 0x3ea00000, 0x3ec00000, 0x3ee00000, 0x3f000000, 0x3f200000, 0x3f400000, 0x3f600000, >> > + 0x3f800000, 0x3fa00000, 0x3fc00000, 0x3fe00000, 0x40000000, 0x40200000, 0x40400000, 0x40800000, >> > + 0x41000000, 0x41800000, 0x43000000, 0x43800000, 0x47000000, 0x47800000, 0x7f800000, 0x7fc00000 >> > +}; >> > + >> > +unsigned HOST_WIDE_INT fli_value_df[32] = >> > +{ >> > + 0xbff0000000000000, 0x10000000000000, 0x3ef0000000000000, 0x3f00000000000000, >> > + 0x3f70000000000000, 0x3f80000000000000, 0x3fb0000000000000, 0x3fc0000000000000, >> > + 0x3fd0000000000000, 0x3fd4000000000000, 0x3fd8000000000000, 0x3fdc000000000000, >> > + 0x3fe0000000000000, 0x3fe4000000000000, 0x3fe8000000000000, 0x3fec000000000000, >> > + 0x3ff0000000000000, 0x3ff4000000000000, 0x3ff8000000000000, 0x3ffc000000000000, >> > + 0x4000000000000000, 0x4004000000000000, 0x4008000000000000, 0x4010000000000000, >> > + 0x4020000000000000, 0x4030000000000000, 0x4060000000000000, 0x4070000000000000, >> > + 0x40e0000000000000, 0x40f0000000000000, 0x7ff0000000000000, 0x7ff8000000000000, >> > +}; >> > + >> > +const char *fli_value_print[32] = >> > +{ >> > + "-1.0", "min", "1.52587890625e-05", "3.0517578125e-05", "0.00390625", "0.0078125", "0.0625", "0.125", >> > + "0.25", "0.3125", "0.375", "0.4375", "0.5", "0.625", "0.75", "0.875", >> > + "1.0", "1.25", "1.5", "1.75", "2.0", "2.5", "3.0", "4.0", >> > + "8.0", "16.0", "128.0", "256.0", "32768.0", "65536.0", "inf", "nan" >> > +}; >> > + >> > +/* Find the index of TARGET in ARRAY, and return -1 if not found. */ >> > + >> > +static int >> > +find_index_in_array (unsigned HOST_WIDE_INT target, unsigned HOST_WIDE_INT *array, int len) >> > +{ >> > + if (array == NULL) >> > + return -1; >> > + >> > + for (int i = 0; i < len; i++) >> > + { >> > + if (target == array[i]) >> > + return i; >> > + } >> > + return -1; >> > +} >> > + >> > +/* Return index of the FLI instruction table if rtx X is an immediate constant that >> > + can be moved using a single FLI instruction in zfa extension. -1 otherwise. */ >> > + >> > +int >> > +riscv_float_const_rtx_index_for_fli (rtx x) >> > +{ >> > + machine_mode mode = GET_MODE (x); >> > + >> > + if (!TARGET_ZFA || mode == VOIDmode >> > + || !CONST_DOUBLE_P(x) >> > + || (mode == HFmode && !TARGET_ZFH) >> > + || (mode == SFmode && !TARGET_HARD_FLOAT) >> > + || (mode == DFmode && !TARGET_DOUBLE_FLOAT)) >> > + return -1; >> > + >> > + if (!SCALAR_FLOAT_MODE_P (mode) >> > + || GET_MODE_BITSIZE (mode).to_constant () > HOST_BITS_PER_WIDE_INT >> > + /* Only support up to DF mode. */ >> > + || GET_MODE_BITSIZE (mode).to_constant () > GET_MODE_BITSIZE (DFmode)) >> > + return -1; >> > + >> > + unsigned HOST_WIDE_INT ival = 0; >> > + >> > + long res[2]; >> > + real_to_target (res, >> > + CONST_DOUBLE_REAL_VALUE (x), >> > + REAL_MODE_FORMAT (mode)); >> > + >> > + if (mode == DFmode) >> > + { >> > + int order = BYTES_BIG_ENDIAN ? 1 : 0; >> > + ival = zext_hwi (res[order], 32); >> > + ival |= (zext_hwi (res[1 - order], 32) << 32); >> > + } >> > + else >> > + ival = zext_hwi (res[0], 32); >> > + >> > + switch (mode) >> > + { >> > + case SFmode: >> > + return find_index_in_array (ival, fli_value_sf, 32); >> > + case DFmode: >> > + return find_index_in_array (ival, fli_value_df, 32); >> > + case HFmode: >> > + return find_index_in_array (ival, fli_value_hf, 32); >> > + default: >> > + break; >> > + } >> > + return -1; >> > +} >> > + >> > /* Implement TARGET_LEGITIMATE_CONSTANT_P. */ >> > >> > static bool >> > @@ -826,6 +936,9 @@ riscv_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) >> > if (GET_CODE (x) == HIGH) >> > return true; >> > >> > + if (riscv_float_const_rtx_index_for_fli (x) != -1) >> > + return true; >> > + >> > split_const (x, &base, &offset); >> > if (riscv_symbolic_constant_p (base, &type)) >> > { >> > @@ -1213,6 +1326,11 @@ riscv_const_insns (rtx x) >> > } >> > >> > case CONST_DOUBLE: >> > + /* See if we can use FMV directly. */ >> > + if (riscv_float_const_rtx_index_for_fli (x) != -1) >> > + return 3; >> > + /* Fall through. */ >> > + >> > case CONST_VECTOR: >> > /* We can use x0 to load floating-point zero. */ >> > return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; >> > @@ -1749,6 +1867,12 @@ riscv_legitimize_const_move (machine_mode mode, rtx dest, rtx src) >> > return; >> > } >> > >> > + if (riscv_float_const_rtx_index_for_fli (src) != -1) >> > + { >> > + riscv_emit_set (dest, src); >> > + return; >> > + } >> > + >> > /* Split moves of symbolic constants into high/low pairs. */ >> > if (riscv_split_symbol (dest, src, MAX_MACHINE_MODE, &src, FALSE)) >> > { >> > @@ -2770,12 +2894,19 @@ riscv_split_64bit_move_p (rtx dest, rtx src) >> > if (TARGET_64BIT) >> > return false; >> > >> > + /* There is no need to split if the FLI instruction in the `Zfa` extension can be used. */ >> > + if (riscv_float_const_rtx_index_for_fli (src) != -1) >> > + return false; >> > + >> > /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case >> > of zeroing an FPR with FCVT.D.W. */ >> > if (TARGET_DOUBLE_FLOAT >> > && ((FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) >> > || (FP_REG_RTX_P (dest) && MEM_P (src)) >> > || (FP_REG_RTX_P (src) && MEM_P (dest)) >> > + || (TARGET_ZFA >> > + && ((FP_REG_RTX_P (dest) && GP_REG_RTX_P (src)) >> > + || (FP_REG_RTX_P (src) && GP_REG_RTX_P (dest)))) >> > || (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src))))) >> > return false; >> > >> > @@ -2857,6 +2988,8 @@ riscv_output_move (rtx dest, rtx src) >> > case 4: >> > return "fmv.x.s\t%0,%1"; >> > case 8: >> > + if (!TARGET_64BIT && TARGET_ZFA) >> > + return "fmv.x.w\t%0,%1\n\tfmvh.x.d\t%N0,%1"; >> > return "fmv.x.d\t%0,%1"; >> > } >> > >> > @@ -2916,6 +3049,8 @@ riscv_output_move (rtx dest, rtx src) >> > case 8: >> > if (TARGET_64BIT) >> > return "fmv.d.x\t%0,%z1"; >> > + else if (TARGET_ZFA && src != CONST0_RTX (mode)) >> > + return "fmvp.d.x\t%0,%1,%N1"; >> > /* 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"; >> > @@ -2968,6 +3103,14 @@ riscv_output_move (rtx dest, rtx src) >> > case 8: >> > return "fld\t%0,%1"; >> > } >> > + >> > + if (src_code == CONST_DOUBLE && (riscv_float_const_rtx_index_for_fli (src) != -1)) >> > + switch (width) >> > + { >> > + case 2: return "fli.h\t%0,%1"; >> > + case 4: return "fli.s\t%0,%1"; >> > + case 8: return "fli.d\t%0,%1"; >> > + } >> > } >> > if (dest_code == REG && GP_REG_P (REGNO (dest)) && src_code == CONST_POLY_INT) >> > { >> > @@ -4349,6 +4492,7 @@ riscv_memmodel_needs_release_fence (enum memmodel model) >> > 'S' Print shift-index of single-bit mask OP. >> > 'T' Print shift-index of inverted single-bit mask OP. >> > '~' Print w if TARGET_64BIT is true; otherwise not print anything. >> > + 'N' Print next register. >> > >> > Note please keep this list and the list in riscv.md in sync. */ >> > >> > @@ -4533,6 +4677,9 @@ riscv_print_operand (FILE *file, rtx op, int letter) >> > output_addr_const (file, newop); >> > break; >> > } >> > + case 'N': >> > + fputs (reg_names[REGNO (op) + 1], file); >> > + break; >> > default: >> > switch (code) >> > { >> > @@ -4549,6 +4696,24 @@ riscv_print_operand (FILE *file, rtx op, int letter) >> > output_address (mode, XEXP (op, 0)); >> > break; >> > >> > + case CONST_DOUBLE: >> > + { >> > + if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) >> > + { >> > + fputs (reg_names[GP_REG_FIRST], file); >> > + break; >> > + } >> > + >> > + int fli_index = riscv_float_const_rtx_index_for_fli (op); >> > + if (fli_index == -1 || fli_index > 31) >> > + { >> > + output_operand_lossage ("invalid use of '%%%c'", letter); >> > + break; >> > + } >> > + asm_fprintf (file, "%s", fli_value_print[fli_index]); >> > + break; >> > + } >> > + >> > default: >> > if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) >> > fputs (reg_names[GP_REG_FIRST], file); >> > @@ -5897,7 +6062,8 @@ riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1, >> > return (!riscv_v_ext_vector_mode_p (mode) >> > && GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD >> > && (class1 == FP_REGS) != (class2 == FP_REGS) >> > - && !TARGET_XTHEADFMV); >> > + && !TARGET_XTHEADFMV >> > + && !TARGET_ZFA); >> > } >> > >> > /* Implement TARGET_REGISTER_MOVE_COST. */ >> > diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h >> > index 66fb07d6652..d438b281142 100644 >> > --- a/gcc/config/riscv/riscv.h >> > +++ b/gcc/config/riscv/riscv.h >> > @@ -377,6 +377,7 @@ ASM_MISA_SPEC >> > #define SIBCALL_REG_P(REGNO) \ >> > TEST_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], REGNO) >> > >> > +#define GP_REG_RTX_P(X) (REG_P (X) && GP_REG_P (REGNO (X))) >> > #define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X))) >> > >> > /* Use s0 as the frame pointer if it is so requested. */ >> > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md >> > index bc384d9aedf..f22e71b5a3a 100644 >> > --- a/gcc/config/riscv/riscv.md >> > +++ b/gcc/config/riscv/riscv.md >> > @@ -59,6 +59,15 @@ (define_c_enum "unspec" [ >> > UNSPEC_LROUND >> > UNSPEC_FMIN >> > UNSPEC_FMAX >> > + UNSPEC_RINT >> > + UNSPEC_ROUND >> > + UNSPEC_FLOOR >> > + UNSPEC_CEIL >> > + UNSPEC_BTRUNC >> > + UNSPEC_ROUNDEVEN >> > + UNSPEC_NEARBYINT >> > + UNSPEC_FMINM >> > + UNSPEC_FMAXM >> > >> > ;; Stack tie >> > UNSPEC_TIE >> > @@ -1232,6 +1241,26 @@ (define_insn "neg2" >> > ;; >> > ;; .................... >> > >> > +(define_insn "fminm3" >> > + [(set (match_operand:ANYF 0 "register_operand" "=f") >> > + (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f")) >> > + (use (match_operand:ANYF 2 "register_operand" " f"))] >> > + UNSPEC_FMINM))] >> > + "TARGET_HARD_FLOAT && TARGET_ZFA" >> > + "fminm.\t%0,%1,%2" >> > + [(set_attr "type" "fmove") >> > + (set_attr "mode" "")]) >> > + >> > +(define_insn "fmaxm3" >> > + [(set (match_operand:ANYF 0 "register_operand" "=f") >> > + (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f")) >> > + (use (match_operand:ANYF 2 "register_operand" " f"))] >> > + UNSPEC_FMAXM))] >> > + "TARGET_HARD_FLOAT && TARGET_ZFA" >> > + "fmaxm.\t%0,%1,%2" >> > + [(set_attr "type" "fmove") >> > + (set_attr "mode" "")]) >> > + >> > (define_insn "fmin3" >> > [(set (match_operand:ANYF 0 "register_operand" "=f") >> > (unspec:ANYF [(use (match_operand:ANYF 1 "register_operand" " f")) >> > @@ -1508,13 +1537,13 @@ (define_expand "movhf" >> > }) >> > >> > (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"))] >> > + [(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,Zf,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 "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > (set_attr "mode" "HF")]) >> > >> > (define_insn "*movhf_softfloat" >> > @@ -1580,6 +1609,26 @@ (define_insn "l2" >> > [(set_attr "type" "fcvt") >> > (set_attr "mode" "")]) >> > >> > +(define_insn "2" >> > + [(set (match_operand:ANYF 0 "register_operand" "=f") >> > + (unspec:ANYF >> > + [(match_operand:ANYF 1 "register_operand" " f")] >> > + ROUND))] >> > + "TARGET_HARD_FLOAT && TARGET_ZFA" >> > + "fround.\t%0,%1," >> > + [(set_attr "type" "fcvt") >> > + (set_attr "mode" "")]) >> > + >> > +(define_insn "rint2" >> > + [(set (match_operand:ANYF 0 "register_operand" "=f") >> > + (unspec:ANYF >> > + [(match_operand:ANYF 1 "register_operand" " f")] >> > + UNSPEC_RINT))] >> > + "TARGET_HARD_FLOAT && TARGET_ZFA" >> > + "froundnx.\t%0,%1" >> > + [(set_attr "type" "fcvt") >> > + (set_attr "mode" "")]) >> > + >> > ;; >> > ;; .................... >> > ;; >> > @@ -1839,13 +1888,13 @@ (define_expand "movsf" >> > }) >> > >> > (define_insn "*movsf_hardfloat" >> > - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m") >> > - (match_operand:SF 1 "move_operand" " f,G,m,f,G,*r,*f,*G*r,*m,*r"))] >> > + [(set (match_operand:SF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m") >> > + (match_operand:SF 1 "move_operand" " f,Zf,G,m,f,G,*r,*f,*G*r,*m,*r"))] >> > "TARGET_HARD_FLOAT >> > && (register_operand (operands[0], SFmode) >> > || reg_or_0_operand (operands[1], SFmode))" >> > { return riscv_output_move (operands[0], operands[1]); } >> > - [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > + [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > (set_attr "mode" "SF")]) >> > >> > (define_insn "*movsf_softfloat" >> > @@ -1873,23 +1922,23 @@ (define_expand "movdf" >> > ;; In RV32, we lack fmv.x.d and fmv.d.x. Go through memory instead. >> > ;; (However, we can still use fcvt.d.w to zero a floating-point register.) >> > (define_insn "*movdf_hardfloat_rv32" >> > - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*th_f_fmv,*th_r_fmv, *r,*r,*m") >> > - (match_operand:DF 1 "move_operand" " f,G,m,f,G,*th_r_fmv,*th_f_fmv,*r*G,*m,*r"))] >> > + [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*th_f_fmv,*th_r_fmv, *r,*r,*m") >> > + (match_operand:DF 1 "move_operand" " f,Zf,G,m,f,G,*th_r_fmv,*th_f_fmv,*r*G,*m,*r"))] >> > "!TARGET_64BIT && TARGET_DOUBLE_FLOAT >> > && (register_operand (operands[0], DFmode) >> > || reg_or_0_operand (operands[1], DFmode))" >> > { return riscv_output_move (operands[0], operands[1]); } >> > - [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > + [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > (set_attr "mode" "DF")]) >> > >> > (define_insn "*movdf_hardfloat_rv64" >> > - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r, *r,*r,*m") >> > - (match_operand:DF 1 "move_operand" " f,G,m,f,G,*r,*f,*r*G,*m,*r"))] >> > + [(set (match_operand:DF 0 "nonimmediate_operand" "=f, f,f,f,m,m,*f,*r, *r,*r,*m") >> > + (match_operand:DF 1 "move_operand" " f,Zf,G,m,f,G,*r,*f,*r*G,*m,*r"))] >> > "TARGET_64BIT && TARGET_DOUBLE_FLOAT >> > && (register_operand (operands[0], DFmode) >> > || reg_or_0_operand (operands[1], DFmode))" >> > { return riscv_output_move (operands[0], operands[1]); } >> > - [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > + [(set_attr "move_type" "fmove,fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") >> > (set_attr "mode" "DF")]) >> > >> > (define_insn "*movdf_softfloat" >> > @@ -2494,16 +2543,23 @@ (define_expand "f_quiet4" >> > rtx op0 = operands[0]; >> > rtx op1 = operands[1]; >> > rtx op2 = operands[2]; >> > - rtx tmp = gen_reg_rtx (SImode); >> > - rtx cmp = gen_rtx_ (mode, op1, op2); >> > - rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, const0_rtx), >> > - UNSPECV_FRFLAGS); >> > - rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp), >> > - UNSPECV_FSFLAGS); >> > - >> > - emit_insn (gen_rtx_SET (tmp, frflags)); >> > - emit_insn (gen_rtx_SET (op0, cmp)); >> > - emit_insn (fsflags); >> > + >> > + if (TARGET_ZFA) >> > + emit_insn (gen_f_quiet4_zfa(op0, op1, op2)); >> > + else >> > + { >> > + rtx tmp = gen_reg_rtx (SImode); >> > + rtx cmp = gen_rtx_ (mode, op1, op2); >> > + rtx frflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, const0_rtx), >> > + UNSPECV_FRFLAGS); >> > + rtx fsflags = gen_rtx_UNSPEC_VOLATILE (SImode, gen_rtvec (1, tmp), >> > + UNSPECV_FSFLAGS); >> > + >> > + emit_insn (gen_rtx_SET (tmp, frflags)); >> > + emit_insn (gen_rtx_SET (op0, cmp)); >> > + emit_insn (fsflags); >> > + } >> > + >> > if (HONOR_SNANS (mode)) >> > emit_insn (gen_rtx_UNSPEC_VOLATILE (mode, >> > gen_rtvec (2, op1, op2), >> > @@ -2511,6 +2567,18 @@ (define_expand "f_quiet4" >> > DONE; >> > }) >> > >> > +(define_insn "f_quiet4_zfa" >> > + [(set (match_operand:X 0 "register_operand" "=r") >> > + (unspec:X >> > + [(match_operand:ANYF 1 "register_operand" " f") >> > + (match_operand:ANYF 2 "register_operand" " f")] >> > + QUIET_COMPARISON))] >> > + "TARGET_HARD_FLOAT && TARGET_ZFA" >> > + "fq.\t%0,%1,%2" >> > + [(set_attr "type" "fcmp") >> > + (set_attr "mode" "") >> > + (set (attr "length") (const_int 16))]) >> > + >> > (define_insn "*seq_zero_" >> > [(set (match_operand:GPR 0 "register_operand" "=r") >> > (eq:GPR (match_operand:X 1 "register_operand" " r") >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c >> > new file mode 100644 >> > index 00000000000..26895b76fa4 >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq-rv32.c >> > @@ -0,0 +1,19 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv32imafdc_zfa -mabi=ilp32d -O2" } */ >> > + >> > +extern void abort(void); >> > +extern float a, b; >> > +extern double c, d; >> > + >> > +void >> > +foo() >> > +{ >> > + if ((__builtin_isless(a, b) || __builtin_islessequal(c, d)) >> > + && (__builtin_islessequal(a, b)|| __builtin_isless(c, d))) >> > + abort(); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fleq.s" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fltq.s" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fleq.d" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fltq.d" 1 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c >> > new file mode 100644 >> > index 00000000000..4ccd6a7dd78 >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fleq-fltq.c >> > @@ -0,0 +1,19 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv64imafdc_zfa -mabi=lp64d -O2" } */ >> > + >> > +extern void abort(void); >> > +extern float a, b; >> > +extern double c, d; >> > + >> > +void >> > +foo() >> > +{ >> > + if ((__builtin_isless(a, b) || __builtin_islessequal(c, d)) >> > + && (__builtin_islessequal(a, b)|| __builtin_isless(c, d))) >> > + abort(); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fleq.s" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fltq.s" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fleq.d" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fltq.d" 1 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c >> > new file mode 100644 >> > index 00000000000..c4da04797aa >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-rv32.c >> > @@ -0,0 +1,79 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv32imafdc_zfa -mabi=ilp32d -O0" } */ >> > + >> > +void foo_float32 () >> > +{ >> > + volatile float a; >> > + a = -1.0; >> > + a = 1.1754944e-38; >> > + a = 1.0/(1 << 16); >> > + a = 1.0/(1 << 15); >> > + a = 1.0/(1 << 8); >> > + a = 1.0/(1 << 7); >> > + a = 1.0/(1 << 4); >> > + a = 1.0/(1 << 3); >> > + a = 1.0/(1 << 2); >> > + a = 0.3125; >> > + a = 0.375; >> > + a = 0.4375; >> > + a = 0.5; >> > + a = 0.625; >> > + a = 0.75; >> > + a = 0.875; >> > + a = 1.0; >> > + a = 1.25; >> > + a = 1.5; >> > + a = 1.75; >> > + a = 2.0; >> > + a = 2.5; >> > + a = 3.0; >> > + a = 1.0*(1 << 2); >> > + a = 1.0*(1 << 3); >> > + a = 1.0*(1 << 4); >> > + a = 1.0*(1 << 7); >> > + a = 1.0*(1 << 8); >> > + a = 1.0*(1 << 15); >> > + a = 1.0*(1 << 16); >> > + a = __builtin_inff (); >> > + a = __builtin_nanf (""); >> > +} >> > + >> > +void foo_double64 () >> > +{ >> > + volatile double a; >> > + a = -1.0; >> > + a = 2.2250738585072014E-308; >> > + a = 1.0/(1 << 16); >> > + a = 1.0/(1 << 15); >> > + a = 1.0/(1 << 8); >> > + a = 1.0/(1 << 7); >> > + a = 1.0/(1 << 4); >> > + a = 1.0/(1 << 3); >> > + a = 1.0/(1 << 2); >> > + a = 0.3125; >> > + a = 0.375; >> > + a = 0.4375; >> > + a = 0.5; >> > + a = 0.625; >> > + a = 0.75; >> > + a = 0.875; >> > + a = 1.0; >> > + a = 1.25; >> > + a = 1.5; >> > + a = 1.75; >> > + a = 2.0; >> > + a = 2.5; >> > + a = 3.0; >> > + a = 1.0*(1 << 2); >> > + a = 1.0*(1 << 3); >> > + a = 1.0*(1 << 4); >> > + a = 1.0*(1 << 7); >> > + a = 1.0*(1 << 8); >> > + a = 1.0*(1 << 15); >> > + a = 1.0*(1 << 16); >> > + a = __builtin_inf (); >> > + a = __builtin_nan (""); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fli.s" 32 } } */ >> > +/* { dg-final { scan-assembler-times "fli.d" 32 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c >> > new file mode 100644 >> > index 00000000000..bcffe9d2c82 >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh-rv32.c >> > @@ -0,0 +1,41 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv32imafdc_zfa_zfh -mabi=ilp32d -O0" } */ >> > + >> > +void foo_float16 () >> > +{ >> > + volatile _Float16 a; >> > + a = -1.0; >> > + a = 6.104E-5; >> > + a = 1.0/(1 << 16); >> > + a = 1.0/(1 << 15); >> > + a = 1.0/(1 << 8); >> > + a = 1.0/(1 << 7); >> > + a = 1.0/(1 << 4); >> > + a = 1.0/(1 << 3); >> > + a = 1.0/(1 << 2); >> > + a = 0.3125; >> > + a = 0.375; >> > + a = 0.4375; >> > + a = 0.5; >> > + a = 0.625; >> > + a = 0.75; >> > + a = 0.875; >> > + a = 1.0; >> > + a = 1.25; >> > + a = 1.5; >> > + a = 1.75; >> > + a = 2.0; >> > + a = 2.5; >> > + a = 3.0; >> > + a = 1.0*(1 << 2); >> > + a = 1.0*(1 << 3); >> > + a = 1.0*(1 << 4); >> > + a = 1.0*(1 << 7); >> > + a = 1.0*(1 << 8); >> > + a = 1.0*(1 << 15); >> > + a = 1.0*(1 << 16); >> > + a = __builtin_inff16 (); >> > + a = __builtin_nanf16 (""); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fli.h" 32 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c >> > new file mode 100644 >> > index 00000000000..13aa7b5f846 >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-zfh.c >> > @@ -0,0 +1,41 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv64imafdc_zfa_zfh -mabi=lp64d -O0" } */ >> > + >> > +void foo_float16 () >> > +{ >> > + volatile _Float16 a; >> > + a = -1.0; >> > + a = 6.104E-5; >> > + a = 1.0/(1 << 16); >> > + a = 1.0/(1 << 15); >> > + a = 1.0/(1 << 8); >> > + a = 1.0/(1 << 7); >> > + a = 1.0/(1 << 4); >> > + a = 1.0/(1 << 3); >> > + a = 1.0/(1 << 2); >> > + a = 0.3125; >> > + a = 0.375; >> > + a = 0.4375; >> > + a = 0.5; >> > + a = 0.625; >> > + a = 0.75; >> > + a = 0.875; >> > + a = 1.0; >> > + a = 1.25; >> > + a = 1.5; >> > + a = 1.75; >> > + a = 2.0; >> > + a = 2.5; >> > + a = 3.0; >> > + a = 1.0*(1 << 2); >> > + a = 1.0*(1 << 3); >> > + a = 1.0*(1 << 4); >> > + a = 1.0*(1 << 7); >> > + a = 1.0*(1 << 8); >> > + a = 1.0*(1 << 15); >> > + a = 1.0*(1 << 16); >> > + a = __builtin_inff16 (); >> > + a = __builtin_nanf16 (""); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fli.h" 32 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli.c b/gcc/testsuite/gcc.target/riscv/zfa-fli.c >> > new file mode 100644 >> > index 00000000000..b6d41cf460f >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli.c >> > @@ -0,0 +1,79 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv64imafdc_zfa -mabi=lp64d -O0" } */ >> > + >> > +void foo_float32 () >> > +{ >> > + volatile float a; >> > + a = -1.0; >> > + a = 1.1754944e-38; >> > + a = 1.0/(1 << 16); >> > + a = 1.0/(1 << 15); >> > + a = 1.0/(1 << 8); >> > + a = 1.0/(1 << 7); >> > + a = 1.0/(1 << 4); >> > + a = 1.0/(1 << 3); >> > + a = 1.0/(1 << 2); >> > + a = 0.3125; >> > + a = 0.375; >> > + a = 0.4375; >> > + a = 0.5; >> > + a = 0.625; >> > + a = 0.75; >> > + a = 0.875; >> > + a = 1.0; >> > + a = 1.25; >> > + a = 1.5; >> > + a = 1.75; >> > + a = 2.0; >> > + a = 2.5; >> > + a = 3.0; >> > + a = 1.0*(1 << 2); >> > + a = 1.0*(1 << 3); >> > + a = 1.0*(1 << 4); >> > + a = 1.0*(1 << 7); >> > + a = 1.0*(1 << 8); >> > + a = 1.0*(1 << 15); >> > + a = 1.0*(1 << 16); >> > + a = __builtin_inff (); >> > + a = __builtin_nanf (""); >> > +} >> > + >> > +void foo_double64 () >> > +{ >> > + volatile double a; >> > + a = -1.0; >> > + a = 2.2250738585072014E-308; >> > + a = 1.0/(1 << 16); >> > + a = 1.0/(1 << 15); >> > + a = 1.0/(1 << 8); >> > + a = 1.0/(1 << 7); >> > + a = 1.0/(1 << 4); >> > + a = 1.0/(1 << 3); >> > + a = 1.0/(1 << 2); >> > + a = 0.3125; >> > + a = 0.375; >> > + a = 0.4375; >> > + a = 0.5; >> > + a = 0.625; >> > + a = 0.75; >> > + a = 0.875; >> > + a = 1.0; >> > + a = 1.25; >> > + a = 1.5; >> > + a = 1.75; >> > + a = 2.0; >> > + a = 2.5; >> > + a = 3.0; >> > + a = 1.0*(1 << 2); >> > + a = 1.0*(1 << 3); >> > + a = 1.0*(1 << 4); >> > + a = 1.0*(1 << 7); >> > + a = 1.0*(1 << 8); >> > + a = 1.0*(1 << 15); >> > + a = 1.0*(1 << 16); >> > + a = __builtin_inf (); >> > + a = __builtin_nan (""); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fli.s" 32 } } */ >> > +/* { dg-final { scan-assembler-times "fli.d" 32 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c b/gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c >> > new file mode 100644 >> > index 00000000000..5a52adce36a >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fmovh-fmovp-rv32.c >> > @@ -0,0 +1,10 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv32g_zfa -mabi=ilp32 -O0" } */ >> > + >> > +double foo(long long a) >> > +{ >> > + return (double)(a + 3); >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fmvp.d.x" 1 } } */ >> > +/* { dg-final { scan-assembler-times "fmvh.x.d" 1 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c b/gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c >> > new file mode 100644 >> > index 00000000000..b53601d6e1f >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fround-rv32.c >> > @@ -0,0 +1,42 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv32imafdc_zfa -mabi=ilp32d -O2" } */ >> > + >> > +extern float a; >> > +extern double b; >> > + >> > +void foo (float *x, double *y) >> > +{ >> > + { >> > + *x = __builtin_roundf (a); >> > + *y = __builtin_round (b); >> > + } >> > + { >> > + *x = __builtin_floorf (a); >> > + *y = __builtin_floor (b); >> > + } >> > + { >> > + *x = __builtin_ceilf (a); >> > + *y = __builtin_ceil (b); >> > + } >> > + { >> > + *x = __builtin_truncf (a); >> > + *y = __builtin_trunc (b); >> > + } >> > + { >> > + *x = __builtin_roundevenf (a); >> > + *y = __builtin_roundeven (b); >> > + } >> > + { >> > + *x = __builtin_nearbyintf (a); >> > + *y = __builtin_nearbyint (b); >> > + } >> > + { >> > + *x = __builtin_rintf (a); >> > + *y = __builtin_rint (b); >> > + } >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fround.s" 6 } } */ >> > +/* { dg-final { scan-assembler-times "fround.d" 6 } } */ >> > +/* { dg-final { scan-assembler-times "froundnx.s" 1 } } */ >> > +/* { dg-final { scan-assembler-times "froundnx.d" 1 } } */ >> > diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fround.c b/gcc/testsuite/gcc.target/riscv/zfa-fround.c >> > new file mode 100644 >> > index 00000000000..c10de82578e >> > --- /dev/null >> > +++ b/gcc/testsuite/gcc.target/riscv/zfa-fround.c >> > @@ -0,0 +1,42 @@ >> > +/* { dg-do compile } */ >> > +/* { dg-options "-march=rv64imafdc_zfa -mabi=lp64d -O2" } */ >> > + >> > +extern float a; >> > +extern double b; >> > + >> > +void foo (float *x, double *y) >> > +{ >> > + { >> > + *x = __builtin_roundf (a); >> > + *y = __builtin_round (b); >> > + } >> > + { >> > + *x = __builtin_floorf (a); >> > + *y = __builtin_floor (b); >> > + } >> > + { >> > + *x = __builtin_ceilf (a); >> > + *y = __builtin_ceil (b); >> > + } >> > + { >> > + *x = __builtin_truncf (a); >> > + *y = __builtin_trunc (b); >> > + } >> > + { >> > + *x = __builtin_roundevenf (a); >> > + *y = __builtin_roundeven (b); >> > + } >> > + { >> > + *x = __builtin_nearbyintf (a); >> > + *y = __builtin_nearbyint (b); >> > + } >> > + { >> > + *x = __builtin_rintf (a); >> > + *y = __builtin_rint (b); >> > + } >> > +} >> > + >> > +/* { dg-final { scan-assembler-times "fround.s" 6 } } */ >> > +/* { dg-final { scan-assembler-times "fround.d" 6 } } */ >> > +/* { dg-final { scan-assembler-times "froundnx.s" 1 } } */ >> > +/* { dg-final { scan-assembler-times "froundnx.d" 1 } } */ >> > -- >> > 2.17.1 >> >