diff options
-rw-r--r-- | gcc/common/config/riscv/riscv-common.cc | 94 | ||||
-rw-r--r-- | gcc/common/config/riscv/riscv-ext-bitmask.def | 83 | ||||
-rw-r--r-- | gcc/config/riscv/riscv-feature-bits.h | 44 | ||||
-rw-r--r-- | gcc/config/riscv/riscv-subset.h | 5 |
4 files changed, 226 insertions, 0 deletions
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 60595a3..b0e49eb 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 @@ -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 <std::string> 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 <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/common/config/riscv/riscv-ext-bitmask.def b/gcc/common/config/riscv/riscv-ext-bitmask.def new file mode 100644 index 0000000..ca5df17 --- /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 +<http://www.gnu.org/licenses/>. */ + +#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 0000000..19b7630 --- /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 +<http://www.gnu.org/licenses/>. */ + +#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 1914a53..62aae4f 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); |