From patchwork Mon Aug 14 05:32:10 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tsukasa OI X-Patchwork-Id: 1820845 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=pOvEyPHS; dkim-atps=neutral Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RPNN40KZMz1yfP for ; Mon, 14 Aug 2023 15:33:08 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0676A3857711 for ; Mon, 14 Aug 2023 05:33:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0676A3857711 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1691991186; bh=s4c2GJ4W7k5nWkZ69LmTeUdnMP04KwS3JKvmYbhkGxg=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=pOvEyPHSu81hw1yk012qfeTPvcbTQgkZjeqr6kiSOoLHvBN1mBigdd2bxfqXsOJso AhmpbQvVeG2PbWCrJ0OJG6CF3pLUa7ZwX4Pk4QxXsvgRAPV/gu5zYQ/Nz041l8m4TQ H8FIKW/wYfEVB5EqTjbY1Che0rm0vgz69JbdiLt4= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-sender-0.a4lg.com (mail-sender.a4lg.com [153.120.152.154]) by sourceware.org (Postfix) with ESMTPS id EEB9A3858D39 for ; Mon, 14 Aug 2023 05:32:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EEB9A3858D39 Received: from [127.0.0.1] (localhost [127.0.0.1]) by mail-sender-0.a4lg.com (Postfix) with ESMTPSA id 39960300089; Mon, 14 Aug 2023 05:32:40 +0000 (UTC) To: Tsukasa OI , Kito Cheng , Palmer Dabbelt , Andrew Waterman , Jim Wilson Cc: gcc-patches@gcc.gnu.org Subject: [PATCH 2/2] RISC-V: Constant FP Optimization with 'Zfa' Date: Mon, 14 Aug 2023 05:32:10 +0000 Message-ID: In-Reply-To: References: Mime-Version: 1.0 X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, GIT_PATCH_0, KAM_SHORT, LIKELY_SPAM_BODY, SPF_HELO_NONE, SPF_PASS, TXREP 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: , X-Patchwork-Original-From: Tsukasa OI via Gcc-patches From: Tsukasa OI Reply-To: Tsukasa OI Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" From: Tsukasa OI This commit implements an optimization for assignments from a FP constant to a FP register using a FLI instruction from the 'Zfa' extension. To this purpose, it adds the constraint "H" and adds hardfloat move instructions a "H -> f" variant. Because FLI instruction constraint is a bit complex, it adds the riscv_get_float_fli_const function to parse a floating point constant if appropriate and the validness is contained in its return value. It also modifies the cost model for floating point constants and implements simple yet bit-accurate printer for valid finite FLI constants. This optimization is partially based on AArch64 (vmov instruction handling). gcc/ChangeLog: * config/riscv/constraints.md (H): New. * config/riscv/riscv-protos.h (enum riscv_float_fli_const_type): New to identify the FLI constant type. (struct riscv_float_fli_const): New to represent an optional FLI constant. * config/riscv/riscv.cc (riscv_get_float_fli_const): New function to parse a CONST_DOUBLE and return optionally-valid FLI constant. (riscv_const_insns): Modify CONST_DOUBLE cost model. (riscv_output_move): Add FLI instruction outputs. (riscv_print_operand): Print a finite FLI constant as a hexadecimal FP representation or a string operand "min", "inf" or "nan". * config/riscv/riscv.md (movhf_hardfloat, movsf_hardfloat, movdf_hardfloat_rv32, movdf_hardfloat_rv64): Add "H" variant for 'Zfa' extension-based FP constant moves. gcc/testsuite/ChangeLog: * gcc.target/riscv/zfa-fli-1.c: New test. * gcc.target/riscv/zfa-fli-2.c: Ditto. * gcc.target/riscv/zfa-fli-3.c: Ditto. * gcc.target/riscv/zfa-fli-4.c: Ditto. * gcc.target/riscv/zfa-fli-5.c: Ditto. * gcc.target/riscv/zfa-fli-6.c: Ditto. * gcc.target/riscv/zfa-fli-7.c: Ditto. * gcc.target/riscv/zfa-fli-8.c: Ditto. --- gcc/config/riscv/constraints.md | 7 + gcc/config/riscv/riscv-protos.h | 34 +++ gcc/config/riscv/riscv.cc | 250 ++++++++++++++++++++- gcc/config/riscv/riscv.md | 24 +- gcc/testsuite/gcc.target/riscv/zfa-fli-1.c | 24 ++ gcc/testsuite/gcc.target/riscv/zfa-fli-2.c | 24 ++ gcc/testsuite/gcc.target/riscv/zfa-fli-3.c | 14 ++ gcc/testsuite/gcc.target/riscv/zfa-fli-4.c | 111 +++++++++ gcc/testsuite/gcc.target/riscv/zfa-fli-5.c | 98 ++++++++ gcc/testsuite/gcc.target/riscv/zfa-fli-6.c | 61 +++++ gcc/testsuite/gcc.target/riscv/zfa-fli-7.c | 30 +++ gcc/testsuite/gcc.target/riscv/zfa-fli-8.c | 39 ++++ 12 files changed, 692 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-5.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-6.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-7.c create mode 100644 gcc/testsuite/gcc.target/riscv/zfa-fli-8.c diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md index 44525b2da491..d57c72ef14f0 100644 --- a/gcc/config/riscv/constraints.md +++ b/gcc/config/riscv/constraints.md @@ -98,6 +98,13 @@ (and (match_code "const_double") (match_test "op == CONST0_RTX (mode)"))) +;; Floating-point constant that can be generated by a FLI instruction +;; in the 'Zfa' standard extension. +(define_constraint "H" + "@internal" + (and (match_code "const_double") + (match_test "riscv_get_float_fli_const (op).valid"))) + (define_memory_constraint "A" "An address that is held in a general-purpose register." (and (match_code "mem") diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 2fbed04ff84c..6effa2437251 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -80,6 +80,39 @@ struct riscv_address_info { enum riscv_symbol_type symbol_type; }; +/* Classifies a floating point constant possibly retrieved by + the FLI instructions. + + RISCV_FLOAT_CONST_MIN + The minimum positive normal value for given mode. + + RISCV_FLOAT_CONST_INF + Positive infinity. + + RISCV_FLOAT_CONST_NAN + Canonical NaN (positive, quiet and zero payload NaN). + + RISCV_FLOAT_CONST_FINITE + A finite number. */ +enum riscv_float_fli_const_type { + RISCV_FLOAT_CONST_MIN, + RISCV_FLOAT_CONST_INF, + RISCV_FLOAT_CONST_NAN, + RISCV_FLOAT_CONST_FINITE, +}; + +/* Information about a floating point constant possibly retrieved by + the FLI instructions. */ +struct riscv_float_fli_const { + bool valid: 1; + bool sign: 1; + enum riscv_float_fli_const_type type: 2; + /* Highest 2 bits of IEEE754 mantissa on RISCV_FLOAT_CONST_FINITE. */ + unsigned int mantissa_below_point: 2; + /* IEEE754 normal exponent - 16 on RISCV_FLOAT_CONST_FINITE. */ + unsigned int biased_exponent: 6; +}; + /* 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 *); @@ -125,6 +158,7 @@ extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *); extern bool riscv_gpr_save_operation_p (rtx); extern void riscv_reinit (void); extern poly_uint64 riscv_regmode_natural_size (machine_mode); +extern struct riscv_float_fli_const riscv_get_float_fli_const (rtx); extern bool riscv_v_ext_vector_mode_p (machine_mode); extern bool riscv_v_ext_tuple_mode_p (machine_mode); extern bool riscv_v_ext_vls_mode_p (machine_mode); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index f9b7a9ee749f..a8c13b014130 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -812,6 +812,185 @@ riscv_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) return riscv_const_insns (x) > 0; } +/* Check and generate information corresponding a floating point constant + that can be generated from a FLI instruction. */ + +struct riscv_float_fli_const +riscv_get_float_fli_const (rtx x) +{ + struct riscv_float_fli_const result = { + false, false, RISCV_FLOAT_CONST_FINITE, 0, 0 + }; + REAL_VALUE_TYPE r, m; + + if (!TARGET_HARD_FLOAT || !TARGET_ZFA) + return result; + switch (GET_MODE (x)) + { + case HFmode: + /* Not only 'Zfhmin', either 'Zfh' or 'Zvfh' is required. */ + if (!TARGET_ZFH && !TARGET_ZVFH) + return result; + break; + case SFmode: break; + case DFmode: break; + default: return result; + } + + if (!CONST_DOUBLE_P (x)) + return result; + + r = *CONST_DOUBLE_REAL_VALUE (x); + + if (REAL_VALUE_ISNAN (r)) + { + long reprs[2] = { 0 }; + /* Compare with canonical NaN. */ + switch (GET_MODE (x)) + { + case HFmode: + reprs[0] = real_to_target (NULL, &r, + float_mode_for_size (16).require ()); + /* 0x7e00: Canonical NaN for binary16. */ + if (reprs[0] != 0x7e00) + return result; + break; + case SFmode: + reprs[0] = real_to_target (NULL, &r, + float_mode_for_size (32).require ()); + /* 0x7fc00000: Canonical NaN for binary32. */ + if (reprs[0] != 0x7fc00000) + return result; + break; + case DFmode: + real_to_target (reprs, &r, float_mode_for_size (64).require ()); + if (FLOAT_WORDS_BIG_ENDIAN) + std::swap (reprs[0], reprs[1]); + /* 0x7ff80000_00000000: Canonical NaN for binary64. */ + if (reprs[0] != 0 || reprs[1] != 0x7ff80000) + return result; + break; + default: + gcc_unreachable (); + } + result.type = RISCV_FLOAT_CONST_NAN; + result.valid = true; + return result; + } + else if (REAL_VALUE_ISINF (r)) + { + if (REAL_VALUE_NEGATIVE (r)) + return result; + result.type = RISCV_FLOAT_CONST_INF; + result.valid = true; + return result; + } + + bool sign = REAL_VALUE_NEGATIVE (r); + result.sign = sign; + + r = real_value_abs (&r); + /* GCC internally does not use IEEE754-like encoding (where normalized + significands are in the range [1, 2). GCC uses [0.5, 1) (see real.cc). + So, this exponent_p1 variable equals IEEE754 unbiased exponent + 1. */ + int exponent_p1 = REAL_EXP (&r); + + /* For the mantissa, we expand into two HOST_WIDE_INTS, apart from the + highest (sign) bit, with a fixed binary point at bit point_pos. + m1 holds the low part of the mantissa, m2 the high part. + WARNING: If we ever have a representation using more than 2 * H_W_I - 1 + bits for the mantissa, this can fail (low bits will be lost). */ + bool fail = false; + real_ldexp (&m, &r, (2 * HOST_BITS_PER_WIDE_INT - 1) - exponent_p1); + wide_int w = real_to_integer (&m, &fail, HOST_BITS_PER_WIDE_INT * 2); + if (fail) + return result; + + /* If the low part of the mantissa has bits set we cannot represent + the value. */ + if (w.ulow () != 0) + return result; + /* We have rejected the lower HOST_WIDE_INT, so update our + understanding of how many bits lie in the mantissa and + look only at the high HOST_WIDE_INT. */ + unsigned HOST_WIDE_INT mantissa = w.elt (1); + + /* We cannot represent the value 0.0. */ + if (mantissa == 0) + return result; + + /* We can only represent values with a mantissa of the form 1.xx. */ + unsigned HOST_WIDE_INT mask + = ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 4)) - 1; + if ((mantissa & mask) != 0) + return result; + mantissa >>= HOST_BITS_PER_WIDE_INT - 4; + /* Now the lowest 3-bits of mantissa should form (1.xx)b. */ + gcc_assert (mantissa & (1u << 2)); + /* Mask out the highest bit. */ + mantissa &= ~(1u << 2); + + if (mantissa == 0) + { + /* We cannot represent any values but -1.0. */ + if (exponent_p1 != 1 && sign) + return result; + switch (exponent_p1) + { + case -15: /* 1.0 * 2^(-16) */ + case -14: /* 1.0 * 2^(-15) */ + case -7: /* 1.0 * 2^(- 8) */ + case -6: /* 1.0 * 2^(- 7) */ + case 8: /* 1.0 * 2^(+ 7) */ + case 9: /* 1.0 * 2^(+ 8) */ + case 16: /* 1.0 * 2^(+15) */ + case 17: /* 1.0 * 2^(+16) */ + break; + default: + if (exponent_p1 >= -3 && exponent_p1 <= 5) + /* 1.0 * 2^[-4,4] */ + break; + switch (GET_MODE (x)) + { + case HFmode: /* IEEE 754 binary16. */ + /* Minimum positive normal == 1.0 * 2^(-14) */ + if (exponent_p1 != -13) return result; + break; + case SFmode: /* IEEE 754 binary32. */ + /* Minimum positive normal == 1.0 * 2^(-126) */ + if (exponent_p1 != -125) return result; + break; + case DFmode: /* IEEE 754 binary64. */ + /* Minimum positive normal == 1.0 * 2^(-1022) */ + if (exponent_p1 != -1021) return result; + break; + default: + gcc_unreachable (); + } + result.type = RISCV_FLOAT_CONST_MIN; + result.valid = true; + return result; + } + } + else + { + if (sign) + return result; + if (exponent_p1 < -1 || exponent_p1 > 2) + return result; + /* The value is (+1.xx)b * 2^[-2,1]. + But we cannot represent (+1.11)b * 2^1 (that is 3.5). */ + if (exponent_p1 == 2 && mantissa == 3) + return result; + } + + result.valid = true; + result.mantissa_below_point = mantissa; + result.biased_exponent = exponent_p1 + 15; + + return result; +} + /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ static bool @@ -1322,8 +1501,12 @@ riscv_const_insns (rtx x) } case CONST_DOUBLE: - /* We can use x0 to load floating-point zero. */ - return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; + /* We can use x0 to load floating-point zero. + We also have FLI instructions when the Zfa extension is enabled. */ + return x == CONST0_RTX (GET_MODE (x)) ? 1 + : riscv_get_float_fli_const (x).valid ? 1 + : 0; + case CONST_VECTOR: { /* TODO: This is not accurate, we will need to @@ -1362,17 +1545,14 @@ riscv_const_insns (rtx x) constant incurs a literal-pool access. Allow this in order to increase vectorization possibilities. */ int n = riscv_const_insns (elt); - if (CONST_DOUBLE_P (elt)) - return 1 + 4; /* vfmv.v.f + memory access. */ + /* We need as many insns as it takes to load the constant + into a GPR and one vmv.v.x. */ + if (n != 0) + return 1 + n; + else if (CONST_DOUBLE_P (elt)) + return 1 + 4; /* vfmv.v.f + memory access. */ else - { - /* We need as many insns as it takes to load the constant - into a GPR and one vmv.v.x. */ - if (n != 0) - return 1 + n; - else - return 1 + 4; /*vmv.v.x + memory access. */ - } + return 1 + 4; /* vmv.v.x + memory access. */ } } @@ -3196,6 +3376,22 @@ riscv_output_move (rtx dest, rtx src) gcc_assert (known_eq (rtx_to_poly_int64 (src), BYTES_PER_RISCV_VECTOR)); return "csrr\t%0,vlenb"; } + if (dest_code == REG && src_code == CONST_DOUBLE) + { + struct riscv_float_fli_const flt = riscv_get_float_fli_const (src); + if (flt.valid) + { + 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"; + } + } + } gcc_unreachable (); } @@ -5117,6 +5313,36 @@ riscv_print_operand (FILE *file, rtx op, int letter) output_address (mode, XEXP (op, 0)); break; + case CONST_DOUBLE: + { + struct riscv_float_fli_const flt = riscv_get_float_fli_const (op); + if (flt.valid) + { + switch (flt.type) + { + case RISCV_FLOAT_CONST_MIN: + fputs ("min", file); + break; + case RISCV_FLOAT_CONST_INF: + fputs ("inf", file); + break; + case RISCV_FLOAT_CONST_NAN: + fputs ("nan", file); + break; + default: + /* Use simpler (and bit-perfect) printer. */ + if (flt.sign) + fputc ('-', file); + fprintf (file, "0x1.%cp%+d", + "048c"[flt.mantissa_below_point], + (int) flt.biased_exponent - 16); + break; + } + break; + } + } + /* Fall through. */ + default: if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) fputs (reg_names[GP_REG_FIRST], file); diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index b456fa6abb3c..ce73db33830d 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1744,13 +1744,13 @@ }) (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,G,H,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,mtc,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") (set_attr "mode" "HF")]) (define_insn "*movhf_softfloat" @@ -2075,13 +2075,13 @@ }) (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,G,H,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,mtc,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") (set_attr "mode" "SF")]) (define_insn "*movsf_softfloat" @@ -2109,23 +2109,23 @@ ;; 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,G,H,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,mtc,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,G,H,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,mtc,mtc,fpload,fpstore,store,mtc,mfc,move,load,store") (set_attr "mode" "DF")]) (define_insn "*movdf_softfloat" diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-1.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-1.c new file mode 100644 index 000000000000..35ea5c477676 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imfd_zfa -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32imfd_zfa -mabi=ilp32d" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os" "-Og" "-Oz"} } */ + +#ifndef __riscv_zfa +#error Feature macro not defined +#endif + +double +foo_positive_d (double a) +{ + /* Use 3 FLI FP constants. */ + return (2.5 * a - 1.0) / 0.875; +} + +float +foo_positive_s (float a) +{ + return ((float) 2.5 * a - (float) 1.0) / (float) 0.875; +} + +/* { dg-final { scan-assembler-times "fli\\.s\t" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.d\t" 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-2.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-2.c new file mode 100644 index 000000000000..10d49d116e46 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imfd_zfa -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32imfd_zfa -mabi=ilp32d" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Os" "-Og" "-Oz"} } */ + +#ifndef __riscv_zfa +#error Feature macro not defined +#endif + +double +foo_negative_d (double a) +{ + /* Use 3 "non-FLI" FP constants. */ + return (3.5 * a - 5.0) / 0.1875; +} + +float +foo_negative_s (float a) +{ + return ((float) 3.5 * a - (float) 5.0) / (float) 0.1875; +} + +/* { dg-final { scan-assembler-not "fli\\.s\t" } } */ +/* { dg-final { scan-assembler-not "fli\\.d\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-3.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-3.c new file mode 100644 index 000000000000..6d069b2a4a9c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imfd_zfa -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32imfd_zfa -mabi=ilp32d" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os" "-Og" "-Oz"} } */ + +double +foo_positive_s (float a) +{ + /* Use 3 FLI FP constants (but type conversion occur in the middle). */ + return (2.5f * a - 1.0) / 0.875; +} + +/* { dg-final { scan-assembler-times "fli\\.s\t" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.d\t" 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-4.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-4.c new file mode 100644 index 000000000000..153853efb196 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-4.c @@ -0,0 +1,111 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imfd_zfa_zfh -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32imfd_zfa_zfh -mabi=ilp32d" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Oz"} } */ + +#define TYPE_h _Float16 +#define TYPE_s float +#define TYPE_d double + +#define DECL_TYPE(TYPE_SHORT) TYPE_##TYPE_SHORT + +#define DECL_FUNC(TYPE_SHORT, N, VALUE) \ + DECL_TYPE (TYPE_SHORT) const_##TYPE_SHORT##_##N (void) \ + { \ + return VALUE; \ + } + +#define DECL_FINITE_FUNCS(TYPE_SHORT) \ + DECL_FUNC (TYPE_SHORT, 00, -1) \ + DECL_FUNC (TYPE_SHORT, 02, 0.0000152587890625) \ + DECL_FUNC (TYPE_SHORT, 03, 0.000030517578125) \ + DECL_FUNC (TYPE_SHORT, 04, 0.00390625) \ + DECL_FUNC (TYPE_SHORT, 05, 0.0078125) \ + DECL_FUNC (TYPE_SHORT, 06, 0.0625) \ + DECL_FUNC (TYPE_SHORT, 07, 0.125) \ + DECL_FUNC (TYPE_SHORT, 08, 0.25) \ + DECL_FUNC (TYPE_SHORT, 09, 0.3125) \ + DECL_FUNC (TYPE_SHORT, 10, 0.375) \ + DECL_FUNC (TYPE_SHORT, 11, 0.4375) \ + DECL_FUNC (TYPE_SHORT, 12, 0.5) \ + DECL_FUNC (TYPE_SHORT, 13, 0.625) \ + DECL_FUNC (TYPE_SHORT, 14, 0.75) \ + DECL_FUNC (TYPE_SHORT, 15, 0.875) \ + DECL_FUNC (TYPE_SHORT, 16, 1) \ + DECL_FUNC (TYPE_SHORT, 17, 1.25) \ + DECL_FUNC (TYPE_SHORT, 18, 1.5) \ + DECL_FUNC (TYPE_SHORT, 19, 1.75) \ + DECL_FUNC (TYPE_SHORT, 20, 2) \ + DECL_FUNC (TYPE_SHORT, 21, 2.5) \ + DECL_FUNC (TYPE_SHORT, 22, 3) \ + DECL_FUNC (TYPE_SHORT, 23, 4) \ + DECL_FUNC (TYPE_SHORT, 24, 8) \ + DECL_FUNC (TYPE_SHORT, 25, 16) \ + DECL_FUNC (TYPE_SHORT, 26, 128) \ + DECL_FUNC (TYPE_SHORT, 27, 256) \ + DECL_FUNC (TYPE_SHORT, 28, 32768) \ + DECL_FUNC (TYPE_SHORT, 29, 65536) + +/* Finite numbers (except 2^16 in _Float16, making an inf). */ +DECL_FINITE_FUNCS (h) +DECL_FINITE_FUNCS (s) +DECL_FINITE_FUNCS (d) + +/* min. */ +DECL_FUNC (h, 01, __FLT16_MIN__) +DECL_FUNC (s, 01, __FLT_MIN__) +DECL_FUNC (d, 01, __DBL_MIN__) + +/* inf. */ +DECL_FUNC (h, 30, __builtin_inff16 ()) +DECL_FUNC (s, 30, __builtin_inff ()) +DECL_FUNC (d, 30, __builtin_inf ()) + +/* nan. */ +DECL_FUNC (h, 31, __builtin_nanf16 ("")) +DECL_FUNC (s, 31, __builtin_nanf ("")) +DECL_FUNC (d, 31, __builtin_nan ("")) + + +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,-0x1\\.0p\\+0\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-16\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-15\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-8\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-7\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-4\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-3\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-2\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.4p-2\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.8p-2\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.cp-2\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p-1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.4p-1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.8p-1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.cp-1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+0\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.4p\\+0\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.8p\\+0\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.cp\\+0\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.4p\\+1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.8p\\+1\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+2\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+3\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+4\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+7\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+8\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,0x1\\.0p\\+15\n" 3 } } */ +/* { dg-final { scan-assembler-times "fli\\.\[sd]\tfa0,0x1\\.0p\\+16\n" 2 } } */ + +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,min\n" 3 } } */ + +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,inf\n" 2 } } */ +/* { dg-final { scan-assembler-times "fli\\.s\tfa0,inf\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.d\tfa0,inf\n" 1 } } */ + +/* { dg-final { scan-assembler-times "fli\\.\[hsd]\tfa0,nan\n" 3 } } */ + + +/* { dg-final { scan-assembler-times "fli\\.h\tfa0," 32 } } */ +/* { dg-final { scan-assembler-times "fli\\.s\tfa0," 32 } } */ +/* { dg-final { scan-assembler-times "fli\\.d\tfa0," 32 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-5.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-5.c new file mode 100644 index 000000000000..186f91ffb349 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-5.c @@ -0,0 +1,98 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imf_zfa_zvfh -mabi=lp64f" { target { rv64 } } } */ +/* { dg-options "-march=rv32imf_zfa_zvfh -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Oz"} } */ + +/* Even if 'Zfh' is disabled, "fli.h" is usable when + both 'Zfa' and 'Zvfh' are available. */ +#ifdef __riscv_zfh +#error Invalid feature macro defined +#endif + +#define TYPE_h _Float16 + +#define DECL_TYPE(TYPE_SHORT) TYPE_##TYPE_SHORT + +#define DECL_FUNC(TYPE_SHORT, N, VALUE) \ + DECL_TYPE (TYPE_SHORT) const_##TYPE_SHORT##_##N (void) \ + { \ + return VALUE; \ + } + +#define DECL_FINITE_FUNCS(TYPE_SHORT) \ + DECL_FUNC (TYPE_SHORT, 00, -1) \ + DECL_FUNC (TYPE_SHORT, 02, 0.0000152587890625) \ + DECL_FUNC (TYPE_SHORT, 03, 0.000030517578125) \ + DECL_FUNC (TYPE_SHORT, 04, 0.00390625) \ + DECL_FUNC (TYPE_SHORT, 05, 0.0078125) \ + DECL_FUNC (TYPE_SHORT, 06, 0.0625) \ + DECL_FUNC (TYPE_SHORT, 07, 0.125) \ + DECL_FUNC (TYPE_SHORT, 08, 0.25) \ + DECL_FUNC (TYPE_SHORT, 09, 0.3125) \ + DECL_FUNC (TYPE_SHORT, 10, 0.375) \ + DECL_FUNC (TYPE_SHORT, 11, 0.4375) \ + DECL_FUNC (TYPE_SHORT, 12, 0.5) \ + DECL_FUNC (TYPE_SHORT, 13, 0.625) \ + DECL_FUNC (TYPE_SHORT, 14, 0.75) \ + DECL_FUNC (TYPE_SHORT, 15, 0.875) \ + DECL_FUNC (TYPE_SHORT, 16, 1) \ + DECL_FUNC (TYPE_SHORT, 17, 1.25) \ + DECL_FUNC (TYPE_SHORT, 18, 1.5) \ + DECL_FUNC (TYPE_SHORT, 19, 1.75) \ + DECL_FUNC (TYPE_SHORT, 20, 2) \ + DECL_FUNC (TYPE_SHORT, 21, 2.5) \ + DECL_FUNC (TYPE_SHORT, 22, 3) \ + DECL_FUNC (TYPE_SHORT, 23, 4) \ + DECL_FUNC (TYPE_SHORT, 24, 8) \ + DECL_FUNC (TYPE_SHORT, 25, 16) \ + DECL_FUNC (TYPE_SHORT, 26, 128) \ + DECL_FUNC (TYPE_SHORT, 27, 256) \ + DECL_FUNC (TYPE_SHORT, 28, 32768) \ + DECL_FUNC (TYPE_SHORT, 29, 65536) + +/* Finite numbers (except 2^16 in _Float16, making an inf). */ +DECL_FINITE_FUNCS (h) + +/* min. */ +DECL_FUNC (h, 01, __FLT16_MIN__) + +/* inf. */ +DECL_FUNC (h, 30, __builtin_inff16 ()) + + +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,-0x1\\.0p\\+0\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-16\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-15\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-8\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-7\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-4\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-3\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-2\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.4p-2\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.8p-2\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.cp-2\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p-1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.4p-1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.8p-1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.cp-1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+0\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.4p\\+0\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.8p\\+0\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.cp\\+0\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.4p\\+1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.8p\\+1\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+2\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+3\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+4\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+7\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+8\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,0x1\\.0p\\+15\n" 1 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,inf\n" 2 } } */ +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,min\n" 1 } } */ + + +/* nan. */ +DECL_FUNC (h, 31, __builtin_nanf16 ("")) + +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,nan\n" 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-6.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-6.c new file mode 100644 index 000000000000..2ee830d5c14c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-6.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imf_zfa_zfhmin -mabi=lp64f" { target { rv64 } } } */ +/* { dg-options "-march=rv32imf_zfa_zfhmin -mabi=ilp32f" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Oz"} } */ + +/* "fli.h" is unavailable even if both 'Zfa' and 'Zfhmin' is enabled. */ + +#define TYPE_h _Float16 + +#define DECL_TYPE(TYPE_SHORT) TYPE_##TYPE_SHORT + +#define DECL_FUNC(TYPE_SHORT, N, VALUE) \ + DECL_TYPE (TYPE_SHORT) const_##TYPE_SHORT##_##N (void) \ + { \ + return VALUE; \ + } + +#define DECL_FINITE_FUNCS(TYPE_SHORT) \ + DECL_FUNC (TYPE_SHORT, 00, -1) \ + DECL_FUNC (TYPE_SHORT, 02, 0.0000152587890625) \ + DECL_FUNC (TYPE_SHORT, 03, 0.000030517578125) \ + DECL_FUNC (TYPE_SHORT, 04, 0.00390625) \ + DECL_FUNC (TYPE_SHORT, 05, 0.0078125) \ + DECL_FUNC (TYPE_SHORT, 06, 0.0625) \ + DECL_FUNC (TYPE_SHORT, 07, 0.125) \ + DECL_FUNC (TYPE_SHORT, 08, 0.25) \ + DECL_FUNC (TYPE_SHORT, 09, 0.3125) \ + DECL_FUNC (TYPE_SHORT, 10, 0.375) \ + DECL_FUNC (TYPE_SHORT, 11, 0.4375) \ + DECL_FUNC (TYPE_SHORT, 12, 0.5) \ + DECL_FUNC (TYPE_SHORT, 13, 0.625) \ + DECL_FUNC (TYPE_SHORT, 14, 0.75) \ + DECL_FUNC (TYPE_SHORT, 15, 0.875) \ + DECL_FUNC (TYPE_SHORT, 16, 1) \ + DECL_FUNC (TYPE_SHORT, 17, 1.25) \ + DECL_FUNC (TYPE_SHORT, 18, 1.5) \ + DECL_FUNC (TYPE_SHORT, 19, 1.75) \ + DECL_FUNC (TYPE_SHORT, 20, 2) \ + DECL_FUNC (TYPE_SHORT, 21, 2.5) \ + DECL_FUNC (TYPE_SHORT, 22, 3) \ + DECL_FUNC (TYPE_SHORT, 23, 4) \ + DECL_FUNC (TYPE_SHORT, 24, 8) \ + DECL_FUNC (TYPE_SHORT, 25, 16) \ + DECL_FUNC (TYPE_SHORT, 26, 128) \ + DECL_FUNC (TYPE_SHORT, 27, 256) \ + DECL_FUNC (TYPE_SHORT, 28, 32768) \ + DECL_FUNC (TYPE_SHORT, 29, 65536) + +/* Finite numbers (except 2^16 in _Float16, making an inf). */ +DECL_FINITE_FUNCS (h) + +/* min. */ +DECL_FUNC (h, 01, __FLT16_MIN__) + +/* inf. */ +DECL_FUNC (h, 30, __builtin_inff16 ()) + +/* nan. */ +DECL_FUNC (h, 31, __builtin_nanf16 ("")) + +/* { dg-final { scan-assembler-not "fli\\.h\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-7.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-7.c new file mode 100644 index 000000000000..4da8a2985852 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-7.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imfd_zfa_zfh -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32imfd_zfa_zfh -mabi=ilp32d" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Oz"} } */ + +/* Canonical NaN is, positive, quiet NaN with zero payload. */ + +#define TYPE_h _Float16 +#define TYPE_s float +#define TYPE_d double + +#define DECL_TYPE(TYPE_SHORT) TYPE_##TYPE_SHORT + +#define DECL_FUNC(TYPE_SHORT, N, VALUE) \ + DECL_TYPE (TYPE_SHORT) const_##TYPE_SHORT##_##N (void) \ + { \ + return VALUE; \ + } + +/* Canonical NaN. */ +DECL_FUNC (h, 1, __builtin_nanf16 ("")) +DECL_FUNC (s, 1, __builtin_nanf ("")) +DECL_FUNC (d, 1, __builtin_nan ("")) +DECL_FUNC (h, 2, __builtin_nanf16 ("0")) +DECL_FUNC (s, 2, __builtin_nanf ("0")) +DECL_FUNC (d, 2, __builtin_nan ("0")) + +/* { dg-final { scan-assembler-times "fli\\.h\tfa0,nan\n" 2 } } */ +/* { dg-final { scan-assembler-times "fli\\.s\tfa0,nan\n" 2 } } */ +/* { dg-final { scan-assembler-times "fli\\.d\tfa0,nan\n" 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zfa-fli-8.c b/gcc/testsuite/gcc.target/riscv/zfa-fli-8.c new file mode 100644 index 000000000000..a09726c0cb59 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zfa-fli-8.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imfd_zfa_zfh -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32imfd_zfa_zfh -mabi=ilp32d" { target { rv32 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Og" "-Oz"} } */ + +/* Canonical NaN is, positive, quiet NaN with zero payload. */ + +#define TYPE_h _Float16 +#define TYPE_s float +#define TYPE_d double + +#define DECL_TYPE(TYPE_SHORT) TYPE_##TYPE_SHORT + +#define DECL_FUNC(TYPE_SHORT, N, VALUE) \ + DECL_TYPE (TYPE_SHORT) const_##TYPE_SHORT##_##N (void) \ + { \ + return VALUE; \ + } + +/* Non-canonical NaN. */ +DECL_FUNC (h, 1, __builtin_nansf16 ("")) +DECL_FUNC (s, 1, __builtin_nansf ("")) +DECL_FUNC (d, 1, __builtin_nans ("")) +DECL_FUNC (h, 2, __builtin_nansf16 ("0")) +DECL_FUNC (s, 2, __builtin_nansf ("0")) +DECL_FUNC (d, 2, __builtin_nans ("0")) +DECL_FUNC (h, 3, __builtin_nanf16 ("1")) +DECL_FUNC (s, 3, __builtin_nanf ("1")) +DECL_FUNC (d, 3, __builtin_nan ("1")) +DECL_FUNC (h, 4, __builtin_nansf16 ("1")) +DECL_FUNC (s, 4, __builtin_nansf ("1")) +DECL_FUNC (d, 4, __builtin_nans ("1")) + +/* Canonical NaN, negated (making it non-canonical). */ +DECL_FUNC (h, 5, -__builtin_nanf16 ("")) +DECL_FUNC (s, 5, -__builtin_nanf ("")) +DECL_FUNC (d, 5, -__builtin_nan ("")) + +/* { dg-final { scan-assembler-not "fli\\.\[hsd]\tfa0,nan\n" } } */