From patchwork Sat Oct 5 18:19:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yangyu Chen X-Patchwork-Id: 1993094 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=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 4XLYdM4YNmz1xsn for ; Sun, 6 Oct 2024 05:21:07 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7062C3858D20 for ; Sat, 5 Oct 2024 18:21:03 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from cstnet.cn (smtp84.cstnet.cn [159.226.251.84]) by sourceware.org (Postfix) with ESMTPS id 2344A3858D20 for ; Sat, 5 Oct 2024 18:20:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2344A3858D20 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=isrc.iscas.ac.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=isrc.iscas.ac.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 2344A3858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=159.226.251.84 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728152440; cv=none; b=CYuTWH88n0L+RR9yAWo8xrBhvxrjPRiLzUMpKIVwWBUpWWAU4rW3wj6IwX3AyO/cBj2eMEhrt21Hp1odKezi10avoD8x34GEu9ReFUKpqjEW8bF3VGJszNv26JVTYAw4+Gfm8gbgrFZeJCQFAhAB5W+Lvxz0vJgvOsGu8ql/gas= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728152440; c=relaxed/simple; bh=f/5Zgcz+qi+DW2TBdAsKPh1fOqAX+xp/crmpPw9IxeY=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=GTbvN0Eem+mt7iEXgTjv7i6kZgIKA/LRFznp461xx++XbbEZWWvgB+ktIIXBZSY94gg31SGbnCKnmjbMl8k6CR2TzVMMtsl/qallqxPanopTkHTCxQj2bVgC7G9GeFLKSMjCO/nAL6eujiGD6aP+vKkxhTO7QyBRMnLyQMlqaaY= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from cyy-pc.lan (unknown [183.252.3.74]) by APP-05 (Coremail) with SMTP id zQCowACHbWRjgwFnMLH5Aw--.44703S2; Sun, 06 Oct 2024 02:20:24 +0800 (CST) From: Yangyu Chen To: gcc-patches@gcc.gnu.org Cc: Kito Cheng , Palmer Dabbelt , Jiawei , Jeff Law , Yangyu Chen Subject: [RFC PATCH] RISC-V: Implement riscv_minimal_hwprobe_feature_bits Date: Sun, 6 Oct 2024 02:19:20 +0800 Message-ID: <20241005181920.2223674-1-chenyangyu@isrc.iscas.ac.cn> X-Mailer: git-send-email 2.45.2 MIME-Version: 1.0 X-CM-TRANSID: zQCowACHbWRjgwFnMLH5Aw--.44703S2 X-Coremail-Antispam: 1UD129KBjvJXoW3Wry7Cw47GF4xJr1UtrW7CFg_yoWfZFW8pa 1rC3yYkFyDJw47u397KFW3XF45CrnYgr43Jr1kC34jqa15JryrZ3Z3KFy5Z3Z5GrZYgF12 9r15WryUZa1DAaDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkm14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26r1j6r1xM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r1j 6r4UM28EF7xvwVC2z280aVAFwI0_Jr0_Gr1l84ACjcxK6I8E87Iv6xkF7I0E14v26r1j6r 4UM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7xfMcIj6xII jxv20xvE14v26r1j6r18McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr 1lF7xvr2IYc2Ij64vIr41lF7I21c0EjII2zVCS5cI20VAGYxC7MxkF7I0En4kS14v26r12 6r1DMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI 0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y 0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxV WUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1l IxAIcVC2z280aVCY1x0267AKxVWUJVW8JbIYCTnIWIevJa73UjIFyTuYvjfUehL0UUUUU X-Originating-IP: [183.252.3.74] X-CM-SenderInfo: xfkh055dqj53w6lv2u4olvutnvoduhdfq/ X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.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 previous patch [1] 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 final version of the target_clones support on RISC-V is still under development, I am working on it. 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. [1] https://patchwork.sourceware.org/project/gcc/patch/20241003182256.1765569-1-chenyangyu@isrc.iscas.ac.cn/ gcc/ChangeLog: * common/config/riscv/riscv-common.cc (struct riscv_ext_bitmask_table_t): New struct. (riscv_minimal_hwprobe_feature_bits): New function. * config/riscv/riscv-subset.h (GCC_RISCV_SUBSET_H): (riscv_minimal_hwprobe_feature_bits): Declare the function. * common/config/riscv/feature_bits.h: New file. --- gcc/common/config/riscv/feature_bits.h | 33 ++++++ gcc/common/config/riscv/riscv-common.cc | 144 ++++++++++++++++++++++++ gcc/config/riscv/riscv-subset.h | 4 + 3 files changed, 181 insertions(+) create mode 100644 gcc/common/config/riscv/feature_bits.h base-commit: a8e6360765336969e3f45ac16e4340e5e5468768 prerequisite-patch-id: 2a8fa0993d052b742835fa76402e4f763feb3475 diff --git a/gcc/common/config/riscv/feature_bits.h b/gcc/common/config/riscv/feature_bits.h new file mode 100644 index 00000000000..c6c6d983edb --- /dev/null +++ b/gcc/common/config/riscv/feature_bits.h @@ -0,0 +1,33 @@ +/* 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 +. */ + +#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 vendorID; + unsigned length; + unsigned long long features[RISCV_VENDOR_FEATURE_BITS_LENGTH]; +}; diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index bd42fd01532..9f343782ae6 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 @@ -1754,6 +1755,75 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] = {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[] = +{ + {"i", 0, 8}, + {"m", 0, 12}, + {"a", 0, 0}, + {"f", 0, 5}, + {"d", 0, 3}, + {"c", 0, 2}, + {"v", 0, 21}, + {"zba", 0, 27}, + {"zbb", 0, 28}, + {"zbs", 0, 33}, + {"zicboz", 0, 37}, + {"zbc", 0, 29}, + {"zbkb", 0, 30}, + {"zbkc", 0, 31}, + {"zbkx", 0, 32}, + {"zknd", 0, 41}, + {"zkne", 0, 42}, + {"zknh", 0, 43}, + {"zksed", 0, 44}, + {"zksh", 0, 45}, + {"zkt", 0, 46}, + {"zvbb", 0, 48}, + {"zvbc", 0, 49}, + {"zvkb", 0, 52}, + {"zvkg", 0, 53}, + {"zvkned", 0, 54}, + {"zvknha", 0, 55}, + {"zvknhb", 0, 56}, + {"zvksed", 0, 57}, + {"zvksh", 0, 58}, + {"zvkt", 0, 59}, + {"zfh", 0, 35}, + {"zfhmin", 0, 36}, + {"zihintntl", 0, 39}, + {"zvfh", 0, 50}, + {"zvfhmin", 0, 51}, + {"zfa", 0, 34}, + {"ztso", 0, 47}, + {"zacas", 0, 26}, + {"zicond", 0, 38}, + {"zihintpause", 0, 40}, + {"zve32x", 0, 60}, + {"zve32f", 0, 61}, + {"zve64x", 0, 62}, + {"zve64f", 0, 63}, + {"zve64d", 1, 0}, + {"zimop", 1, 1}, + {"zca", 1, 2}, + {"zcb", 1, 3}, + {"zcd", 1, 4}, + {"zcf", 1, 5}, + {"zcmop", 1, 6}, + {"zawrs", 1, 7}, + + {NULL, -1, -1} +}; + /* Apply SUBSET_LIST to OPTS if OPTS is not null. */ void @@ -1783,6 +1853,80 @@ riscv_set_arch_by_subset_list (riscv_subset_list *subset_list, } } +/* 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) +{ + riscv_subset_list *subset_list; + subset_list = riscv_subset_list::parse (isa, UNKNOWN_LOCATION); + 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 visted implied extensions. */ + std::set implied_exts; + + /* Iterate through the extension bitmask table in Linux hwprobe order to get + the minimal covered feature bits. Avoding 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/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h index dace4de6575..5a1489c00ea 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 "common/config/riscv/feature_bits.h" + #define RISCV_DONT_CARE_VERSION -1 /* Subset info. */ @@ -120,5 +122,7 @@ 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 *); #endif /* ! GCC_RISCV_SUBSET_H */