@@ -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. */
new file mode 100644
@@ -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
new file mode 100644
@@ -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 */
@@ -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);