I suggest not handling the extension implication rules. This way, it can simplify the logic and reduce the cost of run-time checks.
Also, you need to consider situations where that extension can't be detected. And last, I would like to defer this until run-time resolver patch coming, but welcome to send another version of RFC patch :P On Sun, Oct 6, 2024 at 2:21 AM Yangyu Chen <chenyan...@isrc.iscas.ac.cn> wrote: > > 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-chenyan...@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 > > 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 Rename to riscv_feature_bits.h to prevent potential file name conflict also move to gcc/config/riscv/ rather than gcc/config/riscv/ > @@ -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 > +<http://www.gnu.org/licenses/>. */ > + Need header guard, something like #ifndef 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 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 <sstream> > #include <vector> > +#include <queue> > > #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. */ Typo: visted -> visited > + std::set <std::string> 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 Typo: Avoding -> Avoiding > + 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 <const char *> 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 *); Declare this in riscv_feature_bits.h is fine, then you don't need to change anything within this file. > > #endif /* ! GCC_RISCV_SUBSET_H */ > > base-commit: a8e6360765336969e3f45ac16e4340e5e5468768 > prerequisite-patch-id: 2a8fa0993d052b742835fa76402e4f763feb3475 > -- > 2.45.2 >