From patchwork Tue Nov 5 03:21:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006599 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=S40aQPfM; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDCr5459z1xyD for ; Tue, 5 Nov 2024 14:22:16 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E84203857400 for ; Tue, 5 Nov 2024 03:22:14 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-211.mail.qq.com (out162-62-58-211.mail.qq.com [162.62.58.211]) by sourceware.org (Postfix) with UTF8SMTPS id B46313857732 for ; Tue, 5 Nov 2024 03:21:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org B46313857732 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org B46313857732 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.211 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776912; cv=none; b=Um5OiXB6UIaklDiraxQ8RveAkd8K0nmH+6rKTYp3R+/8nUC5jBIEDa+GLUocdiJHrqReMMBpZwzydoYYui8Y5RjGtzMJ5HXCQiAiWvyp6H5rUA65TE+yuAKROFtlTbv0s71vC/23HL0Dfk60RKd/iO0nuyw6dB8pk3oCMKPhnYs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776912; c=relaxed/simple; bh=r55ndoMNrasKlbketuG29eEzBUTvpalpX6U8CWz4siM=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=C/e1OPyezAfMP0oDcPE18JsxLHGKls1XdOqPwLLztjlLc0D5EdVfE+1t1YeoYaEK7Hm23LnOH/gm3Ev45/J96NV7ensj4FObsU4s+B1tHK/SC11EvD5oV8pUEAHAY1QCzFRUegsFTV7zFmuqAlptmyqzkvGiavmnzz1Mepwsxh4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730776899; bh=Acy4MtSNNALWSkGe5uU1ESwq6o24N3J6VDLDq5OKiSk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=S40aQPfMIK0lhc/cUs6EI7vDA2YNb9psMZqpiL8zrAUGBPihD7ufrEdgHEtvBEdWj jfi/T4+Q/+Tr/tc5rHHC4gFyV64Vo2YpBQV6s6piRy+K9yDDAvTrNOkR8MauNZbYCh jPxWg5ma5zPh5eEHD83hzhcIaxyk6TO4JaNqPBLw= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrszb20-0.qq.com (NewEsmtp) with SMTP id 5640C867; Tue, 05 Nov 2024 11:21:36 +0800 X-QQ-mid: xmsmtpt1730776896tkvc2ui8y Message-ID: X-QQ-XMAILINFO: MqG4KXyEKpQypsnPJ05m3Fqy6Kjt98JM8l0ucGwuRE8FQ+tjqv85/loSgfz35/ HbdAmMsGGGSQ8GF1FQidsmVeQZoCQMSGtZZP5uTsv66PlL0DJDm4M5OF8QM709DCC9HT0S89mbii y9kkrkpRs9IQ2ILUgTM8EMkv9xJLdciVvHP22/h5Pzw8lhsGvPjMjY/JS/IpO8p1MgzIdde2fRUQ ZmANjAQFcMpjnNWKNAPQ714ppxWYkbphpjtPTptj8IPky0a7qAeufYf11gn5RY5jOBGiGHVGQDS8 0WHRIDmOnt9iK9/AOGB2UA7erRldoDB5SMWlYrlvXrCSlEhiOmcjdFWhz+lZxR+N7tDrTtghYlvC 7NviskEUqmNuZPAHY1PVRMI1FQYiLUsRVP4isospp6iuHzkeNN/mnNEYDApMkjn2PiBVKV6d2qoO x0C6HpxEi+2yBNKCX/NLS6g/WbQvXDD5Fjq0TP297U9OM3+1niZKDH9fBdhcofK+wzWXoUZzVVT3 DH2jaqWIavNUwKTZHJoUBNbaZfSd61w4dEhXFZHwu12MTl4zahMsL/eUJv8ibZm5u/UoCdjLK2nS cdM/O0VBZC6qh3RRgr6qd8OjtPDyFzvgTvueqLr4+QqvBFb8WJbpeX7D6pbunTgvqI68SeMPsXEl zsKlB93andiXi9dhTNNCDHZOmprnyFgXxpkYpAihkiqfUSVOJ48hWpxUM9Rr/i5iwhorA39k3Hnn qUZBYthqqFjigZunyOV7fqIKfA4n7gAgbMj/EEOEpDzbONLlGrlyIPvEWzRr/yPOUVXgY5NkRSPG 3AUv3rGC7tTgafdk6wizoF1VMrIj0cgzIOgmBULz73umtWuyW41w1+3T8/i2amlldXjxjWQA2XPm Wzh6eAeC6OoPBTVT+8AEoT/fZhWGw8KZD3GEqZ2zA2myeLIy10bZz0W/QOlWl1I91N3VODpGUbjX IA8NyS9WGOEvsj9uQoxlvSRH9xl0hoGTx7THTI0+zzdatU7mVl62uYzi2bDANLXg5K4oNIIhA4lq 3IvqyZoQ== X-QQ-XMRINFO: MPJ6Tf5t3I/ycC2BItcBVIA= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 1/8] Introduce TARGET_CLONES_ATTR_SEPARATOR for RISC-V Date: Tue, 5 Nov 2024 11:21:22 +0800 X-OQ-MSGID: <20241105032129.2645089-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org Some architectures may use ',' in the attribute string, but it is not used as the separator for different targets. To avoid conflict, we introduce a new macro TARGET_CLONES_ATTR_SEPARATOR to separate different clones. As an example, according to RISC-V C-API Specification [1], RISC-V allows ',' in the attribute string in the "arch=" option to specify one more ISA extensions in the same target function, which conflict with the default separator to separate different clones. This patch introduces TARGET_CLONES_ATTR_SEPARATOR for RISC-V and choose '#' as the separator, since '#' is not allowed in the target_clones option string. [1] https://github.com/riscv-non-isa/riscv-c-api-doc/blob/c6c5d6d9cf96b342293315a5dff3d25e96ef8191/src/c-api.adoc#__attribute__targetattr-string Signed-off-by: Yangyu Chen gcc/ChangeLog: * defaults.h (TARGET_CLONES_ATTR_SEPARATOR): Define new macro. * multiple_target.cc (get_attr_str): Use TARGET_CLONES_ATTR_SEPARATOR to separate attributes. (separate_attrs): Likewise. (expand_target_clones): Likewise. * attribs.cc (attr_strcmp): Likewise. (sorted_attr_string): Likewise. * tree.cc (get_target_clone_attr_len): Likewise. * config/riscv/riscv.h (TARGET_CLONES_ATTR_SEPARATOR): Define TARGET_CLONES_ATTR_SEPARATOR for RISC-V. * doc/tm.texi: Document TARGET_CLONES_ATTR_SEPARATOR. * doc/tm.texi.in: Likewise. --- gcc/attribs.cc | 17 ++++++++++------- gcc/config/riscv/riscv.h | 5 +++++ gcc/defaults.h | 4 ++++ gcc/doc/tm.texi | 7 +++++++ gcc/doc/tm.texi.in | 7 +++++++ gcc/multiple_target.cc | 19 ++++++++++++------- gcc/tree.cc | 4 +++- 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/gcc/attribs.cc b/gcc/attribs.cc index a290015fb47..1d6589835a1 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -1103,9 +1103,10 @@ attr_strcmp (const void *v1, const void *v2) } /* ARGLIST is the argument to target attribute. This function tokenizes - the comma separated arguments, sorts them and returns a string which - is a unique identifier for the comma separated arguments. It also - replaces non-identifier characters "=,-" with "_". */ + the TARGET_CLONES_ATTR_SEPARATOR separated arguments, sorts them and + returns a string which is a unique identifier for the + TARGET_CLONES_ATTR_SEPARATOR separated arguments. It also replaces + non-identifier characters "=,-" with "_". */ char * sorted_attr_string (tree arglist) @@ -1117,6 +1118,7 @@ sorted_attr_string (tree arglist) char *attr = NULL; unsigned int argnum = 1; unsigned int i; + static const char separator_str[] = { TARGET_CLONES_ATTR_SEPARATOR, 0 }; for (arg = arglist; arg; arg = TREE_CHAIN (arg)) { @@ -1126,7 +1128,7 @@ sorted_attr_string (tree arglist) if (arg != arglist) argnum++; for (i = 0; i < strlen (str); i++) - if (str[i] == ',') + if (str[i] == TARGET_CLONES_ATTR_SEPARATOR) argnum++; } @@ -1137,7 +1139,8 @@ sorted_attr_string (tree arglist) const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); size_t len = strlen (str); memcpy (attr_str + str_len_sum, str, len); - attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0'; + attr_str[str_len_sum + len] + = TREE_CHAIN (arg) ? TARGET_CLONES_ATTR_SEPARATOR : '\0'; str_len_sum += len + 1; } @@ -1152,12 +1155,12 @@ sorted_attr_string (tree arglist) args = XNEWVEC (char *, argnum); i = 0; - attr = strtok (attr_str, ","); + attr = strtok (attr_str, separator_str); while (attr != NULL) { args[i] = attr; i++; - attr = strtok (NULL, ","); + attr = strtok (NULL, separator_str); } qsort (args, argnum, sizeof (char *), attr_strcmp); diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index ca1b8329cdc..2ff9c1024f3 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1298,4 +1298,9 @@ extern void riscv_remove_unneeded_save_restore_calls (void); STACK_BOUNDARY / BITS_PER_UNIT) \ : (crtl->outgoing_args_size + STACK_POINTER_OFFSET)) +/* According to the RISC-V C API, the arch string may contains ','. To avoid + the conflict with the default separator, we choose '#' as the separator for + the target attribute. */ +#define TARGET_CLONES_ATTR_SEPARATOR '#' + #endif /* ! GCC_RISCV_H */ diff --git a/gcc/defaults.h b/gcc/defaults.h index ac2d25852ab..918e3ec2f24 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -874,6 +874,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_HAS_FMV_TARGET_ATTRIBUTE 1 #endif +/* Select a attribute separator for function multiversioning. */ +#ifndef TARGET_CLONES_ATTR_SEPARATOR +#define TARGET_CLONES_ATTR_SEPARATOR ',' +#endif /* Select a format to encode pointers in exception handling data. We prefer those that result in fewer dynamic relocations. Assume no diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 4deb3d2c283..109e40384b6 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -10822,6 +10822,13 @@ the function declaration to hold a pointer to a target-specific @code{struct cl_target_option} structure. @end deftypefn +@defmac TARGET_CLONES_ATTR_SEPARATOR +Define this char-typed macro to select a character that separates each +target specific attributes from the @code{attribute(target_clones("..."))} +attribute string. This macro should be carefully chosen to avoid conflicts +with the target specific attributes. The default value is @code{','}. +@end defmac + @deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set}) This hook is called to save any additional target-specific information in the @code{struct cl_target_option} structure for function-specific diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 9f147ccb95c..93bcd747e37 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7101,6 +7101,13 @@ on this implementation detail. @hook TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P +@defmac TARGET_CLONES_ATTR_SEPARATOR +Define this char-typed macro to select a character that separates each +target specific attributes from the @code{attribute(target_clones("..."))} +attribute string. This macro should be carefully chosen to avoid conflicts +with the target specific attributes. The default value is @code{','}. +@end defmac + @hook TARGET_OPTION_SAVE @hook TARGET_OPTION_RESTORE diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc index d2c9671fc1b..0cceba68ce9 100644 --- a/gcc/multiple_target.cc +++ b/gcc/multiple_target.cc @@ -181,7 +181,7 @@ create_dispatcher_calls (struct cgraph_node *node) } } -/* Create string with attributes separated by comma. +/* Create string with attributes separated by TARGET_CLONES_ATTR_SEPARATOR. Return number of attributes. */ static int @@ -195,17 +195,21 @@ get_attr_str (tree arglist, char *attr_str) { const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); size_t len = strlen (str); - for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ',')) + for (const char *p = strchr (str, TARGET_CLONES_ATTR_SEPARATOR); + p; + p = strchr (p + 1, TARGET_CLONES_ATTR_SEPARATOR)) argnum++; memcpy (attr_str + str_len_sum, str, len); - attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0'; + attr_str[str_len_sum + len] + = TREE_CHAIN (arg) ? TARGET_CLONES_ATTR_SEPARATOR : '\0'; str_len_sum += len + 1; argnum++; } return argnum; } -/* Return number of attributes separated by comma and put them into ARGS. +/* Return number of attributes separated by TARGET_CLONES_ATTR_SEPARATOR + and put them into ARGS. If there is no DEFAULT attribute return -1. If there is an empty string in attribute return -2. If there are multiple DEFAULT attributes return -3. @@ -216,9 +220,10 @@ separate_attrs (char *attr_str, char **attrs, int attrnum) { int i = 0; int default_count = 0; + static const char separator_str[] = { TARGET_CLONES_ATTR_SEPARATOR, 0 }; - for (char *attr = strtok (attr_str, ","); - attr != NULL; attr = strtok (NULL, ",")) + for (char *attr = strtok (attr_str, separator_str); + attr != NULL; attr = strtok (NULL, separator_str)) { if (strcmp (attr, "default") == 0) { @@ -306,7 +311,7 @@ static bool expand_target_clones (struct cgraph_node *node, bool definition) { int i; - /* Parsing target attributes separated by comma. */ + /* Parsing target attributes separated by TARGET_CLONES_ATTR_SEPARATOR. */ tree attr_target = lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl)); /* No targets specified. */ diff --git a/gcc/tree.cc b/gcc/tree.cc index b4c059d3b0d..113a669128b 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -15229,7 +15229,9 @@ get_target_clone_attr_len (tree arglist) const char *str = TREE_STRING_POINTER (TREE_VALUE (arg)); size_t len = strlen (str); str_len_sum += len + 1; - for (const char *p = strchr (str, ','); p; p = strchr (p + 1, ',')) + for (const char *p = strchr (str, TARGET_CLONES_ATTR_SEPARATOR); + p; + p = strchr (p + 1, TARGET_CLONES_ATTR_SEPARATOR)) argnum++; argnum++; } From patchwork Tue Nov 5 03:22:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006600 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=a4S/kn6Q; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDDV00P3z1xyD for ; Tue, 5 Nov 2024 14:22:49 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2A9743857037 for ; Tue, 5 Nov 2024 03:22:48 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-216.mail.qq.com (out162-62-58-216.mail.qq.com [162.62.58.216]) by sourceware.org (Postfix) with UTF8SMTPS id 2B3903857706 for ; Tue, 5 Nov 2024 03:22:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2B3903857706 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2B3903857706 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.216 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776938; cv=none; b=gNbI8OulnclnYOcF/YbYpdcfb+KVHxhnG6G4pWC79gnLKLJ3MVLTXtJOYNfnAqY4NQ61Nb+aygW8/8lZG5+dxf+GgFRbf1BaMeNEkI0t7ggdnB1dXYz16p+7g/p0lmN+6mZ83D0l6YduUVnVzDI13Q5pvgJpzmjk7QoEEnhS+mo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776938; c=relaxed/simple; bh=SCA7DgNuHFwWE0i1mIMGDtI9d0rXYB1zhyWBlm0S6lA=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=Ci2xn/XVo4Ljcl5uXl8k9//H13O2VlDvqWtvh/0+h56NXCDf8OI16JUyVBOa7BcZIF5yPhMBclLc6GI5+IDcjGubk56K23u9ygp6fa+abR6hx7/jFou2FNPA+V/eC1gEXMAK+GPHJ1/YD3QXXQbJ/VARyPVjeQhaKCtnVOU7hTE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730776930; bh=ENk4V19HYiQZ7OEvb/I0zWP2xPmKNooYb2GxzfuTnd0=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=a4S/kn6Qi3eLnMZ3QjgXWajZ/39qeVhcuXA6+KSdVh6Of3tSKKlygwTDKrR7Pvirh mwyxW/s1QJK15AWjeuWa5R+YoUnXSCFi7waERCyAV/RPQGfnDx45K9SxFEGHbFNygm YswjDnAnuzz8sV6BzlINCnSKiMya/3KwSpbHouf4= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrszc16-0.qq.com (NewEsmtp) with SMTP id 5878DA8A; Tue, 05 Nov 2024 11:22:07 +0800 X-QQ-mid: xmsmtpt1730776927t1yvewei3 Message-ID: X-QQ-XMAILINFO: OVFdYp27KdlJUb+gPn8mDFaSmOysX8RskicHLICttlwRbZqsymOGM/8IzxbUjl Zn8aIsKjiFBNO+UF6dbYAPXRT3zxszkA5R7LYxup57XUuMrp1irW7aIeZMchhaTod9PxLamN0/UK FTlIVZCjgnfhIE++p1Xv9N07o6GiJcJONg10Wr4Q1UJfpNLL/q/GdBzlw3aV92walVPwI7QZUzk/ aj/IGtnlcpqKsL4ek7338QeeUaNTTpa0Aj5F9JUpGnEA2TRMi3gi3TnpwbDCyy1eZ5jVcTs6DwdC Fx3sGr+peNzaRrUQ0UP+JtKHB7LFfqcgo8Uy3pJSXc6qdPJCagNKK2VlWRfniv5WFqQ5DgLyGBQY rUldFlMQ5PiMOc6LpPw9p5hvQ9wne4pvNtcPi9oPeCC0kB8cB/cB3yHl9XRjlSM0NRuGLmgVWFEV AurXqJ7Zl5Oy0ykdmqLRd6lxZHxJlmvwdm/KgoSUo/ORMACHQxIm8jwcAglX/vz9OpDjQXUPk43A fhV16RgFO201LZPz+Q0CJT99S/loVly9FY1p/ikJ+MwvMRN/CjhtIQvzv43ezq6LOIFtuVnnosL+ J5ycV7Mf+2Zrv/sDd+cYl2rikW4mB+swEnGWzl6MrphtEAsWwn+qC6kRJUSxocwYA1T4zwmj+rW1 CSi6C3KhGtT+T0iV3yHUqtHGNSVph5t71CEfRDH+e2tFTIr8Q/NpKul0/QQ8ZDOMf9qyn1knWQlr HPZRZls39wTwyY6HebismPuzuG5P0ba+ZFiULE+wH8jKCZoPx2DlhCbVwsMCeunRG/WUPPJe7qIv 9go7Jyj8WL3rjUbETeAvYTHJtB1IZ3r3xl5b2vBBMgNzyqF3LIgg/tAT3NUT3Xr+XzsCimnlXRDf 5FTgf+lGKi91ESFiKbrsdRrwIV6FStcOXwFoV+wHLpE35+EmgJHRVaIbKRrLVMJN3Z3nrv6gqUSM Le5JUiuWF2ygHMvvar5qYd/w77LOZ1d94lqihRyzvTQgT3KKdhLI7ifOD5UQHi5yu/giMEqjU8sj qLkdbkIlaSHPte6OvDkd2SYMPXv/AqW9q8ZmrjQg== X-QQ-XMRINFO: M/715EihBoGSf6IYSX1iLFg= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 2/8] RISC-V: Implement Priority syntax parser for Function Multi-Versioning Date: Tue, 5 Nov 2024 11:22:00 +0800 X-OQ-MSGID: <20241105032200.2645476-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch adds the priority syntax parser to support the Function Multi-Versioning (FMV) feature in RISC-V. This feature allows users to specify the priority of the function version in the attribute syntax. Chnages based on RISC-V C-API PR: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/85 Signed-off-by: Yangyu Chen gcc/ChangeLog: * config/riscv/riscv-target-attr.cc (riscv_target_attr_parser::handle_priority): New function. (riscv_target_attr_parser::update_settings): Update priority attribute. * config/riscv/riscv.opt: Add TargetVariable riscv_fmv_priority. --- gcc/config/riscv/riscv-target-attr.cc | 24 ++++++++++++++++++++++++ gcc/config/riscv/riscv.opt | 3 +++ 2 files changed, 27 insertions(+) diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc index 8ce9607b3c9..293d5321215 100644 --- a/gcc/config/riscv/riscv-target-attr.cc +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -39,16 +39,19 @@ public: : m_found_arch_p (false) , m_found_tune_p (false) , m_found_cpu_p (false) + , m_found_priority_p (false) , m_subset_list (nullptr) , m_loc (loc) , m_cpu_info (nullptr) , m_tune (nullptr) + , m_priority (0) { } bool handle_arch (const char *); bool handle_cpu (const char *); bool handle_tune (const char *); + bool handle_priority (const char *); void update_settings (struct gcc_options *opts) const; private: @@ -58,10 +61,12 @@ private: bool m_found_arch_p; bool m_found_tune_p; bool m_found_cpu_p; + bool m_found_priority_p; riscv_subset_list *m_subset_list; location_t m_loc; const riscv_cpu_info *m_cpu_info; const char *m_tune; + int m_priority; }; } @@ -210,6 +215,22 @@ riscv_target_attr_parser::handle_tune (const char *str) return true; } +bool +riscv_target_attr_parser::handle_priority (const char *str) +{ + if (m_found_priority_p) + error_at (m_loc, "% attribute: priority appears more than once"); + m_found_priority_p = true; + + if (sscanf (str, "%d", &m_priority) != 1) + { + error_at (m_loc, "% attribute: invalid priority %qs", str); + return false; + } + + return true; +} + void riscv_target_attr_parser::update_settings (struct gcc_options *opts) const { @@ -236,6 +257,9 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const if (m_cpu_info) opts->x_riscv_tune_string = m_cpu_info->tune; } + + if (m_priority) + opts->x_riscv_fmv_priority = m_priority; } /* Parse ARG_STR which contains the definition of one target attribute. diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 5bc5d300293..ab9d6e82723 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -523,6 +523,9 @@ Mask(XSFVCP) Var(riscv_sifive_subext) Mask(XSFCEASE) Var(riscv_sifive_subext) +TargetVariable +int riscv_fmv_priority = 0 + Enum Name(isa_spec_class) Type(enum riscv_isa_spec_class) Supported ISA specs (for use with the -misa-spec= option): From patchwork Tue Nov 5 03:22:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006601 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=r7bOmKvR; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDDk4bk5z1xyD for ; Tue, 5 Nov 2024 14:23:02 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D18093857011 for ; Tue, 5 Nov 2024 03:23:00 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-216.mail.qq.com (out162-62-58-216.mail.qq.com [162.62.58.216]) by sourceware.org (Postfix) with UTF8SMTPS id 17CCA3857BA3 for ; Tue, 5 Nov 2024 03:22:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 17CCA3857BA3 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 17CCA3857BA3 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.216 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776951; cv=none; b=k6YhdrzyHgoMNQR5egm5O5tjN9fX+ShrU9oUZeBs+rrmN9/220JHEh/GiQTFiDrPlhSSDG3VavVUwoYBSM0UWdk2hCyFPThi+FJ/eLVWO9hVahibRZ0tqQa7JVe9Npz/3t8UxdVEjTv3lT31jp3BH0quPJZVKyWyuqZWPcZ/wUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776951; c=relaxed/simple; bh=FuP8tATgzahH+4Fn4+czpZc+MVlH3YpM9hNCeEZa6EM=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=cl0bdBZKVMVN7q3pxcyxWcAcLtWVAZmD8XrU+SATp3LtAirbKLgZDfra6PL0MCmtla656ptFxkC24DIv5oTLsnj2tOy0NNQ3D05Sozo3HifXEQZdoK+ZLntiGpC2R3Ap0cNzYZnJQU+4FxJ8PQ4tp/RtZZ54rktfRmBwCMQJ7f0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730776941; bh=LjDj199VlNgVSRXUC9c4eyyxcDlgNNXxoqp9FNWmCL4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=r7bOmKvRvxBdp5S24GxnkUwNuk3jI4y0l/Y3xTWZgxu5LF4UcLpEIYi7tvyjMlMxO nNJNFjbGwAs54DKM05XmQZVBpL3DDWC6INyeBss1U2Q/y0pb3uKWzBkJ6PXfN9jRo4 t4pyMPCJzqsCZQkCsKDmqgQ38oiy493klbod71EE= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrszb16-1.qq.com (NewEsmtp) with SMTP id 59315CFE; Tue, 05 Nov 2024 11:22:19 +0800 X-QQ-mid: xmsmtpt1730776939tk7j4yru8 Message-ID: X-QQ-XMAILINFO: MllZffuBkEb5+DdQxOt7EblTccYIXedxCqDxqi97Qi22Tzk98aavK162h4cOLX eQJ32TwfSSlJ6PXkKTGTCjbG7Ree7rZ7NM+8wYAsbVRGvX3vu8Vwmur+p0gzVnxk1GLcS3ijK/fC CnDRpgf9Nl0HDWDF2MMi32VM2JCQLDYL7YSXnue/V4QIl6DBHGpiPhVz4SxgEIHaK6O5NtQKToPI EXfeJNQCXfTB3Y1MGYDWOm23IIhRkOUHXtL9PY5Dzx40E7H4szUH10evkoIrdWuVlzccOpAtwWS3 DZfu//6wR1fFDGTyydhpPKvovU1Cg+5P1f01lCRb5fSI7xFHj9U+acXjPiSfuyJ7ZnztYr4mMdlt 3JTVP9XL+rPAe6EE13VJUMR5LD9302qDCQx5/AEatsaHiuu3doXH4fKT8b/qtyD/AE+I+N+wbkr8 HQ44PyJAKtLzcYmb49/aAVIRgUtDITLnSNFVfO3HAFtSyAcXG7sJ5NR4RtLji2cVREns+nyuclh/ YFnFudC8+Owri7V+6SUk0TacTQC1B9s15vbk/VPqgkSbasKH6rp8+OS8aq0Cg53L8mA1TfmEm58B npHnKDNzKgvBsFAsrVgDY6snTckXscmq4RLJQCYiqdLgkg3ofud5EyGiLFMj0eMIeRA8W2E++s6K yD65AN7d89F39ywG3FYur29tCzUn7XI7F/xq7aREyfhOt/HmfXGDjE2lX2J2vlrqWI5/AboTe8/C YPdILNmuinBvjxZX6nJ9FCmzGAL5oISOU8we17BVBxH3v6hPYCe/xZ+8ebOC6xBmBbgLPwzOeC0l jjsOTrfo11zTDkIZztl27e486hN9ONrh9GLKCQegdi+EQC+ePK0iXT56iZqx2dD+lyl+MBRUbkOz V9rA0x5DhmrJAq9TCuDAT4yRwIJJ8nxEYb15l6GfWwZx7T0Poo5LRpGrWpn1ODaqttTTqq44uuLf 6k+Tsts0Zu9YMPUrRdGw8XkBhmo6dijkpfMD8Pd0TmGvS63K2+ryLHjVkXGhhu38kCFTkmfdlPeM W0qB7sEgCpyW1ZIFE/ X-QQ-XMRINFO: Nq+8W0+stu50PRdwbJxPCL0= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 3/8] RISC-V: Implement riscv_minimal_hwprobe_feature_bits Date: Tue, 5 Nov 2024 11:22:16 +0800 X-OQ-MSGID: <20241105032216.2645639-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch implements the riscv_minimal_hwprobe_feature_bits feature for the RISC-V target. The feature bits are defined in the libgcc/config/riscv/feature_bits.c to provide bitmasks of ISA extensions that defined in RISC-V C-API. Thus, we need a function to generate the feature bits for IFUNC resolver to dispatch between different functions based on the hardware features. The minimal feature bits means to use the earliest extension appeard in the Linux hwprobe to cover the given ISA string. To allow older kernels without some implied extensions probe to run the FMV dispatcher correctly. For example, V implies Zve32x, but Zve32x appears in the Linux kernel since v6.11. If we use isa string directly to generate FMV dispatcher with functions with "arch=+v" extension, since we have V implied the Zve32x, FMV dispatcher will check if the Zve32x extension is supported by the host. If the Linux kernel is older than v6.11, the FMV dispatcher will fail to detect the Zve32x extension even it already implies by the V extension, thus making the FMV dispatcher fail to dispatch the correct function. Thus, we need to generate the minimal feature bits to cover the given ISA string to allow the FMV dispatcher to work correctly on older kernels. Signed-off-by: Yangyu Chen gcc/ChangeLog: * common/config/riscv/riscv-common.cc (RISCV_EXT_BITMASK): New macro. (struct riscv_ext_bitmask_table_t): New struct. (riscv_minimal_hwprobe_feature_bits): New function. * common/config/riscv/riscv-ext-bitmask.def: New file. * config/riscv/riscv-subset.h (GCC_RISCV_SUBSET_H): Include riscv-feature-bits.h. (riscv_minimal_hwprobe_feature_bits): Declare the function. * config/riscv/riscv-feature-bits.h: New file. --- gcc/common/config/riscv/riscv-common.cc | 94 +++++++++++++++++++ gcc/common/config/riscv/riscv-ext-bitmask.def | 83 ++++++++++++++++ gcc/config/riscv/riscv-feature-bits.h | 44 +++++++++ gcc/config/riscv/riscv-subset.h | 5 + 4 files changed, 226 insertions(+) create mode 100644 gcc/common/config/riscv/riscv-ext-bitmask.def create mode 100644 gcc/config/riscv/riscv-feature-bits.h diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 60595a3e356..b0e49eb82c0 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see #include #include +#include #define INCLUDE_STRING #define INCLUDE_SET @@ -1762,6 +1763,24 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = {NULL, NULL, NULL, 0} }; +/* Types for recording extension to RISC-V C-API bitmask. */ +struct riscv_ext_bitmask_table_t { + const char *ext; + int groupid; + int bit_position; +}; + +/* Mapping table between extension to RISC-V C-API extension bitmask. + This table should sort the extension by Linux hwprobe order to get the + minimal feature bits. */ +static const riscv_ext_bitmask_table_t riscv_ext_bitmask_table[] = +{ +#define RISCV_EXT_BITMASK(NAME, GROUPID, BITPOS) \ + {NAME, GROUPID, BITPOS}, +#include "riscv-ext-bitmask.def" + {NULL, -1, -1} +}; + /* Apply SUBSET_LIST to OPTS if OPTS is not null. */ void @@ -1828,6 +1847,81 @@ riscv_x_target_flags_isa_mask (void) return mask; } +/* Get the minimal feature bits in Linux hwprobe of the given ISA string. + + Used for generating Function Multi-Versioning (FMV) dispatcher for RISC-V. + + The minimal feature bits refer to using the earliest extension that appeared + in the Linux hwprobe to support the specified ISA string. This ensures that + older kernels, which may lack certain implied extensions, can still run the + FMV dispatcher correctly. */ + +bool +riscv_minimal_hwprobe_feature_bits (const char *isa, + struct riscv_feature_bits *res, + location_t loc) +{ + riscv_subset_list *subset_list; + subset_list = riscv_subset_list::parse (isa, loc); + if (!subset_list) + return false; + + /* Initialize the result feature bits to zero. */ + res->length = RISCV_FEATURE_BITS_LENGTH; + for (int i = 0; i < RISCV_FEATURE_BITS_LENGTH; ++i) + res->features[i] = 0; + + /* Use a std::set to record all visited implied extensions. */ + std::set implied_exts; + + /* Iterate through the extension bitmask table in Linux hwprobe order to get + the minimal covered feature bits. Avoiding some sub-extensions which will + be implied by the super-extensions like V implied Zve32x. */ + const riscv_ext_bitmask_table_t *ext_bitmask_tab; + for (ext_bitmask_tab = &riscv_ext_bitmask_table[0]; + ext_bitmask_tab->ext; + ++ext_bitmask_tab) + { + /* Skip the extension if it is not in the subset list or already implied + by previous extension. */ + if (subset_list->lookup (ext_bitmask_tab->ext) == NULL + || implied_exts.count (ext_bitmask_tab->ext)) + continue; + + res->features[ext_bitmask_tab->groupid] + |= 1ULL << ext_bitmask_tab->bit_position; + + /* Find the sub-extension using BFS and set the corresponding bit. */ + std::queue search_q; + search_q.push (ext_bitmask_tab->ext); + + while (!search_q.empty ()) + { + const char * search_ext = search_q.front (); + search_q.pop (); + + /* Iterate through the implied extension table. */ + const riscv_implied_info_t *implied_info; + for (implied_info = &riscv_implied_info[0]; + implied_info->ext; + ++implied_info) + { + /* When the search extension matches the implied extension and + the implied extension has not been visited, mark the implied + extension in the implied_exts set and push it into the + queue. */ + if (implied_info->match (subset_list, search_ext) + && implied_exts.count (implied_info->implied_ext) == 0) + { + implied_exts.insert (implied_info->implied_ext); + search_q.push (implied_info->implied_ext); + } + } + } + } + return true; +} + /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch dependent mask bits, in case more than one -march string is passed. */ diff --git a/gcc/common/config/riscv/riscv-ext-bitmask.def b/gcc/common/config/riscv/riscv-ext-bitmask.def new file mode 100644 index 00000000000..ca5df1740f3 --- /dev/null +++ b/gcc/common/config/riscv/riscv-ext-bitmask.def @@ -0,0 +1,83 @@ +/* RISC-V Extension Bitmask Definitions, corresponding to Extension Bitmask + Definitions in RISC-V C API Specification. + Copyright (C) 2024 Free Software Foundation, Inc. + Contributed by Yangyu Chen (cyy@cyyself.name). + +This file is part of GCC. + +GCC 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, or (at your option) +any later version. + +GCC 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 +. */ + +#ifndef RISCV_EXT_BITMASK +#define RISCV_EXT_BITMASK(NAME, GROUP_ID, BIT_POSITION) +#endif + +/* This table should sort the extension by Linux hwprobe order to calculate the + minimal feature bits. */ + +RISCV_EXT_BITMASK ("i", 0, 8) +RISCV_EXT_BITMASK ("m", 0, 12) +RISCV_EXT_BITMASK ("a", 0, 0) +RISCV_EXT_BITMASK ("f", 0, 5) +RISCV_EXT_BITMASK ("d", 0, 3) +RISCV_EXT_BITMASK ("c", 0, 2) +RISCV_EXT_BITMASK ("v", 0, 21) +RISCV_EXT_BITMASK ("zba", 0, 27) +RISCV_EXT_BITMASK ("zbb", 0, 28) +RISCV_EXT_BITMASK ("zbs", 0, 33) +RISCV_EXT_BITMASK ("zicboz", 0, 37) +RISCV_EXT_BITMASK ("zbc", 0, 29) +RISCV_EXT_BITMASK ("zbkb", 0, 30) +RISCV_EXT_BITMASK ("zbkc", 0, 31) +RISCV_EXT_BITMASK ("zbkx", 0, 32) +RISCV_EXT_BITMASK ("zknd", 0, 41) +RISCV_EXT_BITMASK ("zkne", 0, 42) +RISCV_EXT_BITMASK ("zknh", 0, 43) +RISCV_EXT_BITMASK ("zksed", 0, 44) +RISCV_EXT_BITMASK ("zksh", 0, 45) +RISCV_EXT_BITMASK ("zkt", 0, 46) +RISCV_EXT_BITMASK ("zvbb", 0, 48) +RISCV_EXT_BITMASK ("zvbc", 0, 49) +RISCV_EXT_BITMASK ("zvkb", 0, 52) +RISCV_EXT_BITMASK ("zvkg", 0, 53) +RISCV_EXT_BITMASK ("zvkned", 0, 54) +RISCV_EXT_BITMASK ("zvknha", 0, 55) +RISCV_EXT_BITMASK ("zvknhb", 0, 56) +RISCV_EXT_BITMASK ("zvksed", 0, 57) +RISCV_EXT_BITMASK ("zvksh", 0, 58) +RISCV_EXT_BITMASK ("zvkt", 0, 59) +RISCV_EXT_BITMASK ("zfh", 0, 35) +RISCV_EXT_BITMASK ("zfhmin", 0, 36) +RISCV_EXT_BITMASK ("zihintntl", 0, 39) +RISCV_EXT_BITMASK ("zvfh", 0, 50) +RISCV_EXT_BITMASK ("zvfhmin", 0, 51) +RISCV_EXT_BITMASK ("zfa", 0, 34) +RISCV_EXT_BITMASK ("ztso", 0, 47) +RISCV_EXT_BITMASK ("zacas", 0, 26) +RISCV_EXT_BITMASK ("zicond", 0, 38) +RISCV_EXT_BITMASK ("zihintpause", 0, 40) +RISCV_EXT_BITMASK ("zve32x", 0, 60) +RISCV_EXT_BITMASK ("zve32f", 0, 61) +RISCV_EXT_BITMASK ("zve64x", 0, 62) +RISCV_EXT_BITMASK ("zve64f", 0, 63) +RISCV_EXT_BITMASK ("zve64d", 1, 0) +RISCV_EXT_BITMASK ("zimop", 1, 1) +RISCV_EXT_BITMASK ("zca", 1, 2) +RISCV_EXT_BITMASK ("zcb", 1, 3) +RISCV_EXT_BITMASK ("zcd", 1, 4) +RISCV_EXT_BITMASK ("zcf", 1, 5) +RISCV_EXT_BITMASK ("zcmop", 1, 6) +RISCV_EXT_BITMASK ("zawrs", 1, 7) + +#undef RISCV_EXT_BITMASK diff --git a/gcc/config/riscv/riscv-feature-bits.h b/gcc/config/riscv/riscv-feature-bits.h new file mode 100644 index 00000000000..19b7630e339 --- /dev/null +++ b/gcc/config/riscv/riscv-feature-bits.h @@ -0,0 +1,44 @@ +/* Definition of RISC-V feature bits corresponding to + libgcc/config/riscv/feature_bits.c + Copyright (C) 2024 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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, or (at your option) +any later version. + +GCC 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 +. */ + +#ifndef GCC_RISCV_FEATURE_BITS_H +#define GCC_RISCV_FEATURE_BITS_H + +#define RISCV_FEATURE_BITS_LENGTH 2 + +struct riscv_feature_bits { + unsigned length; + unsigned long long features[RISCV_FEATURE_BITS_LENGTH]; +}; + +#define RISCV_VENDOR_FEATURE_BITS_LENGTH 1 + +struct riscv_vendor_feature_bits { + unsigned length; + unsigned long long features[RISCV_VENDOR_FEATURE_BITS_LENGTH]; +}; + +struct riscv_cpu_model { + unsigned mvendorid; + unsigned long long marchid; + unsigned long long mimpid; +}; + +#endif /* GCC_RISCV_FEATURE_BITS_H */ diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h index 1914a5317d7..62aae4f2472 100644 --- a/gcc/config/riscv/riscv-subset.h +++ b/gcc/config/riscv/riscv-subset.h @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_RISCV_SUBSET_H #define GCC_RISCV_SUBSET_H +#include "riscv-feature-bits.h" + #define RISCV_DONT_CARE_VERSION -1 /* Subset info. */ @@ -120,6 +122,9 @@ public: extern const riscv_subset_list *riscv_cmdline_subset_list (void); extern void riscv_set_arch_by_subset_list (riscv_subset_list *, struct gcc_options *); +extern bool riscv_minimal_hwprobe_feature_bits (const char *, + struct riscv_feature_bits *, + location_t); extern bool riscv_ext_is_subset (struct cl_target_option *, struct cl_target_option *); extern int riscv_x_target_flags_isa_mask (void); From patchwork Tue Nov 5 03:22:29 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006604 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=bS9Vn9nC; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDG63VWnz1xyD for ; Tue, 5 Nov 2024 14:24:14 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AE4A9385700E for ; Tue, 5 Nov 2024 03:24:12 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-57-252.mail.qq.com (out162-62-57-252.mail.qq.com [162.62.57.252]) by sourceware.org (Postfix) with UTF8SMTPS id C5B4F385840F for ; Tue, 5 Nov 2024 03:22:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C5B4F385840F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C5B4F385840F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.57.252 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776964; cv=none; b=Xnw6bRabrJEmZPiRV8PurEV9xySxEUTZ693uMsg0efLcAJmp3CWuUUIOAgW7Y5LE925NZ0sAgfQpNQcZahq82tj+Inrl6VlggFF9/HneNTpt8SMivz9zjp6qpvW9zm7cJiGhRIkakZVld+Tz8C2e6FjktiwKMfBOZv61ggginas= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776964; c=relaxed/simple; bh=qv+gnBF0vfZzLoOKBOjEMtLTAjk4XEP50uG221Iz55s=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=JxhhGrV5NCj5A6ziU525C87r/YsSWxxEnTOceQl8bIDgwK3YbC1OUjIcq/XSXC5PynjA0FCoq0Hk73QtEtgYlsB8axhivoUEj/uqsKqEAABrdpDoTV02hkIasM/nLqrpkUMVXvs5LDmnNABk6wVgxlhtbDJPMrnTc3/1eZKNwlM= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730776956; bh=Yqhr2kV3FseJlvemowDC/YOv5yzMrQl/oniyfEKkqjM=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=bS9Vn9nCqvIq0uebD2OlTKS+Cn5YNlW2guMzwKHTcg4St2PYNBDS9EKa86uf3d7OY IPo7LyRnyiHl4Yhv8eoyqljU7j67Uyyi17VksDqOsVzDzA7BNxg/BeOn2IzfZG3veF /FAoSBNl6AZuS5jRnTFcYDYogDZVRjvopCOkuzsA= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrsza36-0.qq.com (NewEsmtp) with SMTP id 5A08FC32; Tue, 05 Nov 2024 11:22:32 +0800 X-QQ-mid: xmsmtpt1730776952tq4ylj7ku Message-ID: X-QQ-XMAILINFO: OATpkVjS499uqcvVK4cwlBM250dh8a2NUzhFR2oiqK5JEXvZAlDfkAjm17xkl2 8f2IqBisGBdqqLPoKzgmggW+OYxPaTzMLnwy/uZzXeceLjMgceQ3mOSfVE+rGCIk+1Mze519i42w sDlFAEL5zQthOWUY4HP3ceZTTvesK/N6xS5Z36NGaT7QheqXMB5/HX63a7OorUhj3zEsh7DFbCtK hVnekj0dnmqAqb7J9Oi058OOvWp2GI/Iu734rtHsUMozsZxUGLejVYT8Rin6hhD6KMkUTqdxpIlx BwkZKdYaz/dL9NVeV98f9TZ69KfYfRM5GBZE3CcgLa38kK8efESktEUZ2Fn9Wfe1LURJvTJk/V9z aRSt0nzTZ3sAqjanGdJNe7flZ0m/LtYaj1gW28MV/3WC2puRNgLbyqAgDAy9XUdxezxyTwRbhsoD veaQtBCSEWOhrEq1yigQ7Pp6KfoHMDrMPsdTwRaqGhcRe/q/U5vk67gVmibCIHcYyl9SfHEMlSgB SPOGmoiWq/PzVaS1FC0Q9V64vVg3x2KfKJLzYSAzyonI0uZQ2FqZIrjSumToYLmiC+ryo2I6dxng vutt8bocqwNcXIHYyA6BoIWBc7EIrRjueGJDm6VXYGLTNY8yWSVALsgV6piUA8hNREjV1zHPMRIc zB08NIFMJCRgYxC5opd62gynyfce3/gqCouVFynEHKCduwOzV0HEYdT6PQYpqn8wC0mJyMEsnMO1 wvCYNsyEuz6FDqy6XHXA1CQ7CXhyVmWnT+8qk7q9RDisItoBovK64EwsRYVns87bmzHjBc8oDRex HaBTmIMTjgWhZFZKVIQtD0qMCAKMVjV+nY7eU3XDxnOiSOzK7EXD0js/nKBG8+sKyPvCfSLj2lmR PZknKL5sBCM8oFcHONdVqKknEiBEjeRGmdwtE+FuoGhAxm2i4LUL6yJv8iKhum59PJpgHW02tRli qB1di/FSuW7B6i63vKnL2e2DW/tO3+IdzgzEmsgN6OuTSBpEsMgZyiq89uIMmcqz0N3ToOjuEBL4 SMHl3OSAR2KQm9UKRIHzayfULJnQEeiX7yagpastb+PqXF2PcM X-QQ-XMRINFO: M/715EihBoGSf6IYSX1iLFg= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 4/8] RISC-V: Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P Date: Tue, 5 Nov 2024 11:22:29 +0800 X-OQ-MSGID: <20241105032229.2645803-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch implements the TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P for RISC-V. This hook is used to process attribute ((target_version ("..."))). As it is the first patch which introduces the target_version attribute, we also set TARGET_HAS_FMV_TARGET_ATTRIBUTE to 0 to use "target_version" for function versioning. Co-Developed-by: Hank Chang Signed-off-by: Yangyu Chen gcc/ChangeLog: * config/riscv/riscv-protos.h (riscv_process_target_attr): Remove as it is not used. (riscv_option_valid_version_attribute_p): Declare. (riscv_process_target_version_attr): Declare. * config/riscv/riscv-target-attr.cc (riscv_target_attrs): Renamed from riscv_attributes. (riscv_target_version_attrs): New attributes for target_version. (riscv_process_one_target_attr): New arguments to select attrs. (riscv_process_target_attr): Likewise. (riscv_option_valid_attribute_p): Likewise. (riscv_process_target_version_attr): New function. (riscv_option_valid_version_attribute_p): New function. * config/riscv/riscv.cc (TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P): Implement it. * config/riscv/riscv.h (TARGET_HAS_FMV_TARGET_ATTRIBUTE): Define it to 0 to use "target_version" for function versioning. --- gcc/config/riscv/riscv-protos.h | 4 +- gcc/config/riscv/riscv-target-attr.cc | 118 +++++++++++++++++++++++--- gcc/config/riscv/riscv.cc | 4 + gcc/config/riscv/riscv.h | 2 + 4 files changed, 115 insertions(+), 13 deletions(-) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 4ed04321d32..500b357f6eb 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -806,7 +806,9 @@ void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int); extern bool riscv_option_valid_attribute_p (tree, tree, tree, int); extern bool -riscv_process_target_attr (const char *, location_t); +riscv_option_valid_version_attribute_p (tree, tree, tree, int); +extern bool +riscv_process_target_version_attr (tree, location_t); extern void riscv_override_options_internal (struct gcc_options *); extern void riscv_option_override (void); diff --git a/gcc/config/riscv/riscv-target-attr.cc b/gcc/config/riscv/riscv-target-attr.cc index 293d5321215..2979d63a011 100644 --- a/gcc/config/riscv/riscv-target-attr.cc +++ b/gcc/config/riscv/riscv-target-attr.cc @@ -82,10 +82,16 @@ struct riscv_attribute_info /* The target attributes that we support. */ -static const struct riscv_attribute_info riscv_attributes[] +static const struct riscv_attribute_info riscv_target_attrs[] = {{"arch", &riscv_target_attr_parser::handle_arch}, {"cpu", &riscv_target_attr_parser::handle_cpu}, - {"tune", &riscv_target_attr_parser::handle_tune}}; + {"tune", &riscv_target_attr_parser::handle_tune}, + {NULL, NULL}}; + +static const struct riscv_attribute_info riscv_target_version_attrs[] + = {{"arch", &riscv_target_attr_parser::handle_arch}, + {"priority", &riscv_target_attr_parser::handle_priority}, + {NULL, NULL}}; bool riscv_target_attr_parser::parse_arch (const char *str) @@ -268,7 +274,8 @@ riscv_target_attr_parser::update_settings (struct gcc_options *opts) const static bool riscv_process_one_target_attr (char *arg_str, location_t loc, - riscv_target_attr_parser &attr_parser) + riscv_target_attr_parser &attr_parser, + const struct riscv_attribute_info *attrs) { size_t len = strlen (arg_str); @@ -295,15 +302,17 @@ riscv_process_one_target_attr (char *arg_str, arg[0] = '\0'; ++arg; - for (const auto &attr : riscv_attributes) + for (const auto *attr = attrs; + attr->name; + ++attr) { /* If the names don't match up, or the user has given an argument to an attribute that doesn't accept one, or didn't give an argument to an attribute that expects one, fail to match. */ - if (strncmp (str_to_check, attr.name, strlen (attr.name)) != 0) + if (strncmp (str_to_check, attr->name, strlen (attr->name)) != 0) continue; - return (&attr_parser->*attr.handler) (arg); + return (&attr_parser->*attr->handler) (arg); } error_at (loc, "Got unknown attribute %", str_to_check); @@ -332,7 +341,9 @@ num_occurrences_in_str (char c, char *str) and update the global target options space. */ bool -riscv_process_target_attr (const char *args, location_t loc) +riscv_process_target_attr (const char *args, + location_t loc, + const struct riscv_attribute_info *attrs) { size_t len = strlen (args); @@ -359,7 +370,7 @@ riscv_process_target_attr (const char *args, location_t loc) while (token) { num_attrs++; - if (!riscv_process_one_target_attr (token, loc, attr_parser)) + if (!riscv_process_one_target_attr (token, loc, attr_parser, attrs)) return false; token = strtok_r (NULL, ";", &str_to_check); @@ -382,7 +393,9 @@ riscv_process_target_attr (const char *args, location_t loc) and update the global target options space. */ static bool -riscv_process_target_attr (tree args, location_t loc) +riscv_process_target_attr (tree args, + location_t loc, + const struct riscv_attribute_info *attrs) { if (TREE_CODE (args) == TREE_LIST) { @@ -391,7 +404,7 @@ riscv_process_target_attr (tree args, location_t loc) tree head = TREE_VALUE (args); if (head) { - if (!riscv_process_target_attr (head, loc)) + if (!riscv_process_target_attr (head, loc, attrs)) return false; } args = TREE_CHAIN (args); @@ -406,7 +419,7 @@ riscv_process_target_attr (tree args, location_t loc) return false; } - return riscv_process_target_attr (TREE_STRING_POINTER (args), loc); + return riscv_process_target_attr (TREE_STRING_POINTER (args), loc, attrs); } /* Implement TARGET_OPTION_VALID_ATTRIBUTE_P. @@ -444,7 +457,7 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int) TREE_TARGET_OPTION (target_option_default_node)); /* Now we can parse the attributes and set &global_options accordingly. */ - ret = riscv_process_target_attr (args, loc); + ret = riscv_process_target_attr (args, loc, riscv_target_attrs); if (ret) { riscv_override_options_internal (&global_options); @@ -457,3 +470,84 @@ riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int) cl_target_option_restore (&global_options, &global_options_set, &cur_target); return ret; } + +/* Parse the tree in ARGS that contains the target_version attribute + information and update the global target options space. */ + +bool +riscv_process_target_version_attr (tree args, location_t loc) +{ + if (TREE_CODE (args) == TREE_LIST) + { + if (TREE_CHAIN (args)) + { + error ("attribute % has multiple values"); + return false; + } + args = TREE_VALUE (args); + } + + if (!args || TREE_CODE (args) != STRING_CST) + { + error ("attribute % argument not a string"); + return false; + } + + const char *str = TREE_STRING_POINTER (args); + if (strcmp (str, "default") == 0) + return true; + + return riscv_process_target_attr (str, loc, riscv_target_version_attrs); +} + + +/* Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P. This is used to + process attribute ((target_version ("..."))). */ + +bool +riscv_option_valid_version_attribute_p (tree fndecl, tree, tree args, int) +{ + struct cl_target_option cur_target; + bool ret; + tree new_target; + tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + location_t loc = DECL_SOURCE_LOCATION (fndecl); + + /* Save the current target options to restore at the end. */ + cl_target_option_save (&cur_target, &global_options, &global_options_set); + + /* If fndecl already has some target attributes applied to it, unpack + them so that we add this attribute on top of them, rather than + overwriting them. */ + if (existing_target) + { + struct cl_target_option *existing_options + = TREE_TARGET_OPTION (existing_target); + + if (existing_options) + cl_target_option_restore (&global_options, &global_options_set, + existing_options); + } + else + cl_target_option_restore (&global_options, &global_options_set, + TREE_TARGET_OPTION (target_option_current_node)); + + ret = riscv_process_target_version_attr (args, loc); + + /* Set up any additional state. */ + if (ret) + { + riscv_override_options_internal (&global_options); + new_target = build_target_option_node (&global_options, + &global_options_set); + } + else + new_target = NULL; + + if (fndecl && ret) + DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; + + cl_target_option_restore (&global_options, &global_options_set, &cur_target); + + return ret; +} diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 2e9ac280c8f..07553d036a3 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -13079,6 +13079,10 @@ riscv_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P riscv_use_by_pieces_infrastructure_p +#undef TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P +#define TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P \ + riscv_option_valid_version_attribute_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 2ff9c1024f3..8a8b08b6b51 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1303,4 +1303,6 @@ extern void riscv_remove_unneeded_save_restore_calls (void); the target attribute. */ #define TARGET_CLONES_ATTR_SEPARATOR '#' +#define TARGET_HAS_FMV_TARGET_ATTRIBUTE 0 + #endif /* ! GCC_RISCV_H */ From patchwork Tue Nov 5 03:22:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006606 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=lBainjqC; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDHg6RYsz1xxb for ; Tue, 5 Nov 2024 14:25:35 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 051B6385734E for ; Tue, 5 Nov 2024 03:25:34 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-216.mail.qq.com (out162-62-58-216.mail.qq.com [162.62.58.216]) by sourceware.org (Postfix) with UTF8SMTPS id 950683857003 for ; Tue, 5 Nov 2024 03:22:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 950683857003 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 950683857003 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.216 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776979; cv=none; b=smA60YlmmsLttAHanTKA85CzUtRaGwunzjY3dVTGbKyUWxDY6/1slcHYRiOiDe9GnxmlYgPlZFzsaa2Wylpb7ZORjMRStLOjCizLotKdxAkNuEkc8T+7os8F+40DQVII0A3nARqNfmMFSPaj+7mjNz4PQJ78YUs/vh0d4CcvtNU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776979; c=relaxed/simple; bh=Lk4QmKHz/DVT96bmS2LrJc3yHZDQpD6XPbBduevodvE=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=BfQX7QtFocWNFboXVa3DjRkVQqyuDGAMsC+RA3xe3aFH8DtVXOpbG1ZF+3G1oP77+/FdCR3GHGFvEAZutOYwrgBx+xA0O+CHJS2gTxL1jO4xydPouHsxFGrobFicbQWC9hblxEoR8oKznFVjo2nEK6CTQUMRXk9yHihp0zzoJ8I= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730776971; bh=6Ooab0gQ9gC9b/v5QLd9UoCenSUpW0jke8e95Hb7pOE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=lBainjqCg8gE/m8ONvmSOBbJS2senf2jcFRFgAg2YtcrLM5ECZvDF8iB0naQisYyZ KfZod8nabRRejm+g4IpDKZTmrBhTe318wcqtNDdST2tWMFVg8hoFpqiu1+7T+LbVyB 3mym4IrMwy8UsyorFJmG35Y/7EO0jdv/NDF+DwxQ= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrsza29-0.qq.com (NewEsmtp) with SMTP id 5AF8821B; Tue, 05 Nov 2024 11:22:47 +0800 X-QQ-mid: xmsmtpt1730776967t2v803b1s Message-ID: X-QQ-XMAILINFO: MILSKRzDrLPbH1zAP4ZVKMKSZrWUU4Q/9l86lOgllKFwZKm+BEcYFZg+9XSDQA XaYnFBsFPd8Syx5Fu4lv9AY0L5yQH+DKvLm+a4V6/7IALoP2lx8pCf4L1acHbiSKSxkoSCc+fNcj OFF0WW+UtJfzJm7IsKanje9BQw6TyCQvJMAgDOOkQKEsvHT0JTizIKWuhrBXOkRbmsJwcsTYGtdo flATCzN0odWfptqdFCWFtIQRS3anNUNqx/w6TUH1NdwcIdShwuOkeYH9VyGDXeE0Op0N4xVrhUhK 1JGmayuseHXZQCjfrZGZGJKl0b5xeHyjD2pd3mQvShSJMptXhWmg/TxJCKGFmBqTxGVPgBAvKomi bGic0s5SxCZZRYER3WZNrmeOCHJU61I1+9Ef3XmVpkf2/B5IXE45sG3EYGsQwfnLZzxUws/Ku4/5 QKFWYaXiQnY8qQcsikbZErFPxtisELOn+2Nnb9US1lGnJFqWeBCbrWl9wgBhJTFrUXJyLdxJ+k+6 2Zi1CtS9leUtfJ9FnobHJCmonDIbwL8OM4HMu2CC9WlxCefvvPQeieBwcki+ZDQ8Plbu6+B0yTcy 4ZkU9b56PHbeq8I1bVsqxfJs6AiAsEUIma5vMoIP54umZRzI0nPxMF60e0K6tLgsFOw8cyUHBc8x QCDA86rzj3xdk95oaDjn+/bit5j2LIUb9tAa+RFoBX/8eu2lA3ZMNGP30dt7hQ3xQp4LRk/gt950 VqAcu/FCQ2e35lC1IeYG9Lq0PItoKD/DvimRB+mGIuwhceDee76Jre9ub6QCozV83TR6JNxL8l3b GcNli5c+K1LgFCYLYIRCgF5OE5HEY8+GcXG0rcoHeFPVlXcygTT5Cv8nVOx60sVhUC2hNzUzOG2N I/OFvfrks2ylK1GwlrkDRCCjsqfumea3+BmA9UKT1PYLh9tXO1/qbZL1KIeQrzueDjUTUggHRXXw +d+g/BlMZ10O5wRBM90EBJaNXYEtOlKWkOApPhw8M4lkXK7PsdxwEZSVDT4QQbKVgsFoa3TP4= X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 5/8] RISC-V: Implement TARGET_COMPARE_VERSION_PRIORITY and TARGET_OPTION_FUNCTION_VERSIONS Date: Tue, 5 Nov 2024 11:22:45 +0800 X-OQ-MSGID: <20241105032245.2645957-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch implements TARGET_COMPARE_VERSION_PRIORITY and TARGET_OPTION_FUNCTION_VERSIONS for RISC-V. The TARGET_COMPARE_VERSION_PRIORITY is implemented to compare the priority of two function versions based on the rules defined in the RISC-V C-API Doc PR #85: https://github.com/riscv-non-isa/riscv-c-api-doc/pull/85/files#diff-79a93ca266139524b8b642e582ac20999357542001f1f4666fbb62b6fb7a5824R721 If multiple versions have equal priority, we select the function with the most number of feature bits generated by riscv_minimal_hwprobe_feature_bits. When it comes to the same number of feature bits, we diff two versions and select the one with the least significant bit set. Since a feature appears earlier in the feature_bits might be more important to performance. The TARGET_OPTION_FUNCTION_VERSIONS is implemented to check whether the two function versions are the same. This Implementation reuses the code in TARGET_COMPARE_VERSION_PRIORITY and check it returns 0, which means the equal priority. Co-Developed-by: Hank Chang Signed-off-by: Yangyu Chen gcc/ChangeLog: * config/riscv/riscv.cc (parse_features_for_version): New function. (compare_fmv_features): New function. (riscv_compare_version_priority): New function. (riscv_common_function_versions): New function. (TARGET_COMPARE_VERSION_PRIORITY): Implement it. (TARGET_OPTION_FUNCTION_VERSIONS): Implement it. --- gcc/config/riscv/riscv.cc | 127 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 07553d036a3..b7eec1654d4 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -12686,6 +12686,127 @@ riscv_c_mode_for_floating_type (enum tree_index ti) return default_mode_for_floating_type (ti); } +/* This parses the attribute arguments to target_version in DECL and modifies + the feature mask and priority required to select those targets. */ +static void +parse_features_for_version (tree decl, + struct riscv_feature_bits &res, + int &priority) +{ + tree version_attr = lookup_attribute ("target_version", + DECL_ATTRIBUTES (decl)); + if (version_attr == NULL_TREE) + { + res.length = 0; + priority = 0; + return; + } + + const char *version_string = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE + (version_attr))); + gcc_assert (version_string != NULL); + if (strcmp (version_string, "default") == 0) + { + res.length = 0; + priority = 0; + return; + } + struct cl_target_option cur_target; + cl_target_option_save (&cur_target, &global_options, + &global_options_set); + /* Always set to default option before parsing "arch=+..." */ + struct cl_target_option *default_opts + = TREE_TARGET_OPTION (target_option_default_node); + cl_target_option_restore (&global_options, &global_options_set, + default_opts); + + riscv_process_target_version_attr (TREE_VALUE (version_attr), + DECL_SOURCE_LOCATION (decl)); + + priority = global_options.x_riscv_fmv_priority; + const char *arch_string = global_options.x_riscv_arch_string; + bool parse_res + = riscv_minimal_hwprobe_feature_bits (arch_string, &res, + DECL_SOURCE_LOCATION (decl)); + gcc_assert (parse_res); + + if (arch_string != default_opts->x_riscv_arch_string) + free (CONST_CAST (void *, (const void *) arch_string)); + + cl_target_option_restore (&global_options, &global_options_set, + &cur_target); +} + +/* Compare priorities of two feature masks. Return: + 1: mask1 is higher priority + -1: mask2 is higher priority + 0: masks are equal. + Since riscv_feature_bits has total 128 bits to be used as mask, when counting + the total 1s in the mask, the 1s in group1 needs to multiply a weight. */ +static int +compare_fmv_features (const struct riscv_feature_bits &mask1, + const struct riscv_feature_bits &mask2, + int prio1, int prio2) +{ + unsigned length1 = mask1.length, length2 = mask2.length; + /* 1. Compare length, for length == 0 means default version, which should be + the lowest priority). */ + if (length1 != length2) + return length1 > length2 ? 1 : -1; + /* 2. Compare the priority. */ + if (prio1 != prio2) + return prio1 > prio2 ? 1 : -1; + /* 3. Compare the total number of 1s in the mask. */ + unsigned pop1 = 0, pop2 = 0; + for (unsigned i = 0; i < length1; i++) + { + pop1 += __builtin_popcountll (mask1.features[i]); + pop2 += __builtin_popcountll (mask2.features[i]); + } + if (pop1 != pop2) + return pop1 > pop2 ? 1 : -1; + /* 4. Compare the mask bit by bit order. */ + for (unsigned i = 0; i < length1; i++) + { + unsigned long long xor_mask = mask1.features[i] ^ mask2.features[i]; + if (xor_mask == 0) + continue; + return TEST_BIT (mask1.features[i], __builtin_ctzll (xor_mask)) ? 1 : -1; + } + /* 5. If all bits are equal, return 0. */ + return 0; +} + +/* Compare priorities of two version decls. Return: + 1: mask1 is higher priority + -1: mask2 is higher priority + 0: masks are equal. */ +int +riscv_compare_version_priority (tree decl1, tree decl2) +{ + struct riscv_feature_bits mask1, mask2; + int prio1, prio2; + + parse_features_for_version (decl1, mask1, prio1); + parse_features_for_version (decl2, mask2, prio2); + + return compare_fmv_features (mask1, mask2, prio1, prio2); +} + +/* This function returns true if FN1 and FN2 are versions of the same function, + that is, the target_version attributes of the function decls are different. + This assumes that FN1 and FN2 have the same signature. */ + +bool +riscv_common_function_versions (tree fn1, tree fn2) +{ + if (TREE_CODE (fn1) != FUNCTION_DECL + || TREE_CODE (fn2) != FUNCTION_DECL) + return false; + + return riscv_compare_version_priority (fn1, fn2) != 0; +} + /* On riscv we have an ABI defined safe buffer. This constant is used to determining the probe offset for alloca. */ @@ -13083,6 +13204,12 @@ riscv_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, #define TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P \ riscv_option_valid_version_attribute_p +#undef TARGET_COMPARE_VERSION_PRIORITY +#define TARGET_COMPARE_VERSION_PRIORITY riscv_compare_version_priority + +#undef TARGET_OPTION_FUNCTION_VERSIONS +#define TARGET_OPTION_FUNCTION_VERSIONS riscv_common_function_versions + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" From patchwork Tue Nov 5 03:22:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006602 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=qotjGrlt; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDFd585Rz1xyD for ; Tue, 5 Nov 2024 14:23:49 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DC590385703B for ; Tue, 5 Nov 2024 03:23:47 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-211.mail.qq.com (out162-62-58-211.mail.qq.com [162.62.58.211]) by sourceware.org (Postfix) with UTF8SMTPS id A560A385773C for ; Tue, 5 Nov 2024 03:23:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A560A385773C Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A560A385773C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.211 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776992; cv=none; b=aoK2pp1Z9lxSqWYiGSYkKg78YIZwN99e5ESmVTX6aPnv0dA32b1OGSVDyDu7rFSV3+6U1qWAZUf3UDgkoI2AT/cR3EUdVTzo4yMw6C22wwyvfTCnAD4ZAvAg8b2hDocpZ1ReenvAq9t7PK10ZtWFf8rygMmU6+cD02Lp9KnQWYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730776992; c=relaxed/simple; bh=jRG+OTFMY65Sumr4zKXdRLeM7CjACDaOtA6UM1Wz7Qk=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=NJek8x9DV4gqvcADyFNKm/cfjXZDbi+KhZ2mtwyMUbUby/wGN4223eVsI5K6E+xCcA2pTpe8ew7bGR+FR1VlwTVGITWggqPu3BSgrqEwtC9x9t6o4pHE4ZU/xaXTdmvvrXzzuqBd/8Yg3zY2egcr9QFCkK0x/tTXPpfrvH7qk5U= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730776981; bh=tJ6vX/pFyWR3gNZvmdOT74H2+MPV8rdjxOSueigB4kU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=qotjGrltuYXJlYuvYrDfEDFdUCclbJJnX4FB/h5HvVwr0avH/8A0BuyEmIQM3dLOw yi7gaXHcVq776qsKz5vq3+KWwpNfshKzjnvNVzpve+PDmKPqR1MP6bGWcsJ7uaiIkZ /0diXbG5qvXQSTcpa0QNf1MFBYw5nieLcEvSBE8E= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrsza36-0.qq.com (NewEsmtp) with SMTP id 5BA3D070; Tue, 05 Nov 2024 11:22:58 +0800 X-QQ-mid: xmsmtpt1730776978tbxmbblq2 Message-ID: X-QQ-XMAILINFO: ODafEzNm5Exj1TmE9R9hpnVIpy73RM5KDN/mHjFVBC8QY1sr3txdEj2lYdXLws ihTwCZX1ba8unyfymDHTmZav4Nu/VFskkEC3Q6h1n9CsdKadoHrSLVdg7ff+w8SB1m/khDct8cHp 1OirThIZquKJ00dTg7E6mdiyeBnQnMyabDqueqVQdvUxxLicT2ftgsPBtoajDxEzKulZ4R9eZQvJ Wksu7XdsrOqurRzbMjSTxCw/hNlwXCNrANLIAzaByiDnyj/qVxY/MtI4e1O74u2gvPtc1ooxhFI1 HsN71+iot3wbqqv82jo7AoBBEutrl4FlE0G7P0XSbHhBrjF3mfuQFwUaS16/uiBSNN6WophWzCLu r0gIkmcea8CrOOZtzsWonu6e6NOmNltWYYAEaqBo2WqgD3Tpg8WQWaX0E0EGiHIkAFl9UfnDGvsp skr2pdzyxWVDiRkQovVgBILKoN9G/ZqlNvDMrZrGiY8p2GYMnP8CB4ATd13FY7eTY1qFHdzB0BEb QRDuh2BSQyDzO+SSKHmsfBP2LFYvtmsaCcD7OlzTFjJmFXcytr/Qzfuj82QxZbH9dsnA2xvYFzV2 lPjfISEJ4uC+kDmkDp0kSPvzr8iBeTsXBq++uFFHEZFgjn6VL9g7vXjDtdgHoUU85SbifSJkabXX mVf7Q/EkcEWGLKHLARvngLigaFtneGDjRQVjm+QcoxZuUmU6fAYaw29ChR3y2SxIJneTsORTpnCH PgM583xbpI8Pg9BoKg6RTVGA9x8RbMhgXm2Kup6lw2ebpI4KamyBPa45vM3bclx6/+24eyplUBmc xuNgX3ySNhrp7LGXf+FnDeeHRzrAOLZWFYVW+aWFnSfq7HJGuDQHO+aOEptzSlxzAb5DxWZ/1Jg/ EEvwoRtVxsA50QnyPRUwwWDm3JvMweOK/T9/7por+CWRVcsZcaYXi6F89OkVYlZOb2ykfID8m9YP gbqZ5RmD/bxKd/spotAFqmpGXcWsrsIDVQdxCJK6Mjwmu8mOigqk3iMvRgNMepGVZLmz12yTrCxA LGw2OKSCxWm2NkEN3Ut75q4Y1+XAtzUWvTLGe6OQ== X-QQ-XMRINFO: MPJ6Tf5t3I/ycC2BItcBVIA= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 6/8] RISC-V: Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME Date: Tue, 5 Nov 2024 11:22:56 +0800 X-OQ-MSGID: <20241105032256.2646087-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch implements the TARGET_MANGLE_DECL_ASSEMBLER_NAME for RISC-V. This is used to add function multiversioning suffixes to the assembler name. Signed-off-by: Yangyu Chen gcc/ChangeLog: * config/riscv/riscv.cc (riscv_mangle_decl_assembler_name): New function. (TARGET_MANGLE_DECL_ASSEMBLER_NAME): Define. --- gcc/config/riscv/riscv.cc | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b7eec1654d4..f47b439df38 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -12807,6 +12807,42 @@ riscv_common_function_versions (tree fn1, tree fn2) return riscv_compare_version_priority (fn1, fn2) != 0; } +/* Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME, to add function multiversioning + suffixes. */ + +tree +riscv_mangle_decl_assembler_name (tree decl, tree id) +{ + /* For function version, add the target suffix to the assembler name. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_FUNCTION_VERSIONED (decl)) + { + std::string name = IDENTIFIER_POINTER (id) + std::string ("."); + tree target_attr = lookup_attribute ("target_version", + DECL_ATTRIBUTES (decl)); + + if (target_attr == NULL_TREE) + { + name += "default"; + return get_identifier (name.c_str ()); + } + + const char *version_string = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE + (target_attr))); + + /* Replace non-alphanumeric characters with underscores as the suffix. */ + for (const char *c = version_string; *c; c++) + name += ISALNUM (*c) == 0 ? '_' : *c; + + if (DECL_ASSEMBLER_NAME_SET_P (decl)) + SET_DECL_RTL (decl, NULL); + + id = get_identifier (name.c_str ()); + } + + return id; +} + /* On riscv we have an ABI defined safe buffer. This constant is used to determining the probe offset for alloca. */ @@ -13210,6 +13246,9 @@ riscv_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, #undef TARGET_OPTION_FUNCTION_VERSIONS #define TARGET_OPTION_FUNCTION_VERSIONS riscv_common_function_versions +#undef TARGET_MANGLE_DECL_ASSEMBLER_NAME +#define TARGET_MANGLE_DECL_ASSEMBLER_NAME riscv_mangle_decl_assembler_name + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" From patchwork Tue Nov 5 03:23:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006605 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=NlFbT+yj; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDH86jxqz1xyD for ; Tue, 5 Nov 2024 14:25:08 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1EE3B3857734 for ; Tue, 5 Nov 2024 03:25:07 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-211.mail.qq.com (out162-62-58-211.mail.qq.com [162.62.58.211]) by sourceware.org (Postfix) with UTF8SMTPS id 0D74C385735B for ; Tue, 5 Nov 2024 03:24:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0D74C385735B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0D74C385735B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.211 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730777076; cv=none; b=aNcYphESz/qo2hSU11rKKWL+lGz0WkTuH4dGxOXlgnewheueyZMmpHsPcpl3QyiVWOTMlvtOR1n8pUpQeZ6mIwIoAdG60sBVzWUGiEoJbRpEI0JZo3SxpBILmqbNRx663Um076YyZMheqNQ+3yRmjexfMlpzk7s5qZ+cXtylIVg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730777076; c=relaxed/simple; bh=UwvXKMV7t+8lXJ/Eg7hP6js8ZWaY6zFQUdarN4tMKI4=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=uxxzxzLjdTqVuzuHTtCAepSTsNcl0RVURZxFvr4uvaKvR47ofNJqOVnxTyqvpvlD6Dm8+nuHemIdc5/SOSA6u+s8ecsykdtFuwqTViIY/QdPY3XyXTKqLgSWyUwozy/YCIlTugb+DY/t6pEe2q5JDOPI1hVnIQhWUGPl8yqBMaQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730777065; bh=/+HmtOzP1QMjVS554+YjO1/wW7vP2pgf/89jaXzIkgc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=NlFbT+yjAZsmbZG30hrSrGVnH99YKVhkyhemJZeccwVwO+c3pU43JfBWyHn4KtGHJ w83V0T5Dixl5fAVrL4uRu1grP8AtXAnMlPmw4uzWu7TdcfWDGEGmdZaQE7zdBRD7wU 4iHIXuLTolBU8mY9rpOxI5ZZOb8rRKfAMLyx2Zbg= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrszc25-0.qq.com (NewEsmtp) with SMTP id 5C817AAB; Tue, 05 Nov 2024 11:23:08 +0800 X-QQ-mid: xmsmtpt1730776988t7agzp7l6 Message-ID: X-QQ-XMAILINFO: MRMtjO3A6C9Xe6HjQ1Ou+WLwmiiDIKNT2tkKvYDHATy5nJuuhtF8OQUOz+ssPS Dw+Wc4m5bov+JcAQFcJBzwZryY1EoovpZ95wB7my+Iow4kaI9KTUQBIgvY2lfRKg00H9qN5aL/Cu uw/+RYiVukilcyCIuFXEpRpgfcJO3qnsXYsrxmF9fPy/8hW4DA4l+OQvFkgAx0tveEaLPIfTV4/2 M7oq5u8i7CnXkjXtOJLRx3lA6I0VPH3eoCE4hPjSBDiRG60x70e/uo4NjsXglj816XlOBUkrwrG3 enIyK4RI0giLcEcxCH8GMSYxmG0yE0hSv+1jV0nhO/nWQH7q6+hUV5+pM4OvZp8ovcdUYjd9GmBs IPrTitX47a5e5sAbQ1rr54gz9CgJYISvAgRYyVgt1MvbyaMMERsRnAmdfkaNQA/MzZB96N6c7idS WFexLhMXUuCdPxjN1gcI6jFjVbs3mfR5WjfVZQUGgNS/oPvnAEvtwLv3qPy76qsyLqyZFyYSwxPf 2ofIADwRJVVxr3v1/C297tHAn/tpnhylpuUi9bKgzZS4JIzuBieZ+YMNHahc3sxoavG8OH30mArp 5B7hCOF5MNLDSNXiZt5ig/cpo2VNMA/QrWbK+LspPtuv0cG9gIx9GjRvQUZn6nYH8XWhLRnVN86j /jG2Xj0Vv/F2Sap7G5aPmOvkJGJu5mfKy3+XfEs1Ze5MMvaldisE1tvzH9tlf31/UZVWneqVsn43 BmeQF0APwpVA3KiO3F2rtNRcif/6DAyRGP17X0LzInZEdyufm04vAYwe3xe/1k/0+jM8idYd9zIW dL1QDNfIaVJ+W0o49Kzqj6BaVSGq7qz2sN1q1GVQWx+kL8LgB4WBQKT+3ftdxdM/U1xpFOd4hD09 o9ZLX5khNO2MkBUCbV0g9+ILUeVZUNW9gq198bc/+tkOj0GVXjLH3OnDKdxdcOXX7WN7sgldjlxZ 6zEZl9fcyAm5t4WEcgUEnbiqMv/wNJ+vQMRp5/VbnqW8TkDvZdOcymu0YhUWtmmc+8jz5Dnnur75 E22vp0lwCX5Fe9fRf/X3GVOcDnUaLociedRHuz1Q== X-QQ-XMRINFO: Mp0Kj//9VHAxr69bL5MkOOs= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 7/8] RISC-V: Implement TARGET_GENERATE_VERSION_DISPATCHER_BODY and TARGET_GET_FUNCTION_VERSIONS_DISPATCHER Date: Tue, 5 Nov 2024 11:23:07 +0800 X-OQ-MSGID: <20241105032307.2646211-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch implements the TARGET_GENERATE_VERSION_DISPATCHER_BODY and TARGET_GET_FUNCTION_VERSIONS_DISPATCHER for RISC-V. This is used to generate the dispatcher function and get the dispatcher function for function multiversioning. This patch copies many codes from commit 0cfde688e213 ("[aarch64] Add function multiversioning support") and modifies them to fit the RISC-V port. A key difference is the data structure of feature bits in RISC-V C-API is a array of unsigned long long, while in AArch64 is not a array. So we need to generate the array reference for each feature bits element in the dispatcher function. Signed-off-by: Yangyu Chen gcc/ChangeLog: * config/riscv/riscv.cc (add_condition_to_bb): New function. (dispatch_function_versions): New function. (get_suffixed_assembler_name): New function. (make_resolver_func): New function. (riscv_generate_version_dispatcher_body): New function. (riscv_get_function_versions_dispatcher): New function. (TARGET_GENERATE_VERSION_DISPATCHER_BODY): Implement it. (TARGET_GET_FUNCTION_VERSIONS_DISPATCHER): Implement it. --- gcc/config/riscv/riscv.cc | 587 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 587 insertions(+) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index f47b439df38..d841edc4d16 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #define INCLUDE_MEMORY #define INCLUDE_STRING +#define INCLUDE_VECTOR +#define INCLUDE_ALGORITHM #include "config.h" #include "system.h" #include "coretypes.h" @@ -77,6 +79,9 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "target-globals.h" #include "riscv-v.h" +#include "cgraph.h" +#include "langhooks.h" +#include "gimplify.h" /* This file should be included last. */ #include "target-def.h" @@ -12843,6 +12848,580 @@ riscv_mangle_decl_assembler_name (tree decl, tree id) return id; } +/* This adds a condition to the basic_block NEW_BB in function FUNCTION_DECL + to return a pointer to VERSION_DECL if all feature bits specified in + FEATURE_MASK are not set in MASK_VAR. This function will be called during + version dispatch to decide which function version to execute. It returns + the basic block at the end, to which more conditions can be added. */ +static basic_block +add_condition_to_bb (tree function_decl, tree version_decl, + const struct riscv_feature_bits *features, + tree mask_var, basic_block new_bb) +{ + gimple *return_stmt; + tree convert_expr, result_var; + gimple *convert_stmt; + gimple *if_else_stmt; + + basic_block bb1, bb2, bb3; + edge e12, e23; + + gimple_seq gseq; + + push_cfun (DECL_STRUCT_FUNCTION (function_decl)); + + gcc_assert (new_bb != NULL); + gseq = bb_seq (new_bb); + + convert_expr = build1 (CONVERT_EXPR, ptr_type_node, + build_fold_addr_expr (version_decl)); + result_var = create_tmp_var (ptr_type_node); + convert_stmt = gimple_build_assign (result_var, convert_expr); + return_stmt = gimple_build_return (result_var); + + if (features->length == 0) + { + /* Default version. */ + gimple_seq_add_stmt (&gseq, convert_stmt); + gimple_seq_add_stmt (&gseq, return_stmt); + set_bb_seq (new_bb, gseq); + gimple_set_bb (convert_stmt, new_bb); + gimple_set_bb (return_stmt, new_bb); + pop_cfun (); + return new_bb; + } + + tree zero_llu = build_int_cst (long_long_unsigned_type_node, 0); + tree cond_status = create_tmp_var (boolean_type_node); + tree mask_array_ele_var = create_tmp_var (long_long_unsigned_type_node); + tree and_expr_var = create_tmp_var (long_long_unsigned_type_node); + tree eq_expr_var = create_tmp_var (boolean_type_node); + + /* cond_status = true. */ + gimple *cond_init_stmt = gimple_build_assign (cond_status, boolean_true_node); + gimple_set_block (cond_init_stmt, DECL_INITIAL (function_decl)); + gimple_set_bb (cond_init_stmt, new_bb); + gimple_seq_add_stmt (&gseq, cond_init_stmt); + + for (int i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++) + { + tree index_expr = build_int_cst (unsigned_type_node, i); + /* mask_array_ele_var = mask_var[i] */ + tree mask_array_ref = build4 (ARRAY_REF, long_long_unsigned_type_node, + mask_var, index_expr, NULL_TREE, NULL_TREE); + + gimple *mask_stmt = gimple_build_assign (mask_array_ele_var, + mask_array_ref); + gimple_set_block (mask_stmt, DECL_INITIAL (function_decl)); + gimple_set_bb (mask_stmt, new_bb); + gimple_seq_add_stmt (&gseq, mask_stmt); + /* and_expr_var = mask_array_ele_var & features[i] */ + tree and_expr = build2 (BIT_AND_EXPR, + long_long_unsigned_type_node, + mask_array_ele_var, + build_int_cst (long_long_unsigned_type_node, + features->features[i])); + gimple *and_stmt = gimple_build_assign (and_expr_var, and_expr); + gimple_set_block (and_stmt, DECL_INITIAL (function_decl)); + gimple_set_bb (and_stmt, new_bb); + gimple_seq_add_stmt (&gseq, and_stmt); + /* eq_expr_var = and_expr_var == 0. */ + tree eq_expr = build2 (EQ_EXPR, boolean_type_node, + and_expr_var, zero_llu); + gimple *eq_stmt = gimple_build_assign (eq_expr_var, eq_expr); + gimple_set_block (eq_stmt, DECL_INITIAL (function_decl)); + gimple_set_bb (eq_stmt, new_bb); + gimple_seq_add_stmt (&gseq, eq_stmt); + /* cond_status = cond_status & eq_expr_var. */ + tree cond_expr = build2 (BIT_AND_EXPR, boolean_type_node, + cond_status, eq_expr_var); + gimple *cond_stmt = gimple_build_assign (cond_status, cond_expr); + gimple_set_block (cond_stmt, DECL_INITIAL (function_decl)); + gimple_set_bb (cond_stmt, new_bb); + gimple_seq_add_stmt (&gseq, cond_stmt); + } + if_else_stmt = gimple_build_cond (EQ_EXPR, cond_status, boolean_true_node, + NULL_TREE, NULL_TREE); + gimple_set_block (if_else_stmt, DECL_INITIAL (function_decl)); + gimple_set_bb (if_else_stmt, new_bb); + gimple_seq_add_stmt (&gseq, if_else_stmt); + + gimple_seq_add_stmt (&gseq, convert_stmt); + gimple_seq_add_stmt (&gseq, return_stmt); + set_bb_seq (new_bb, gseq); + + bb1 = new_bb; + e12 = split_block (bb1, if_else_stmt); + bb2 = e12->dest; + e12->flags &= ~EDGE_FALLTHRU; + e12->flags |= EDGE_TRUE_VALUE; + + e23 = split_block (bb2, return_stmt); + + gimple_set_bb (convert_stmt, bb2); + gimple_set_bb (return_stmt, bb2); + + bb3 = e23->dest; + make_edge (bb1, bb3, EDGE_FALSE_VALUE); + + remove_edge (e23); + make_edge (bb2, EXIT_BLOCK_PTR_FOR_FN (cfun), 0); + + pop_cfun (); + + return bb3; +} + +/* This function generates the dispatch function for + multi-versioned functions. DISPATCH_DECL is the function which will + contain the dispatch logic. FNDECLS are the function choices for + dispatch, and is a tree chain. EMPTY_BB is the basic block pointer + in DISPATCH_DECL in which the dispatch code is generated. */ + +static int +dispatch_function_versions (tree dispatch_decl, + void *fndecls_p, + basic_block *empty_bb) +{ + gimple *ifunc_cpu_init_stmt; + gimple_seq gseq; + vec *fndecls; + + gcc_assert (dispatch_decl != NULL + && fndecls_p != NULL + && empty_bb != NULL); + + push_cfun (DECL_STRUCT_FUNCTION (dispatch_decl)); + + gseq = bb_seq (*empty_bb); + /* Function version dispatch is via IFUNC. IFUNC resolvers fire before + constructors, so explicity call __init_riscv_feature_bits here. */ + tree init_fn_type = build_function_type_list (void_type_node, + long_unsigned_type_node, + ptr_type_node, + NULL); + tree init_fn_id = get_identifier ("__init_riscv_feature_bits"); + tree init_fn_decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, + init_fn_id, init_fn_type); + DECL_EXTERNAL (init_fn_decl) = 1; + TREE_PUBLIC (init_fn_decl) = 1; + DECL_VISIBILITY (init_fn_decl) = VISIBILITY_HIDDEN; + DECL_VISIBILITY_SPECIFIED (init_fn_decl) = 1; + ifunc_cpu_init_stmt = gimple_build_call (init_fn_decl, 0); + gimple_seq_add_stmt (&gseq, ifunc_cpu_init_stmt); + gimple_set_bb (ifunc_cpu_init_stmt, *empty_bb); + + /* Build the struct type for __riscv_feature_bits. */ + tree global_type = lang_hooks.types.make_type (RECORD_TYPE); + tree features_type = build_array_type_nelts (long_long_unsigned_type_node, + RISCV_FEATURE_BITS_LENGTH); + tree field1 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, + get_identifier ("length"), + unsigned_type_node); + tree field2 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, + get_identifier ("features"), + features_type); + DECL_FIELD_CONTEXT (field1) = global_type; + DECL_FIELD_CONTEXT (field2) = global_type; + TYPE_FIELDS (global_type) = field1; + DECL_CHAIN (field1) = field2; + layout_type (global_type); + + tree global_var = build_decl (UNKNOWN_LOCATION, VAR_DECL, + get_identifier ("__riscv_feature_bits"), + global_type); + DECL_EXTERNAL (global_var) = 1; + TREE_PUBLIC (global_var) = 1; + DECL_VISIBILITY (global_var) = VISIBILITY_HIDDEN; + DECL_VISIBILITY_SPECIFIED (global_var) = 1; + tree mask_var = create_tmp_var (features_type); + tree feature_ele_var = create_tmp_var (long_long_unsigned_type_node); + tree noted_var = create_tmp_var (long_long_unsigned_type_node); + + + for (int i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++) + { + tree index_expr = build_int_cst (unsigned_type_node, i); + /* feature_ele_var = __riscv_feature_bits.features[i] */ + tree component_expr = build3 (COMPONENT_REF, features_type, + global_var, field2, NULL_TREE); + tree feature_array_ref = build4 (ARRAY_REF, long_long_unsigned_type_node, + component_expr, index_expr, + NULL_TREE, NULL_TREE); + gimple *feature_stmt = gimple_build_assign (feature_ele_var, + feature_array_ref); + gimple_set_block (feature_stmt, DECL_INITIAL (dispatch_decl)); + gimple_set_bb (feature_stmt, *empty_bb); + gimple_seq_add_stmt (&gseq, feature_stmt); + /* noted_var = ~feature_ele_var. */ + tree not_expr = build1 (BIT_NOT_EXPR, long_long_unsigned_type_node, + feature_ele_var); + gimple *not_stmt = gimple_build_assign (noted_var, not_expr); + gimple_set_block (not_stmt, DECL_INITIAL (dispatch_decl)); + gimple_set_bb (not_stmt, *empty_bb); + gimple_seq_add_stmt (&gseq, not_stmt); + /* mask_var[i] = noted_var. */ + tree mask_array_ref = build4 (ARRAY_REF, long_long_unsigned_type_node, + mask_var, index_expr, NULL_TREE, NULL_TREE); + gimple *mask_assign_stmt = gimple_build_assign (mask_array_ref, + noted_var); + gimple_set_block (mask_assign_stmt, DECL_INITIAL (dispatch_decl)); + gimple_set_bb (mask_assign_stmt, *empty_bb); + gimple_seq_add_stmt (&gseq, mask_assign_stmt); + } + + set_bb_seq (*empty_bb, gseq); + + pop_cfun (); + + /* fndecls_p is actually a vector. */ + fndecls = static_cast *> (fndecls_p); + + /* At least one more version other than the default. */ + unsigned int num_versions = fndecls->length (); + gcc_assert (num_versions >= 2); + + struct function_version_info + { + tree version_decl; + struct riscv_feature_bits features; + int prio; + }; + + std::vector function_versions; + + for (tree version_decl : *fndecls) + { + struct function_version_info version_info; + version_info.version_decl = version_decl; + // Get attribute string, parse it and find the right features. + parse_features_for_version (version_decl, + version_info.features, + version_info.prio); + function_versions.push_back (version_info); + } + + + auto compare_feature_version_info = [](const struct function_version_info &v1, + const struct function_version_info &v2) + { + return compare_fmv_features (v1.features, v2.features, + v1.prio, v2.prio) > 0; + }; + + /* Sort the versions according to descending order of dispatch priority. */ + std::sort (function_versions.begin (), function_versions.end (), + compare_feature_version_info); + + for (auto version : function_versions) + { + *empty_bb = add_condition_to_bb (dispatch_decl, + version.version_decl, + &version.features, + mask_var, + *empty_bb); + } + + return 0; +} + +/* Return an identifier for the base assembler name of a versioned function. + This is computed by taking the default version's assembler name, and + stripping off the ".default" suffix if it's already been appended. */ + +static tree +get_suffixed_assembler_name (tree default_decl, const char *suffix) +{ + std::string name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (default_decl)); + + auto size = name.size (); + if (size >= 8 && name.compare (size - 8, 8, ".default") == 0) + name.resize (size - 8); + name += suffix; + return get_identifier (name.c_str ()); +} + +/* Make the resolver function decl to dispatch the versions of + a multi-versioned function, DEFAULT_DECL. IFUNC_ALIAS_DECL is + ifunc alias that will point to the created resolver. Create an + empty basic block in the resolver and store the pointer in + EMPTY_BB. Return the decl of the resolver function. */ + +static tree +make_resolver_func (const tree default_decl, + const tree ifunc_alias_decl, + basic_block *empty_bb) +{ + tree decl, type, t; + + /* Create resolver function name based on default_decl. We need to remove an + existing ".default" suffix if this has already been appended. */ + tree decl_name = get_suffixed_assembler_name (default_decl, ".resolver"); + const char *resolver_name = IDENTIFIER_POINTER (decl_name); + + /* The resolver function should have signature + (void *) resolver (uint64_t, void *) */ + type = build_function_type_list (ptr_type_node, + uint64_type_node, + ptr_type_node, + NULL_TREE); + + decl = build_fn_decl (resolver_name, type); + SET_DECL_ASSEMBLER_NAME (decl, decl_name); + + DECL_NAME (decl) = decl_name; + TREE_USED (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_PUBLIC (decl) = 0; + DECL_UNINLINABLE (decl) = 1; + + /* Resolver is not external, body is generated. */ + DECL_EXTERNAL (decl) = 0; + DECL_EXTERNAL (ifunc_alias_decl) = 0; + + DECL_CONTEXT (decl) = NULL_TREE; + DECL_INITIAL (decl) = make_node (BLOCK); + DECL_STATIC_CONSTRUCTOR (decl) = 0; + + if (DECL_COMDAT_GROUP (default_decl) + || TREE_PUBLIC (default_decl)) + { + /* In this case, each translation unit with a call to this + versioned function will put out a resolver. Ensure it + is comdat to keep just one copy. */ + DECL_COMDAT (decl) = 1; + make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); + } + else + TREE_PUBLIC (ifunc_alias_decl) = 0; + + /* Build result decl and add to function_decl. */ + t = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, ptr_type_node); + DECL_CONTEXT (t) = decl; + DECL_ARTIFICIAL (t) = 1; + DECL_IGNORED_P (t) = 1; + DECL_RESULT (decl) = t; + + /* Build parameter decls and add to function_decl. */ + tree arg1 = build_decl (UNKNOWN_LOCATION, PARM_DECL, + get_identifier ("hwcap"), + uint64_type_node); + tree arg2 = build_decl (UNKNOWN_LOCATION, PARM_DECL, + get_identifier ("hwprobe_func"), + ptr_type_node); + DECL_CONTEXT (arg1) = decl; + DECL_CONTEXT (arg2) = decl; + DECL_ARTIFICIAL (arg1) = 1; + DECL_ARTIFICIAL (arg2) = 1; + DECL_IGNORED_P (arg1) = 1; + DECL_IGNORED_P (arg2) = 1; + DECL_ARG_TYPE (arg1) = uint64_type_node; + DECL_ARG_TYPE (arg2) = ptr_type_node; + DECL_ARGUMENTS (decl) = arg1; + TREE_CHAIN (arg1) = arg2; + + gimplify_function_tree (decl); + push_cfun (DECL_STRUCT_FUNCTION (decl)); + *empty_bb = init_lowered_empty_function (decl, false, + profile_count::uninitialized ()); + + cgraph_node::add_new_function (decl, true); + symtab->call_cgraph_insertion_hooks (cgraph_node::get_create (decl)); + + pop_cfun (); + + gcc_assert (ifunc_alias_decl != NULL); + /* Mark ifunc_alias_decl as "ifunc" with resolver as resolver_name. */ + DECL_ATTRIBUTES (ifunc_alias_decl) + = make_attribute ("ifunc", resolver_name, + DECL_ATTRIBUTES (ifunc_alias_decl)); + + /* Create the alias for dispatch to resolver here. */ + cgraph_node::create_same_body_alias (ifunc_alias_decl, decl); + return decl; +} + +/* Implement TARGET_GENERATE_VERSION_DISPATCHER_BODY. */ + +tree +riscv_generate_version_dispatcher_body (void *node_p) +{ + tree resolver_decl; + basic_block empty_bb; + tree default_ver_decl; + struct cgraph_node *versn; + struct cgraph_node *node; + + struct cgraph_function_version_info *node_version_info = NULL; + struct cgraph_function_version_info *versn_info = NULL; + + node = (cgraph_node *)node_p; + + node_version_info = node->function_version (); + gcc_assert (node->dispatcher_function + && node_version_info != NULL); + + if (node_version_info->dispatcher_resolver) + return node_version_info->dispatcher_resolver; + + /* The first version in the chain corresponds to the default version. */ + default_ver_decl = node_version_info->next->this_node->decl; + + /* node is going to be an alias, so remove the finalized bit. */ + node->definition = false; + + resolver_decl = make_resolver_func (default_ver_decl, + node->decl, &empty_bb); + + node_version_info->dispatcher_resolver = resolver_decl; + + push_cfun (DECL_STRUCT_FUNCTION (resolver_decl)); + + auto_vec fn_ver_vec; + + for (versn_info = node_version_info->next; versn_info; + versn_info = versn_info->next) + { + versn = versn_info->this_node; + /* Check for virtual functions here again, as by this time it should + have been determined if this function needs a vtable index or + not. This happens for methods in derived classes that override + virtual methods in base classes but are not explicitly marked as + virtual. */ + if (DECL_VINDEX (versn->decl)) + sorry ("virtual function multiversioning not supported"); + + fn_ver_vec.safe_push (versn->decl); + } + + dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb); + cgraph_edge::rebuild_edges (); + pop_cfun (); + + /* Fix up symbol names. First we need to obtain the base name, which may + have already been mangled. */ + tree base_name = get_suffixed_assembler_name (default_ver_decl, ""); + + /* We need to redo the version mangling on the non-default versions for the + target_clones case. Redoing the mangling for the target_version case is + redundant but does no harm. We need to skip the default version, because + expand_clones will append ".default" later; fortunately that suffix is the + one we want anyway. */ + for (versn_info = node_version_info->next->next; versn_info; + versn_info = versn_info->next) + { + tree version_decl = versn_info->this_node->decl; + tree name = riscv_mangle_decl_assembler_name (version_decl, + base_name); + symtab->change_decl_assembler_name (version_decl, name); + } + + /* We also need to use the base name for the ifunc declaration. */ + symtab->change_decl_assembler_name (node->decl, base_name); + + return resolver_decl; +} + +/* Make a dispatcher declaration for the multi-versioned function DECL. + Calls to DECL function will be replaced with calls to the dispatcher + by the front-end. Returns the decl of the dispatcher function. */ + +tree +riscv_get_function_versions_dispatcher (void *decl) +{ + tree fn = (tree) decl; + struct cgraph_node *node = NULL; + struct cgraph_node *default_node = NULL; + struct cgraph_function_version_info *node_v = NULL; + struct cgraph_function_version_info *first_v = NULL; + + tree dispatch_decl = NULL; + + struct cgraph_function_version_info *default_version_info = NULL; + + gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn)); + + node = cgraph_node::get (fn); + gcc_assert (node != NULL); + + node_v = node->function_version (); + gcc_assert (node_v != NULL); + + if (node_v->dispatcher_resolver != NULL) + return node_v->dispatcher_resolver; + + /* Find the default version and make it the first node. */ + first_v = node_v; + /* Go to the beginning of the chain. */ + while (first_v->prev != NULL) + first_v = first_v->prev; + default_version_info = first_v; + + while (default_version_info != NULL) + { + struct riscv_feature_bits res; + int priority; /* Unused. */ + parse_features_for_version (default_version_info->this_node->decl, + res, priority); + if (res.length == 0) + break; + default_version_info = default_version_info->next; + } + + /* If there is no default node, just return NULL. */ + if (default_version_info == NULL) + return NULL; + + /* Make default info the first node. */ + if (first_v != default_version_info) + { + default_version_info->prev->next = default_version_info->next; + if (default_version_info->next) + default_version_info->next->prev = default_version_info->prev; + first_v->prev = default_version_info; + default_version_info->next = first_v; + default_version_info->prev = NULL; + } + + default_node = default_version_info->this_node; + + if (targetm.has_ifunc_p ()) + { + struct cgraph_function_version_info *it_v = NULL; + struct cgraph_node *dispatcher_node = NULL; + struct cgraph_function_version_info *dispatcher_version_info = NULL; + + /* Right now, the dispatching is done via ifunc. */ + dispatch_decl = make_dispatcher_decl (default_node->decl); + TREE_NOTHROW (dispatch_decl) = TREE_NOTHROW (fn); + + dispatcher_node = cgraph_node::get_create (dispatch_decl); + gcc_assert (dispatcher_node != NULL); + dispatcher_node->dispatcher_function = 1; + dispatcher_version_info + = dispatcher_node->insert_new_function_version (); + dispatcher_version_info->next = default_version_info; + dispatcher_node->definition = 1; + + /* Set the dispatcher for all the versions. */ + it_v = default_version_info; + while (it_v != NULL) + { + it_v->dispatcher_resolver = dispatch_decl; + it_v = it_v->next; + } + } + else + { + error_at (DECL_SOURCE_LOCATION (default_node->decl), + "multiversioning needs % which is not supported " + "on this target"); + } + + return dispatch_decl; +} + /* On riscv we have an ABI defined safe buffer. This constant is used to determining the probe offset for alloca. */ @@ -13249,6 +13828,14 @@ riscv_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, #undef TARGET_MANGLE_DECL_ASSEMBLER_NAME #define TARGET_MANGLE_DECL_ASSEMBLER_NAME riscv_mangle_decl_assembler_name +#undef TARGET_GENERATE_VERSION_DISPATCHER_BODY +#define TARGET_GENERATE_VERSION_DISPATCHER_BODY \ + riscv_generate_version_dispatcher_body + +#undef TARGET_GET_FUNCTION_VERSIONS_DISPATCHER +#define TARGET_GET_FUNCTION_VERSIONS_DISPATCHER \ + riscv_get_function_versions_dispatcher + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" From patchwork Tue Nov 5 03:23:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2006603 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=qq.com header.i=@qq.com header.a=rsa-sha256 header.s=s201512 header.b=blh/VNpQ; dkim-atps=neutral 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=patchwork.ozlabs.org) 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 (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XjDFn5Slhz1xyD for ; Tue, 5 Nov 2024 14:23:57 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EE215385783B for ; Tue, 5 Nov 2024 03:23:55 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out162-62-58-211.mail.qq.com (out162-62-58-211.mail.qq.com [162.62.58.211]) by sourceware.org (Postfix) with UTF8SMTPS id 376563857830 for ; Tue, 5 Nov 2024 03:23:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 376563857830 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=cyyself.name Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cyyself.name ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 376563857830 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=162.62.58.211 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730777008; cv=none; b=k9wbIHkK9x9BHtZdvo7SEWgFt+oQr5sCYerreyxjl8e0Tr3MFi2FSDfdN6r7jNBB33S4MWlmH7n/agaCmqRV4qj+BPuglc+cIG+4ZK0/5qrnSQBzvmkUiZYVL+7Cio3953YQaA++5JqqCeNXcNknCsV288TyWrZEP5W0mWxJaBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730777008; c=relaxed/simple; bh=0PxguMCX8r4J60Qpualba3KK6ZXlp7is9nIDe7w9P8Y=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=A9lci1gnbDd/0fydn3TWoLhMY5jzvwzmuHTRDH6yccJnLjArfIRwDk4VXvlrdxTD6HPx6vmVA9+Wd2pfoD6IOMM9eOQL9Dv18jp5D8imSCLSILo/6lIzEyD05YPpfItqeDzscKGC2LURx8Sv8lFkU1eYskdF1TCByDkS62JKddQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730777001; bh=RHFlmZrfTCP4WcQHnTKocE/fAUltLDVbGwG0DSir3gQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=blh/VNpQMc2CTXLtd7x9uJ2rTpp6UOI208lm97YsuS+31gdoFlhDNLA3bTyGZ1DTa 9TxAnPDdL74Sx0gOhD3avtTGTaSeRQW/TlpqtLZUemLQTK1LwRxB+RFwc/jYxK8V3a nQVJD/KE3akj0flN3rZyuXUhs4Gz8IghRcHu9/lc= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrsza36-0.qq.com (NewEsmtp) with SMTP id 5D234E22; Tue, 05 Nov 2024 11:23:18 +0800 X-QQ-mid: xmsmtpt1730776998t5v5rid3f Message-ID: X-QQ-XMAILINFO: N/WmRbclY25GgSjUQdGBjjejAVOqC0V9by9wzqKa7XhJGXXKt0DJuVvkkXnZvL skDFud1Ln0D7ahWYfEE0qUf1KjwSE/0KuhmlT0uXA9xLPYZW8VfELLagYyKdER2pz70FFhbmDGai iBoDqmwpRTUZPAKYJxzzpa8njDy4BK07Kt9iC0g9Ogr1HiphmfXInSOBxRmNnmX6VGReY/Vcnjh5 ZM1+yMYDKFkgTz8VkWZ6lq+w2pPCeiobu33j0guA9qbx+V1i815XeD1Ye0feigndLRZ7GG8EdJ2p bYbiUGwM2UZ/jBpecbfJpg54ei14bJwTtYSubqlR986ByF8FaL9nkHDIDtpSYhZbIg9AgA1bSjjZ UjbPFyLkXHp9FZNUv6TJ7JT5r3aGfxnuheMPzfECFl2REV861nipaaBEViwGGiUyTwis0ehC0Iyu nU6t1J46oOedVbbnxDlrR8LC71VF5VfLt454kSu5qm4vl1IVstgyDXLL58Ia50qv/aD1/S7JEPKL MpzQ6cwLxzgFifUqP00a4yalkeFg5foRffm+uw74XUwk7yBvjF2H+HG0O3wVAfD/Ii8/Ed7qwkIW F9yXVjQg+oEH7e8UceKyeZPkONKsGZ4Oap4y+5RSjR+dP1ZyaFJYx3/Nm6xAKjfm+70RrKV3xvDX fm5HXgKO3utSi7G6DWHurLM65PRUgvoaMdEcNDmIzy6QUbwsZr5u5HOo5d2mA4brrPAzt9DwsNZK ChlNoYdBfUJJJZ6MmsvEZzbqeiJXOxFtVRWYnYk0qQMODUCKSRDhN++WjJy3bPduWqreJt2PTG09 /Un3yZX3iCCEyDGrsTGEmRbsD2A3puWzNxmKtRbjTYPyCwcGDOB8V36RfCmIBdIQqxPfmbOpNKQh l718vVXt2oYVOWNe1OLBzTUj9Rp7uxuTswuncaNqls5TX6+/0xe/aFo4fGiIVzh48ratrO5vj12f GUEb3NUzX2fnYRVowQzKLKeqoe6QrXJOxv4Y/a7/RQ9TD1DexVb3KxIDQnYzBz/7K70meSzQ9YA7 F6BvWIRy7LNqubJbTYn/ZeMyscllY= X-QQ-XMRINFO: MSVp+SPm3vtS1Vd6Y4Mggwc= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Hank Chang , Yangyu Chen Subject: [PATCH v5 8/8] RISC-V: Add Multi-Versioning Test Cases Date: Tue, 5 Nov 2024 11:23:16 +0800 X-OQ-MSGID: <20241105032316.2646322-1-cyy@cyyself.name> X-Mailer: git-send-email 2.45.2 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org This patch adds test cases for the Function Multi-Versioning (FMV) feature for RISC-V, which reuses the existing test cases from the aarch64 and ported them to RISC-V. Signed-off-by: Yangyu Chen gcc/testsuite/ChangeLog: * g++.target/riscv/mv-symbols1.C: New test. * g++.target/riscv/mv-symbols2.C: New test. * g++.target/riscv/mv-symbols3.C: New test. * g++.target/riscv/mv-symbols4.C: New test. * g++.target/riscv/mv-symbols5.C: New test. * g++.target/riscv/mvc-symbols1.C: New test. * g++.target/riscv/mvc-symbols2.C: New test. * g++.target/riscv/mvc-symbols3.C: New test. * g++.target/riscv/mvc-symbols4.C: New test. --- gcc/testsuite/g++.target/riscv/mv-symbols1.C | 70 +++++++++++++++++++ gcc/testsuite/g++.target/riscv/mv-symbols2.C | 61 ++++++++++++++++ gcc/testsuite/g++.target/riscv/mv-symbols3.C | 50 +++++++++++++ gcc/testsuite/g++.target/riscv/mv-symbols4.C | 56 +++++++++++++++ gcc/testsuite/g++.target/riscv/mv-symbols5.C | 62 ++++++++++++++++ gcc/testsuite/g++.target/riscv/mvc-symbols1.C | 49 +++++++++++++ gcc/testsuite/g++.target/riscv/mvc-symbols2.C | 36 ++++++++++ gcc/testsuite/g++.target/riscv/mvc-symbols3.C | 42 +++++++++++ gcc/testsuite/g++.target/riscv/mvc-symbols4.C | 32 +++++++++ 9 files changed, 458 insertions(+) create mode 100644 gcc/testsuite/g++.target/riscv/mv-symbols1.C create mode 100644 gcc/testsuite/g++.target/riscv/mv-symbols2.C create mode 100644 gcc/testsuite/g++.target/riscv/mv-symbols3.C create mode 100644 gcc/testsuite/g++.target/riscv/mv-symbols4.C create mode 100644 gcc/testsuite/g++.target/riscv/mv-symbols5.C create mode 100644 gcc/testsuite/g++.target/riscv/mvc-symbols1.C create mode 100644 gcc/testsuite/g++.target/riscv/mvc-symbols2.C create mode 100644 gcc/testsuite/g++.target/riscv/mvc-symbols3.C create mode 100644 gcc/testsuite/g++.target/riscv/mvc-symbols4.C diff --git a/gcc/testsuite/g++.target/riscv/mv-symbols1.C b/gcc/testsuite/g++.target/riscv/mv-symbols1.C new file mode 100644 index 00000000000..ea1a536fd00 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mv-symbols1.C @@ -0,0 +1,70 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +int foo () +{ + return 1; +} + +__attribute__((target_version("arch=+v"))) +int foo () +{ + return 3; +} +__attribute__((target_version("arch=+zba,+zbb"))) +int foo () +{ + return 5; +} + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (int) +{ + return 6; +} + +__attribute__((target_version("arch=+v"))) +int foo (int) +{ + return 4; +} + +int foo (int) +{ + return 2; +} + + +int bar() +{ + return foo (); +} + +int bar(int x) +{ + return foo (x); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mv-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 2 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 2 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\call\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\call\t_Z3fooi\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mv-symbols2.C b/gcc/testsuite/g++.target/riscv/mv-symbols2.C new file mode 100644 index 00000000000..43fa1502b7d --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mv-symbols2.C @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_version("default"))) +int foo () +{ + return 1; +} + +__attribute__((target_version("arch=+v"))) +int foo () +{ + return 3; +} +__attribute__((target_version("arch=+zba,+zbb"))) +int foo () +{ + return 5; +} + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (int) +{ + return 6; +} + +__attribute__((target_version("arch=+v"))) +int foo (int) +{ + return 4; +} + +__attribute__((target_version("default"))) +int foo (int) +{ + return 2; +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mv-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 2 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 2 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mv-symbols3.C b/gcc/testsuite/g++.target/riscv/mv-symbols3.C new file mode 100644 index 00000000000..4dc81cf7395 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mv-symbols3.C @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_version("default"))) +int foo (); + +__attribute__((target_version("arch=+v"))) +int foo (); + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (); + +__attribute__((target_version("default"))) +int foo (int); + +__attribute__((target_version("arch=+v"))) +int foo (int); + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (int); + + +int bar() +{ + return foo (); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mv-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 0 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mv-symbols4.C b/gcc/testsuite/g++.target/riscv/mv-symbols4.C new file mode 100644 index 00000000000..b0ed16a5eda --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mv-symbols4.C @@ -0,0 +1,56 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_version("default"))) +int foo () +{ + return 1; +} + +__attribute__((target_version("arch=+v"))) +int foo (); + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (); + +__attribute__((target_version("default"))) +int foo (int) +{ + return 2; +} + +__attribute__((target_version("arch=+v"))) +int foo (int); + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (int); + + +int bar() +{ + return foo (); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mv-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 0 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mv-symbols5.C b/gcc/testsuite/g++.target/riscv/mv-symbols5.C new file mode 100644 index 00000000000..f4c6b294e0f --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mv-symbols5.C @@ -0,0 +1,62 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_version("default"))) +int foo (); + +__attribute__((target_version("arch=+v"))) +int foo () +{ + return 3; +} + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo () +{ + return 5; +} + +__attribute__((target_version("default"))) +int foo (int); + +__attribute__((target_version("arch=+v"))) +int foo (int) +{ + return 4; +} + +__attribute__((target_version("arch=+zba,+zbb"))) +int foo (int) +{ + return 6; +} + + +int bar() +{ + return foo (); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mv-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 2 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 2 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mvc-symbols1.C b/gcc/testsuite/g++.target/riscv/mvc-symbols1.C new file mode 100644 index 00000000000..c78bc7cb64a --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mvc-symbols1.C @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_clones("default", "arch=+v", "arch=+zba,+zbb"))) +int foo () +{ + return 1; +} + +__attribute__((target_clones("arch=+zba,+zbb", "arch=+v", "default"))) +int foo (int) +{ + return 2; +} + + +int bar() +{ + return foo (); +} + +int bar(int x) +{ + return foo (x); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mvc-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 2 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 2 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mvc-symbols2.C b/gcc/testsuite/g++.target/riscv/mvc-symbols2.C new file mode 100644 index 00000000000..d7e1bd228f8 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mvc-symbols2.C @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_clones("default", "arch=+v", "arch=+zba,+zbb"))) +int foo () +{ + return 1; +} + +__attribute__((target_clones("arch=+zba,+zbb", "arch=+v", "default"))) +int foo (int) +{ + return 2; +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mvc-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 2 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 2 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mvc-symbols3.C b/gcc/testsuite/g++.target/riscv/mvc-symbols3.C new file mode 100644 index 00000000000..b36c3fa7a95 --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mvc-symbols3.C @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_clones("default", "arch=+v", "arch=+zba,+zbb"))) +int foo (); + +__attribute__((target_clones("arch=+zba,+zbb", "arch=+v", "default"))) +int foo (int); + +int bar() +{ + return foo (); +} + +int bar(int x) +{ + return foo (x); +} + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mvc-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 0 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 1 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 1 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 1 } } */ diff --git a/gcc/testsuite/g++.target/riscv/mvc-symbols4.C b/gcc/testsuite/g++.target/riscv/mvc-symbols4.C new file mode 100644 index 00000000000..e83b6d8368b --- /dev/null +++ b/gcc/testsuite/g++.target/riscv/mvc-symbols4.C @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0 -march=rv64gc -mabi=lp64" } */ + +__attribute__((target_clones("default", "arch=+v", "arch=+zba,+zbb"))) +int foo (); + +__attribute__((target_clones("arch=+zba,+zbb", "arch=+v", "default"))) +int foo (int); + +/* When updating any of the symbol names in these tests, make sure to also + update any tests for their absence in mvc-symbolsN.C */ + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0\"" } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0" 0 } } */ +/* { dg-final { scan-assembler-times ".option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zca1p0_zcd1p0_zba1p0_zbb1p0" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3foov\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3foov\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3foov\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3foov, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3foov,_Z3foov\.resolver\n" 0 } } */ + +/* { dg-final { scan-assembler-times "\n_Z3fooi\.default:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__v:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.arch__zba__zbb:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n_Z3fooi\.resolver:\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\tcall\t_Z3fooi\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.type\t_Z3fooi, @gnu_indirect_function\n" 0 } } */ +/* { dg-final { scan-assembler-times "\n\t\.set\t_Z3fooi,_Z3fooi\.resolver\n" 0 } } */