From patchwork Tue May 31 08:50:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "juzhe.zhong@rivai.ai" X-Patchwork-Id: 54552 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 E4314383665B for ; Tue, 31 May 2022 08:57:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtpproxy21.qq.com (smtpbg704.qq.com [203.205.195.105]) by sourceware.org (Postfix) with ESMTPS id DFC9E3834E42 for ; Tue, 31 May 2022 08:50:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DFC9E3834E42 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivai.ai Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivai.ai X-QQ-mid: bizesmtp84t1653987049tpqjlloa Received: from server1.localdomain ( [42.247.22.65]) by bizesmtp.qq.com (ESMTP) with id ; Tue, 31 May 2022 16:50:48 +0800 (CST) X-QQ-SSF: 01400000002000B0F000000A0000000 X-QQ-FEAT: 6NsApsECK7dIatawgx6zpbI/wg1LOv9YzPFZ/a3SgirnFCgf06ifvKN3RXUqU pxEV+lTBq5zXpEcANtllYnCZzUomJnYgy94Vj0aIcJPIcslxpJg3yhA+SBaLxndnY42uDqd avOulvwHlytERxaaZH5PBySeqZzkrcEDOmhT4NaYcNo/96AfBIdDHSp82Av/IJ/KjckCHHu j4orpd+jMx9ZXIwcxcwCjCi0DCyM8QaUJGInnHaW/5zkluHWPDEft7DazBRgGPBmLw0z+mK OutSZlkuJGtxnk5CHH/kOahrpyVEd8RUmWQhuqXx9Pc3WPp+6AhYLrOWREQSSOtnsG1KKLg D8g2F/KpPMd33a1wQBeXSbpmv8nsVIAzvkUU5tjsTlSzA+OwGk= X-QQ-GoodBg: 2 From: juzhe.zhong@rivai.ai To: gcc-patches@gcc.gnu.org Subject: [PATCH 11/21] Add calling function support Date: Tue, 31 May 2022 16:50:02 +0800 Message-Id: <20220531085012.269719-12-juzhe.zhong@rivai.ai> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220531085012.269719-1-juzhe.zhong@rivai.ai> References: <20220531085012.269719-1-juzhe.zhong@rivai.ai> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybgforeign:qybgforeign8 X-QQ-Bgrelay: 1 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, 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@gmail.com, juzhe.zhong@rivai.ai Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: zhongjuzhe gcc/ChangeLog: * config/riscv/riscv.cc (struct riscv_arg_info): Add calling convention support. (riscv_get_arg_info): Add calling convention support. (riscv_function_arg_advance): Add calling convention support. (riscv_pass_by_reference): Add calling convention support. * config/riscv/riscv.h (GCC_RISCV_H): include . (V_RETURN): New macro define. (MAX_ARGS_IN_VECTOR_REGISTERS): New macro define. (MAX_ARGS_IN_MASK_REGISTERS): New macro define. (V_ARG_FIRST): New macro define. (V_ARG_LAST): New macro define. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/custom/calling_convention_1.c: New test. * gcc.target/riscv/rvv/custom/rvv-custom.exp: New test. --- gcc/config/riscv/riscv.cc | 90 +++++++++++++++++++ gcc/config/riscv/riscv.h | 14 +++ .../riscv/rvv/custom/calling_convention_1.c | 46 ++++++++++ .../riscv/rvv/custom/rvv-custom.exp | 47 ++++++++++ 4 files changed, 197 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/custom/calling_convention_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/custom/rvv-custom.exp diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index e88057e992a..832c1754002 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -181,6 +181,18 @@ struct riscv_arg_info { /* The offset of the first register used, provided num_fprs is nonzero. */ unsigned int fpr_offset; + + /* The number of vector registers allocated to this argument. */ + unsigned int num_vrs; + + /* The offset of the first register used, provided num_vrs is nonzero. */ + unsigned int vr_offset; + + /* The number of mask registers allocated to this argument. */ + unsigned int num_mrs; + + /* The offset of the first register used, provided num_mrs is nonzero. */ + unsigned int mr_offset; }; /* Information about an address described by riscv_address_type. @@ -3225,11 +3237,13 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum, unsigned num_bytes, num_words; unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST; unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST; + unsigned vr_base = return_p ? V_RETURN : V_ARG_FIRST; unsigned alignment = riscv_function_arg_boundary (mode, type); memset (info, 0, sizeof (*info)); info->gpr_offset = cum->num_gprs; info->fpr_offset = cum->num_fprs; + info->mr_offset = cum->num_mrs; if (named) { @@ -3292,6 +3306,67 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum, gregno, TYPE_MODE (fields[1].type), fields[1].offset); } + /* Pass vectors in VRs. For the argument contain scalable vectors, + for example: foo (vint8m1_t a), we pass this in VRs to reduce + redundant register spills. The maximum vector arg registers is + MAX_ARGS_IN_VECTOR_REGISTERS. */ + if (rvv_mode_p (mode)) + { + /* For return vector register, we use V_RETURN as default. */ + if (return_p) + { + if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL) + return gen_rtx_REG (mode, V_REG_FIRST); + else + return gen_rtx_REG (mode, vr_base); + } + /* The first mask register in argument we use is v0, the res of them + we use v8,v9,.....etc same as vector registers. */ + if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL) + { + info->num_mrs = 1; + + if (info->mr_offset + info->num_mrs <= MAX_ARGS_IN_MASK_REGISTERS) + return gen_rtx_REG (mode, V_REG_FIRST); + } + /* The number of vectors to pass in the function arg. + When the mode size is less than a full vector, we + use 1 vector to pass. */ + int nvecs; + nvecs = known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR) ? 1 : + exact_div (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR).to_constant (); + int align = rvv_regsize (mode); + for (int i = 0; i + nvecs <= MAX_ARGS_IN_VECTOR_REGISTERS; i += 1) + { + if (!cum->used_vrs[i] && (i + 8) % align == 0) + { + bool find_space = true; + int j = 1; + for (; j < nvecs; j += 1) + { + if (cum->used_vrs[i + j]) + { + find_space = false; + break; + } + } + if (find_space) + { + info->num_vrs = nvecs; + info->vr_offset = i; + return gen_rtx_REG(mode, vr_base + i); + } + else + { + /* skip the j num registers which can not be used */ + i += j; + } + } + } + info->num_vrs = 0; + info->num_mrs = 0; + return NULL_RTX; + } } /* Work out the size of the argument. */ @@ -3344,6 +3419,15 @@ riscv_function_arg_advance (cumulative_args_t cum_v, argument on the stack. */ cum->num_fprs = info.fpr_offset + info.num_fprs; cum->num_gprs = info.gpr_offset + info.num_gprs; + if (info.num_vrs > 0) + { + for (unsigned int i = 0; i < info.num_vrs; i += 1) + { + /* set current used vector registers */ + cum->used_vrs[info.vr_offset + i] = true; + } + } + cum->num_mrs = info.mr_offset + info.num_mrs; } /* Implement TARGET_ARG_PARTIAL_BYTES. */ @@ -3401,6 +3485,12 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg) /* Don't pass by reference if we can use a floating-point register. */ riscv_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false); if (info.num_fprs) + return false; + /* Don't pass by reference if we can use a RVV vector register. */ + if (info.num_vrs) + return false; + /* Don't pass by reference if we can use a RVV mask register. */ + if (info.num_mrs) return false; } diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index c54c984e70b..5de745bc824 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_RISCV_H #define GCC_RISCV_H +#include #include "config/riscv/riscv-opts.h" /* Target CPU builtins. */ @@ -620,8 +621,13 @@ enum reg_class #define GP_RETURN GP_ARG_FIRST #define FP_RETURN (UNITS_PER_FP_ARG == 0 ? GP_RETURN : FP_ARG_FIRST) +#define V_RETURN V_ARG_FIRST #define MAX_ARGS_IN_REGISTERS (riscv_abi == ABI_ILP32E ? 6 : 8) +/* Follow the calling convention in LLVM, + maximum 16 vector registers and 1 mask register in function arg. */ +#define MAX_ARGS_IN_VECTOR_REGISTERS (16) +#define MAX_ARGS_IN_MASK_REGISTERS (1) /* Symbolic macros for the first/last argument registers. */ @@ -630,6 +636,8 @@ enum reg_class #define GP_TEMP_FIRST (GP_REG_FIRST + 5) #define FP_ARG_FIRST (FP_REG_FIRST + 10) #define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1) +#define V_ARG_FIRST (V_REG_FIRST + 8) +#define V_ARG_LAST (V_ARG_FIRST + MAX_ARGS_IN_VECTOR_REGISTERS - 1) #define CALLEE_SAVED_REG_NUMBER(REGNO) \ ((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 : \ @@ -657,6 +665,12 @@ typedef struct { /* Number of floating-point registers used so far, likewise. */ unsigned int num_fprs; + + /* The used state of args in vectors, 1 for used by prev arg, initial to 0 */ + bool used_vrs[MAX_ARGS_IN_VECTOR_REGISTERS]; + + /* Number of mask registers used so far, up to MAX_ARGS_IN_MASK_REGISTERS. */ + unsigned int num_mrs; } CUMULATIVE_ARGS; /* Initialize a variable CUM of type CUMULATIVE_ARGS diff --git a/gcc/testsuite/gcc.target/riscv/rvv/custom/calling_convention_1.c b/gcc/testsuite/gcc.target/riscv/rvv/custom/calling_convention_1.c new file mode 100644 index 00000000000..5f79da2a9d6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/custom/calling_convention_1.c @@ -0,0 +1,46 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O3" } */ + +#include +#include + +void +test ( + vint8mf2_t a, vint8m4_t c, vint8m4_t d,vint8m2_t e, vint8m2_t b, + vint8m1_t f,vint8m1_t f2, vint8m1_t f3, vint8m1_t f4, vint8m2_t g, vint8m2_t h, + vbool16_t m1, vbool4_t m2, + int8_t *a1, int8_t *b1, int8_t *c1, + size_t vl) +{ + /* f4 => a0, g => a1, h => a2, m2 => a3, + a1 => a4, b1 => a5, c1 => a6, vl => a7 + + m1 => v0 + a => v8, c => v12, d => v16, e => v10, + b => v20, f => v9, f2 => v22, f3 => v23 */ + + vse8_v_i8mf2_m(m1, a1, a, vl); + + vse8_v_i8m2_m(m2, b1, b, vl); + + vse8_v_i8m4(c1, c, vl); + vse8_v_i8m4(c1, d, vl); + + vse8_v_i8m2(c1, e, vl); + + vse8_v_i8m1(c1, f, vl); + vse8_v_i8m1(c1, f2, vl); + vse8_v_i8m1(c1, f3, vl); + vse8_v_i8m1(c1, f4, vl); + + vse8_v_i8m2(c1, g, vl); + vse8_v_i8m2(c1, h, vl); +} +/* { dg-final { scan-assembler-times {vse8.v\s+v8,\s*\(a4\),\s*v0.t} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v20,\s*\(a5\),\s*v0.t} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v12,\s*\(a6\)} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v16,\s*\(a6\)} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v10,\s*\(a6\)} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v9,\s*\(a6\)} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v22,\s*\(a6\)} 1 } } */ +/* { dg-final { scan-assembler-times {vse8.v\s+v23,\s*\(a6\)} 1 } } */ \ No newline at end of file diff --git a/gcc/testsuite/gcc.target/riscv/rvv/custom/rvv-custom.exp b/gcc/testsuite/gcc.target/riscv/rvv/custom/rvv-custom.exp new file mode 100644 index 00000000000..4956ac0b184 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/custom/rvv-custom.exp @@ -0,0 +1,47 @@ +# Copyright (C) 2022-2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a RISC-V target. +if ![istarget riscv*-*-*] then { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS "-pedantic-errors -ansi" +} + +set gcc_march "rv64gcv_zfh" +if [istarget riscv32-*-*] then { + set gcc_march "rv32gcv_zfh" +} + +# Initialize `dg'. +dg-init + +# Main loop. +set CFLAGS "$DEFAULT_CFLAGS -march=$gcc_march -std=gnu11" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] \ + "" $CFLAGS + +# All done. +dg-finish \ No newline at end of file