From patchwork Fri Nov 1 20:59:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 2005318 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=O0dylOPJ; 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 4XgCv90xFpz1xwF for ; Sat, 2 Nov 2024 08:00:53 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4F4B0385B52C for ; Fri, 1 Nov 2024 21:00:51 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from out203-205-221-192.mail.qq.com (out203-205-221-192.mail.qq.com [203.205.221.192]) by sourceware.org (Postfix) with UTF8SMTPS id 9F67B3857BA7 for ; Fri, 1 Nov 2024 20:59:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9F67B3857BA7 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 9F67B3857BA7 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=203.205.221.192 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730494774; cv=none; b=Jimt8SBl67SP9zshrZChzHqSUpl/j4+xleppGsoW4rX4pf+9QhWS2/eZTQNtBvo0Jk8oimTV5Yi7BM5j2YPT4+S+9BgsFNR3xuSm/sZs71DR4FVtkiwf1gJDxrhkjmipiQVGb89RQ3yytGvrqag8bYQVjvwYkVhbi8r60M+Qjco= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730494774; c=relaxed/simple; bh=ClN1GOupA4X8Wf2nRBF4UjE4iY4sKm5YnHTJrXHqu14=; h=DKIM-Signature:Message-ID:From:To:Subject:Date:MIME-Version; b=mYs1PL2gT/j7s5oF7QjHqbbGnCbgt/xV73EFIehbEAxiNN6GYATPm/5vvN11IqLjrIPaJec5jgJK8SpzalfgzAeQPL/Zw6t07By3gJwzJJzmAMveF+Mpv/gnuXedUyjQ2ViBdvdAYH0cborCAGobLLeljB+1x9vkkNTM6T4Oybw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qq.com; s=s201512; t=1730494767; bh=F6B0EbUgoFjc37bvE5Q7OSqLbdhLMwmLn5TwJsaQs5M=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=O0dylOPJiiwnfH4yQLoelHHneOzwlxVygXBYUPozdfL3xa7/i1SuRghy7Se+FgEPD 2sE7HCW1BGWkV59KGFKvDju3sZlQ40/EIR1PE35kkU5PzZ6wPJKZTWjVpuO/I6V+kO DVPZNFpazLkYP5ojMmYI+s0s6KlmH44norM5fYLo= Received: from cyy-pc.lan ([240e:379:2276:5d00:cda0:97a5:84f4:5191]) by newxmesmtplogicsvrsza15-1.qq.com (NewEsmtp) with SMTP id ED8A543D; Sat, 02 Nov 2024 04:59:24 +0800 X-QQ-mid: xmsmtpt1730494764tqsgbbd64 Message-ID: X-QQ-XMAILINFO: OZILsD/zN1fM9t5wJUlhGl4mEJZkL6iEZ1x/LvybgWLOu81rZlHMjMVGJMBNLB ZzKfAI1lVgF9QIsU+/wSO6P/aWPiF6CD/O2xtsRjCmexz6jH3xMtZUz0pyXotQzZyo9gmhg0e8Fw riGiTpPYr8ruRgxwVRCr3lj5q/5YXyQEiNGaFzvpCacTepJCRs8+Z29sxW3treHnL8XGkfjQkpxI wBKkx3QLTMxjfNlqdbY6P9LR54F4uECZeNX8opQg2vl67yJ4DY+FcogIKj7+T3P5f9yC8YH8kmgJ jmzUntcdmpRpidwkpWojeyhUT6b0Q9L9aWtT2GHn+EGlKv4lzMdLoHsp7ZA189rCwN7A2gsbvtE/ 710z+oDRbOKhV1J0Nwa/9dKG6ycYS1p/hIwtnAK1Q2ePeWL6hjaQ12iEODWqVDwzmyFZdB4ZtXcL AaH6PVQoHc1Hep2KI9BY2O8D47s48Xil/tCXWob1HonRqXvSHl+k0arBSY46yBWRjml5L0ckwABD fodsnYmO6sYfImX2HmHt1YivTN+vPjO0/UeCWx3jelhMJUhzHWDDjRvTDYEa+zCgLveWi6o9mj6U IlksiXihvqNOmq/E9ZOzuJ2akOdjSFe5xvg4Wa5Oz28/FYE32nJVbeoaVST40+RbK0ltK1bw7021 QlnhjiDsZ0uUS/Y9vxvvmNOLTJSTWBXOq7uyrlq6pvklQuM1DbP1tBD0qST1wiiKRR1NBoOAR8ES /H6wVBpqK1E7Oyn0GlTqw1XMFYo20tdHjpUxlCIhVGlWPgzs6wNOJmRXSUHFGn++oQ3Z9tXktH48 8bUTEFe/vPpZohwxwi907FKtPtoffeu+ciABIm5bmEgE2bIE/nhipH/lHaItGnC9DQ4kOP9P+3d4 OQPWoOX6O2mJLirrBywcY7EA0H9DnRxVmGFBPaeu1w+qL4/j/iHo6tdHfgk/IZv00U+1iLa9rzNS qFrilk1H2H8D7GJVeU6sj1JZOGFWs0j5G18eFXeFL8r679sTng3K1Oi0CIfRkXHA+Z9bjhDB/Vxx /jgJD5tIPXHI1nYqpEKQVHQlUqg1UlY9Qk2T2iFkpfpYO44o4qRuMSgY2YX6A= X-QQ-XMRINFO: OWPUhxQsoeAVDbp3OJHYyFg= From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Evgeny Stupachenko , Andrew Carlotti , Yangyu Chen , Hank Chang Subject: [PATCH v4 5/8] RISC-V: Implement TARGET_COMPARE_VERSION_PRIORITY and TARGET_OPTION_FUNCTION_VERSIONS Date: Sat, 2 Nov 2024 04:59:23 +0800 X-OQ-MSGID: <20241101205923.1533909-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 23062a482c2..5ade0084b11 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. */ @@ -13064,6 +13185,12 @@ riscv_stack_clash_protection_alloca_probe_range (void) #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"