On Mon, Jul 15, 2024 at 11:10 AM Kito Cheng <kito.ch...@gmail.com> wrote: > > LGTM, and could you backport this to the GCC 14 branch as well?
Rebased, retested (multilib), fixed an issue related to Zca/Zcd and pushed. Should the GCC 14 backport be posted for review before pushing? Thanks, Christoph > > On Tue, Jul 9, 2024 at 8:50 PM Christoph Müllner > <christoph.muell...@vrull.eu> wrote: > > > > The target-arch attribute handling in RISC-V is only a few months old, > > but already saw a rewrite (9941f0295a14), which addressed an important > > issue. This rewrite introduced a hash table in the backend, which is > > used to keep track of target-arch attributes of all functions. > > The index of this hash table is the pointer to the function declaration > > object (fndecl). However, objects like these don't have the lifetime > > that is assumed here, which resulted in observing two fndecl objects > > with the same address for different objects (triggering the assertion > > in riscv_func_target_put() -- see also PR115562). > > > > This patch removes the hash table approach in favor of storing target > > specific options using the DECL_FUNCTION_SPECIFIC_TARGET() macro, which > > is also used by other backends and is specifically designed for this > > purpose (https://gcc.gnu.org/onlinedocs/gccint/Function-Properties.html). > > > > To have an accessible field in the target options, we need to > > adjust riscv.opt and introduce the field riscv_arch_string > > (for the already existing option '-march='). > > > > Using this macro allows to remove much code from riscv-common.cc, which > > controls access to the objects 'func_target_table' and > > 'current_subset_list'. > > > > One thing to mention is, that we had two subset lists: > > current_subset_list and cmdline_subset_list, with the latter being > > introduced recently for target attribute handling. > > This patch reduces them back to one (cmdline_subset_list) which > > contains the list of extensions that have been enabled by the command > > line arguments. > > > > Note that the patch keeps the existing behavior of rejecting > > duplications of extensions when added via the '+' operator in a function > > target attribute. E.g. "-march=rv64gc_zbb" and "arch=+zbb" will trigger > > an error (see pr115554.c). However, at the same time this patch breaks > > the acceptance of adding implied extensions, which causes the following > > six regressions (with the error "extension 'EXT' appear more than one > > time"): > > * gcc.target/riscv/rvv/base/target_attribute_v_with_intrinsic-39.c > > * gcc.target/riscv/rvv/base/target_attribute_v_with_intrinsic-42.c > > * gcc.target/riscv/rvv/base/target_attribute_v_with_intrinsic-43.c > > * gcc.target/riscv/rvv/base/target_attribute_v_with_intrinsic-44.c > > * gcc.target/riscv/rvv/base/target_attribute_v_with_intrinsic-45.c > > * gcc.target/riscv/rvv/base/target_attribute_v_with_intrinsic-46.c > > > > New tests were added to document the behavior and to ensure it won't > > regress. This patch did not show any regressions for rv32/rv64 > > and fixes the ICEs from PR115554 and PR115562. > > > > PR 115554 > > PR 115562 > > > > gcc/ChangeLog: > > > > * common/config/riscv/riscv-common.cc (struct > > riscv_func_target_info): > > Remove. > > (struct riscv_func_target_hasher): Likewise. > > (riscv_func_decl_hash): Likewise. > > (riscv_func_target_hasher::hash): Likewise. > > (riscv_func_target_hasher::equal): Likewise. > > (riscv_current_subset_list): Likewise. > > (riscv_cmdline_subset_list): Remove obsolete space. > > (riscv_func_target_table_lazy_init): Remove. > > (riscv_func_target_get): Likewise. > > (riscv_func_target_put): Likewise. > > (riscv_func_target_remove_and_destory): Likewise. > > (riscv_arch_str): Generate from cmdline_subset_list. > > (riscv_set_arch_by_subset_list): Don't set current_subset_list. > > (riscv_parse_arch_string): Remove current_subset_list. > > * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): > > Get subset list via riscv_cmdline_subset_list(). > > * config/riscv/riscv-subset.h (riscv_current_subset_list): > > Remove prototype. > > (riscv_func_target_get): Likewise. > > (riscv_func_target_put): Likewise. > > (riscv_func_target_remove_and_destory): Likewise. > > * config/riscv/riscv-target-attr.cc > > (riscv_target_attr_parser::parse_arch): > > Build base arch string from existing target options, if any. > > (riscv_target_attr_parser::update_settings): Store new arch > > string in target options. > > (riscv_process_one_target_attr): Whitespace fix. > > (riscv_process_target_attr): Drop opts argument. > > (riscv_option_valid_attribute_p): Properly save, change and restore > > target options. > > * config/riscv/riscv.cc (get_arch_str): New function. > > (riscv_declare_function_name): Get arch string for option-arch > > directive from function's target options. > > * config/riscv/riscv.opt: Add riscv_arch_string variable to > > march option. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/riscv/target-attr-01.c: Add test for option-arch > > directive. > > * gcc.target/riscv/target-attr-02.c: Likewise. > > * gcc.target/riscv/target-attr-03.c: Likewise. > > * gcc.target/riscv/target-attr-04.c: Likewise. > > * gcc.target/riscv/target-attr-05.c: Fix formatting. > > * gcc.target/riscv/target-attr-06.c: Likewise. > > * gcc.target/riscv/target-attr-07.c: Likewise. > > * gcc.target/riscv/pr115554.c: New test. > > * gcc.target/riscv/pr115562.c: New test. > > * gcc.target/riscv/target-attr-08.c: New test. > > * gcc.target/riscv/target-attr-09.c: New test. > > * gcc.target/riscv/target-attr-10.c: New test. > > * gcc.target/riscv/target-attr-11.c: New test. > > * gcc.target/riscv/target-attr-12.c: New test. > > * gcc.target/riscv/target-attr-13.c: New test. > > * gcc.target/riscv/target-attr-14.c: New test. > > * gcc.target/riscv/target-attr-15.c: New test. > > > > Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu> > > --- > > gcc/common/config/riscv/riscv-common.cc | 113 +----------------- > > gcc/config/riscv/riscv-c.cc | 2 +- > > gcc/config/riscv/riscv-subset.h | 4 - > > gcc/config/riscv/riscv-target-attr.cc | 102 +++++++++------- > > gcc/config/riscv/riscv.cc | 22 ++-- > > gcc/config/riscv/riscv.opt | 2 +- > > gcc/testsuite/gcc.target/riscv/pr115554.c | 13 ++ > > gcc/testsuite/gcc.target/riscv/pr115562.c | 25 ++++ > > .../gcc.target/riscv/target-attr-01.c | 16 ++- > > .../gcc.target/riscv/target-attr-02.c | 16 ++- > > .../gcc.target/riscv/target-attr-03.c | 11 +- > > .../gcc.target/riscv/target-attr-04.c | 11 +- > > .../gcc.target/riscv/target-attr-05.c | 10 +- > > .../gcc.target/riscv/target-attr-06.c | 11 +- > > .../gcc.target/riscv/target-attr-07.c | 10 +- > > .../gcc.target/riscv/target-attr-08.c | 20 ++++ > > .../gcc.target/riscv/target-attr-09.c | 19 +++ > > .../gcc.target/riscv/target-attr-10.c | 19 +++ > > .../gcc.target/riscv/target-attr-11.c | 22 ++++ > > .../gcc.target/riscv/target-attr-12.c | 21 ++++ > > .../gcc.target/riscv/target-attr-13.c | 21 ++++ > > .../gcc.target/riscv/target-attr-14.c | 42 +++++++ > > .../gcc.target/riscv/target-attr-15.c | 42 +++++++ > > 23 files changed, 371 insertions(+), 203 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/riscv/pr115554.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/pr115562.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-08.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-09.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-10.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-11.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-12.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-13.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-14.c > > create mode 100644 gcc/testsuite/gcc.target/riscv/target-attr-15.c > > > > diff --git a/gcc/common/config/riscv/riscv-common.cc > > b/gcc/common/config/riscv/riscv-common.cc > > index dfe960e51293..c215484c287b 100644 > > --- a/gcc/common/config/riscv/riscv-common.cc > > +++ b/gcc/common/config/riscv/riscv-common.cc > > @@ -438,110 +438,13 @@ static const char *riscv_supported_std_ext (void); > > > > bool riscv_subset_list::parse_failed = false; > > > > -static riscv_subset_list *current_subset_list = NULL; > > - > > static riscv_subset_list *cmdline_subset_list = NULL; > > > > -struct riscv_func_target_info > > -{ > > - tree fn_decl; > > - std::string fn_target_name; > > - > > - riscv_func_target_info (const tree &decl, const std::string &target_name) > > - : fn_decl (decl), fn_target_name (target_name) > > - { > > - } > > -}; > > - > > -struct riscv_func_target_hasher : nofree_ptr_hash<struct > > riscv_func_target_info> > > -{ > > - typedef tree compare_type; > > - > > - static hashval_t hash (value_type); > > - static bool equal (value_type, const compare_type &); > > -}; > > - > > -static hash_table<riscv_func_target_hasher> *func_target_table = NULL; > > - > > -static inline hashval_t riscv_func_decl_hash (tree fn_decl) > > -{ > > - inchash::hash h; > > - > > - h.add_ptr (fn_decl); > > - > > - return h.end (); > > -} > > - > > -inline hashval_t > > -riscv_func_target_hasher::hash (value_type value) > > -{ > > - return riscv_func_decl_hash (value->fn_decl); > > -} > > - > > -inline bool > > -riscv_func_target_hasher::equal (value_type value, const compare_type &key) > > -{ > > - return value->fn_decl == key; > > -} > > - > > -const riscv_subset_list *riscv_current_subset_list () > > -{ > > - return current_subset_list; > > -} > > - > > -const riscv_subset_list * riscv_cmdline_subset_list () > > +const riscv_subset_list *riscv_cmdline_subset_list () > > { > > return cmdline_subset_list; > > } > > > > -static inline void riscv_func_target_table_lazy_init () > > -{ > > - if (func_target_table != NULL) > > - return; > > - > > - func_target_table = new hash_table<riscv_func_target_hasher> (1023); > > -} > > - > > -std::string * riscv_func_target_get (tree fn_decl) > > -{ > > - riscv_func_target_table_lazy_init (); > > - > > - hashval_t hash = riscv_func_decl_hash (fn_decl); > > - struct riscv_func_target_info *info > > - = func_target_table->find_with_hash (fn_decl, hash); > > - > > - return info == NULL ? NULL : &info->fn_target_name; > > -} > > - > > -void riscv_func_target_put (tree fn_decl, std::string fn_target_name) > > -{ > > - riscv_func_target_table_lazy_init (); > > - > > - hashval_t hash = riscv_func_decl_hash (fn_decl); > > - struct riscv_func_target_info **target_info_slot > > - = func_target_table->find_slot_with_hash (fn_decl, hash, INSERT); > > - > > - gcc_assert (!*target_info_slot); > > - > > - struct riscv_func_target_info *info > > - = new riscv_func_target_info (fn_decl, fn_target_name); > > - > > - *target_info_slot = info; > > -} > > - > > -void riscv_func_target_remove_and_destory (tree fn_decl) > > -{ > > - hashval_t hash = riscv_func_decl_hash (fn_decl); > > - struct riscv_func_target_info *info > > - = func_target_table->find_with_hash (fn_decl, hash); > > - > > - if (info) > > - { > > - func_target_table->remove_elt_with_hash (fn_decl, hash); > > - delete info; > > - } > > -} > > - > > /* struct for recording multi-lib info. */ > > struct riscv_multi_lib_info_t { > > std::string path; > > @@ -1612,8 +1515,8 @@ riscv_subset_list::finalize () > > std::string > > riscv_arch_str (bool version_p) > > { > > - if (current_subset_list) > > - return current_subset_list->to_string (version_p); > > + if (cmdline_subset_list) > > + return cmdline_subset_list->to_string (version_p); > > else > > return std::string(); > > } > > @@ -1798,8 +1701,7 @@ static const riscv_ext_flag_table_t > > riscv_ext_flag_table[] = > > {NULL, NULL, 0} > > }; > > > > -/* Apply SUBSET_LIST to OPTS if OPTS is not null, also set > > CURRENT_SUBSET_LIST > > - to SUBSET_LIST, just note this WON'T delete old CURRENT_SUBSET_LIST. */ > > +/* Apply SUBSET_LIST to OPTS if OPTS is not null. */ > > > > void > > riscv_set_arch_by_subset_list (riscv_subset_list *subset_list, > > @@ -1826,8 +1728,6 @@ riscv_set_arch_by_subset_list (riscv_subset_list > > *subset_list, > > opts->*arch_ext_flag_tab->var_ref |= arch_ext_flag_tab->mask; > > } > > } > > - > > - current_subset_list = subset_list; > > } > > > > /* Parse a RISC-V ISA string into an option mask. Must clear or set all > > arch > > @@ -1843,15 +1743,10 @@ riscv_parse_arch_string (const char *isa, > > if (!subset_list) > > return; > > > > - /* Avoid double delete if current_subset_list equals > > cmdline_subset_list. */ > > - if (current_subset_list && current_subset_list != cmdline_subset_list) > > - delete current_subset_list; > > - > > if (cmdline_subset_list) > > delete cmdline_subset_list; > > > > cmdline_subset_list = subset_list; > > - /* current_subset_list is set in the call below. */ > > > > riscv_set_arch_by_subset_list (subset_list, opts); > > } > > diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc > > index 43c8eecbb6ff..71112d9c66d7 100644 > > --- a/gcc/config/riscv/riscv-c.cc > > +++ b/gcc/config/riscv/riscv-c.cc > > @@ -218,7 +218,7 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) > > /* Define architecture extension test macros. */ > > builtin_define_with_int_value ("__riscv_arch_test", 1); > > > > - const riscv_subset_list *subset_list = riscv_current_subset_list (); > > + const riscv_subset_list *subset_list = riscv_cmdline_subset_list (); > > if (!subset_list) > > return; > > > > diff --git a/gcc/config/riscv/riscv-subset.h > > b/gcc/config/riscv/riscv-subset.h > > index fe7f54d8bc57..256d28657460 100644 > > --- a/gcc/config/riscv/riscv-subset.h > > +++ b/gcc/config/riscv/riscv-subset.h > > @@ -109,11 +109,7 @@ public: > > void finalize (); > > }; > > > > -extern const riscv_subset_list *riscv_current_subset_list (void); > > extern const riscv_subset_list *riscv_cmdline_subset_list (void); > > -extern std::string * riscv_func_target_get (tree); > > -extern void riscv_func_target_put (tree, std::string); > > -extern void riscv_func_target_remove_and_destory (tree); > > extern void > > riscv_set_arch_by_subset_list (riscv_subset_list *, struct gcc_options *); > > > > diff --git a/gcc/config/riscv/riscv-target-attr.cc > > b/gcc/config/riscv/riscv-target-attr.cc > > index 3d7753f64574..317806143949 100644 > > --- a/gcc/config/riscv/riscv-target-attr.cc > > +++ b/gcc/config/riscv/riscv-target-attr.cc > > @@ -50,14 +50,6 @@ public: > > bool handle_cpu (const char *); > > bool handle_tune (const char *); > > > > - void set_loc (location_t loc) { > > - m_loc = loc; > > - } > > - > > - riscv_subset_list* get_riscv_subset_list () { > > - return m_subset_list; > > - } > > - > > void update_settings (struct gcc_options *opts) const; > > private: > > const char *m_raw_attr_str; > > @@ -98,7 +90,7 @@ riscv_target_attr_parser::parse_arch (const char *str) > > /* Check if it's setting full arch string. */ > > if (strncmp ("rv", str, strlen ("rv")) == 0) > > { > > - m_subset_list = riscv_subset_list::parse (str, location_t ()); > > + m_subset_list = riscv_subset_list::parse (str, m_loc); > > > > if (m_subset_list == nullptr) > > goto fail; > > @@ -112,7 +104,10 @@ riscv_target_attr_parser::parse_arch (const char *str) > > char *str_to_check = (char *) alloca (len + 1); > > strcpy (str_to_check, str); > > const char *token = strtok_r (str_to_check, ",", &str_to_check); > > - m_subset_list = riscv_cmdline_subset_list ()->clone (); > > + const char *local_arch_str = global_options.x_riscv_arch_string; > > + m_subset_list = local_arch_str > > + ? riscv_subset_list::parse (local_arch_str, m_loc) > > + : riscv_cmdline_subset_list ()->clone (); > > m_subset_list->set_loc (m_loc); > > while (token) > > { > > @@ -124,19 +119,18 @@ riscv_target_attr_parser::parse_arch (const char *str) > > "with + or rv"); > > goto fail; > > } > > - else > > + > > + const char *result = m_subset_list->parse_single_ext (token + 1); > > + /* Check parse_single_ext has consume all string. */ > > + if (*result != '\0') > > { > > - const char *result = m_subset_list->parse_single_ext (token + > > 1); > > - /* Check parse_single_ext has consume all string. */ > > - if (*result != '\0') > > - { > > - error_at ( > > - m_loc, > > - "unexpected arch for %<target()%> attribute: bad " > > - "string found %<%s%>", token); > > - goto fail; > > - } > > + error_at ( > > + m_loc, > > + "unexpected arch for %<target()%> attribute: bad " > > + "string found %<%s%>", token); > > + goto fail; > > } > > + > > token = strtok_r (NULL, ",", &str_to_check); > > } > > > > @@ -216,7 +210,17 @@ void > > riscv_target_attr_parser::update_settings (struct gcc_options *opts) const > > { > > if (m_subset_list) > > - riscv_set_arch_by_subset_list (m_subset_list, opts); > > + { > > + std::string local_arch = m_subset_list->to_string (true); > > + const char* local_arch_str = local_arch.c_str (); > > + struct cl_target_option *default_opts > > + = TREE_TARGET_OPTION (target_option_default_node); > > + if (opts->x_riscv_arch_string != default_opts->x_riscv_arch_string) > > + free (CONST_CAST (void *, (const void *) > > opts->x_riscv_arch_string)); > > + opts->x_riscv_arch_string = xstrdup (local_arch_str); > > + > > + riscv_set_arch_by_subset_list (m_subset_list, opts); > > + } > > > > if (m_cpu_info) > > opts->x_riscv_cpu_string = m_cpu_info->name; > > @@ -272,8 +276,8 @@ riscv_process_one_target_attr (char *arg_str, > > > > return (&attr_parser->*attr.handler) (arg); > > } > > - error_at (loc, "Got unknown attribute %<target(\"%s\")%>", str_to_check); > > > > + error_at (loc, "Got unknown attribute %<target(\"%s\")%>", str_to_check); > > return false; > > } > > > > @@ -299,8 +303,7 @@ num_occurences_in_str (char c, char *str) > > and update the global target options space. */ > > > > static bool > > -riscv_process_target_attr (tree fndecl, tree args, location_t loc, > > - struct gcc_options *opts) > > +riscv_process_target_attr (tree args, location_t loc) > > { > > if (TREE_CODE (args) == TREE_LIST) > > { > > @@ -309,7 +312,7 @@ riscv_process_target_attr (tree fndecl, tree args, > > location_t loc, > > tree head = TREE_VALUE (args); > > if (head) > > { > > - if (!riscv_process_target_attr (fndecl, head, loc, opts)) > > + if (!riscv_process_target_attr (head, loc)) > > return false; > > } > > args = TREE_CHAIN (args); > > @@ -323,6 +326,7 @@ riscv_process_target_attr (tree fndecl, tree args, > > location_t loc, > > error_at (loc, "attribute %<target%> argument not a string"); > > return false; > > } > > + > > size_t len = strlen (TREE_STRING_POINTER (args)); > > > > /* No need to emit warning or error on empty string here, generic code > > already > > @@ -347,7 +351,9 @@ riscv_process_target_attr (tree fndecl, tree args, > > location_t loc, > > while (token) > > { > > num_attrs++; > > - riscv_process_one_target_attr (token, loc, attr_parser); > > + if (!riscv_process_one_target_attr (token, loc, attr_parser)) > > + return false; > > + > > token = strtok_r (NULL, ";", &str_to_check); > > } > > > > @@ -359,18 +365,16 @@ riscv_process_target_attr (tree fndecl, tree args, > > location_t loc, > > } > > > > /* Apply settings from target attribute. */ > > - attr_parser.update_settings (opts); > > - > > - /* Add the string of the target attribute to the fndecl hash table. */ > > - riscv_subset_list *subset_list = attr_parser.get_riscv_subset_list (); > > - if (subset_list) > > - riscv_func_target_put (fndecl, subset_list->to_string (true)); > > + attr_parser.update_settings (&global_options); > > > > return true; > > } > > > > -/* Implement TARGET_OPTION_VALID_ATTRIBUTE_P. This is used to > > - process attribute ((target ("..."))). */ > > +/* Implement TARGET_OPTION_VALID_ATTRIBUTE_P. > > + This is used to process attribute ((target ("..."))). > > + Note, that riscv_set_current_function() has not been called before, > > + so we need must not mess with the current global_options, which > > + likely belong to another function. */ > > > > bool > > riscv_option_valid_attribute_p (tree fndecl, tree, tree args, int) > > @@ -378,27 +382,39 @@ riscv_option_valid_attribute_p (tree fndecl, tree, > > tree args, int) > > struct cl_target_option cur_target; > > bool ret; > > tree new_target; > > + tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); > > location_t loc = DECL_SOURCE_LOCATION (fndecl); > > > > /* Save the current target options to restore at the end. */ > > cl_target_option_save (&cur_target, &global_options, > > &global_options_set); > > > > - ret = riscv_process_target_attr (fndecl, args, loc, &global_options); > > - > > - if (ret) > > + /* If fndecl already has some target attributes applied to it, unpack > > + them so that we add this attribute on top of them, rather than > > + overwriting them. */ > > + if (existing_target) > > { > > - riscv_override_options_internal (&global_options); > > - new_target > > - = build_target_option_node (&global_options, &global_options_set); > > + struct cl_target_option *existing_options > > + = TREE_TARGET_OPTION (existing_target); > > + > > + if (existing_options) > > + cl_target_option_restore (&global_options, &global_options_set, > > + existing_options); > > } > > else > > - new_target = NULL; > > + cl_target_option_restore (&global_options, &global_options_set, > > + TREE_TARGET_OPTION > > (target_option_default_node)); > > > > - if (fndecl && ret) > > + /* Now we can parse the attributes and set &global_options accordingly. > > */ > > + ret = riscv_process_target_attr (args, loc); > > + if (ret) > > { > > + riscv_override_options_internal (&global_options); > > + new_target = build_target_option_node (&global_options, > > + &global_options_set); > > DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; > > } > > > > + /* Restore current target options to original state. */ > > cl_target_option_restore (&global_options, &global_options_set, > > &cur_target); > > return ret; > > } > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > > index 38ed773c222d..d4766b6aeeee 100644 > > --- a/gcc/config/riscv/riscv.cc > > +++ b/gcc/config/riscv/riscv.cc > > @@ -719,6 +719,15 @@ riscv_min_arithmetic_precision (void) > > return 32; > > } > > > > +/* Get the arch string from an options object. */ > > + > > +template <class T> > > +static const char * > > +get_arch_str (const T *opts) > > +{ > > + return opts->x_riscv_arch_string; > > +} > > + > > template <class T> > > static const char * > > get_tune_str (const T *opts) > > @@ -9469,17 +9478,16 @@ riscv_declare_function_name (FILE *stream, const > > char *name, tree fndecl) > > { > > fprintf (stream, "\t.option push\n"); > > > > - std::string *target_name = riscv_func_target_get (fndecl); > > - std::string isa = target_name != NULL > > - ? *target_name > > - : riscv_cmdline_subset_list ()->to_string (true); > > - fprintf (stream, "\t.option arch, %s\n", isa.c_str ()); > > - riscv_func_target_remove_and_destory (fndecl); > > - > > struct cl_target_option *local_cl_target = > > TREE_TARGET_OPTION (DECL_FUNCTION_SPECIFIC_TARGET (fndecl)); > > struct cl_target_option *global_cl_target = > > TREE_TARGET_OPTION (target_option_default_node); > > + > > + const char *local_arch_str = get_arch_str (local_cl_target); > > + const char *arch_str = local_arch_str != NULL > > + ? local_arch_str > > + : riscv_arch_str (true).c_str (); > > + fprintf (stream, "\t.option arch, %s\n", arch_str); > > const char *local_tune_str = get_tune_str (local_cl_target); > > const char *global_tune_str = get_tune_str (global_cl_target); > > if (strcmp (local_tune_str, global_tune_str) != 0) > > diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt > > index 32a0dda58439..e882caa8b7f5 100644 > > --- a/gcc/config/riscv/riscv.opt > > +++ b/gcc/config/riscv/riscv.opt > > @@ -82,7 +82,7 @@ Target Mask(DIV) > > Use hardware instructions for integer division. > > > > march= > > -Target RejectNegative Joined Negative(march=) > > +Target RejectNegative Joined Negative(march=) Var(riscv_arch_string) Save > > -march= Generate code for given RISC-V ISA (e.g. RV64IM). ISA > > strings must be > > lower-case. > > > > diff --git a/gcc/testsuite/gcc.target/riscv/pr115554.c > > b/gcc/testsuite/gcc.target/riscv/pr115554.c > > new file mode 100644 > > index 000000000000..e7dcde6276fa > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/pr115554.c > > @@ -0,0 +1,13 @@ > > +/* { dg-do compile } */ > > + > > +extern > > +__attribute__((target("arch=+zba"))) > > +__attribute__((target("arch=+zbb"))) > > +void foo(void); > > + > > +extern > > +__attribute__((target("arch=+zbb"))) > > +__attribute__((target("arch=+zbb"))) > > +void bar(void); > > + > > +/* { dg-error "extension 'zbb' appear more than one time" "" { target > > *-*-* } 0 } */ > > diff --git a/gcc/testsuite/gcc.target/riscv/pr115562.c > > b/gcc/testsuite/gcc.target/riscv/pr115562.c > > new file mode 100644 > > index 000000000000..b20f69d8dec6 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/pr115562.c > > @@ -0,0 +1,25 @@ > > +/* { dg-do compile } */ > > + > > +void foo (void); > > + > > +__attribute__((target("arch=+zbb"))) > > +void* > > +memcpy (void *d, const void *s, unsigned long n) > > +{ > > + (void) s; > > + (void) n; > > + return d; > > +} > > +__attribute__((target("arch=+zbb"))) void fun0(void) {} > > +__attribute__((target("arch=+zbb"))) void fun1(void) {} > > +__attribute__((target("arch=+zbb"))) void fun2(void) {} > > +__attribute__((target("arch=+zbb"))) void fun3(void) {} > > +__attribute__((target("arch=+zbb"))) void fun4(void) {} > > +__attribute__((target("arch=+zbb"))) void fun5(void) {} > > +__attribute__((target("arch=+zbb"))) void fun6(void) {} > > +__attribute__((target("arch=+zbb"))) void fun7(void) {} > > +__attribute__((target("arch=+zbb"))) void fun8(void) {} > > +__attribute__((target("arch=+zbb"))) void fun9(void) {} > > +__attribute__((target("arch=+zbb"))) void fun10(void) {} > > +__attribute__((target("arch=+zbb"))) void fun11(void) {} > > +__attribute__((target("arch=+zbb"))) void fun12(void) {} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-01.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-01.c > > index b3f3d65d543f..4748f6a08e72 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-01.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-01.c > > @@ -1,19 +1,18 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > - > > /* > > ** foo: > > ** ... > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > - > > - > > -long foo() __attribute__((target("arch=rv64gc_zba"))); > > -long foo(long a, long b){ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zba1p0" > > } } */ > > +long foo () __attribute__((target("arch=rv64gc_zba"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -24,8 +23,7 @@ long foo(long a, long b){ > > ** add\s*a0,a1,a0 > > ** ... > > */ > > - > > - > > -long bar(long a, long b){ > > +long bar (long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-02.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-02.c > > index c010089a823b..9ebf16e3675e 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-02.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-02.c > > @@ -1,19 +1,18 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > - > > /* > > ** foo: > > ** ... > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > - > > - > > -long foo() __attribute__((target("arch=+zba"))); > > -long foo(long a, long b){ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zba1p0" > > } } */ > > +long foo () __attribute__((target("arch=+zba"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -24,8 +23,7 @@ long foo(long a, long b){ > > ** add\s*a0,a1,a0 > > ** ... > > */ > > - > > - > > -long bar(long a, long b){ > > +long bar (long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-03.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-03.c > > index b4896cb2e277..44fabf68fd07 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-03.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-03.c > > @@ -1,5 +1,5 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > @@ -10,8 +10,10 @@ > > ** add\s*a0,a1,a0 > > ** ... > > */ > > -long foo() __attribute__((target("arch=rv64gc"))); > > -long foo(long a, long b){ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0" > > } } */ > > +long foo () __attribute__((target("arch=rv64gc"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -21,6 +23,7 @@ long foo(long a, long b){ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long bar(long a, long b){ > > +long bar (long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-04.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-04.c > > index 369d6514e5aa..258eaf4eb584 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-04.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-04.c > > @@ -1,5 +1,5 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > @@ -12,8 +12,10 @@ > > ** add\s*a0,a1,a0 > > ** ... > > */ > > -long foo() __attribute__((target("cpu=sifive-u74"))); > > -long foo(long a, long b){ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zaamo1p0_zalrsc1p0" } } */ > > +long foo () __attribute__((target("cpu=sifive-u74"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -23,6 +25,7 @@ long foo(long a, long b){ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long bar(long a, long b){ > > +long bar (long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-05.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-05.c > > index c75368dcebf9..1474f319e414 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-05.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-05.c > > @@ -1,5 +1,5 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > @@ -11,8 +11,9 @@ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long foo() __attribute__((target("cpu=sifive-u74;arch=rv64gc_zba"))); > > -long foo(long a, long b){ > > +long foo () __attribute__((target("cpu=sifive-u74;arch=rv64gc_zba"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -22,6 +23,7 @@ long foo(long a, long b){ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long bar(long a, long b){ > > +long bar (long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-06.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-06.c > > index 369c95eeb54b..32ecfaee319a 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-06.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-06.c > > @@ -1,5 +1,5 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > @@ -11,8 +11,10 @@ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long foo() > > __attribute__((target("cpu=sifive-u74;tune=sifive-5-series;arch=rv64gc_zba"))); > > -long foo(long a, long b){ > > +long foo () > > +__attribute__((target("cpu=sifive-u74;tune=sifive-5-series;arch=rv64gc_zba"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -22,6 +24,7 @@ long foo(long a, long b){ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long bar(long a, long b){ > > +long bar(long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-07.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-07.c > > index 4ff81166a626..f3066f4fcfea 100644 > > --- a/gcc/testsuite/gcc.target/riscv/target-attr-07.c > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-07.c > > @@ -1,5 +1,5 @@ > > /* { dg-do compile } */ > > -/* { dg-skip-if "" { *-*-* } { "-fno-fat-lto-objects" } } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > /* { dg-options "-march=rv64gc_zba -O2 -mabi=lp64 -mtune=rocket" } */ > > /* { dg-final { check-function-bodies "**" "" } } */ > > > > @@ -9,8 +9,9 @@ > > ** # tune = sifive-5-series > > ** ... > > */ > > -long foo() __attribute__((target("tune=sifive-5-series"))); > > -long foo(long a, long b){ > > +long foo () __attribute__((target("tune=sifive-5-series"))); > > +long foo (long a, long b) > > +{ > > return a + (b * 2); > > } > > > > @@ -20,6 +21,7 @@ long foo(long a, long b){ > > ** sh1add\s*a0,a1,a0 > > ** ... > > */ > > -long bar(long a, long b){ > > +long bar (long a, long b) > > +{ > > return a + (b * 2); > > } > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-08.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-08.c > > new file mode 100644 > > index 000000000000..e7792c1598e4 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-08.c > > @@ -0,0 +1,20 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +long foo () > > +__attribute__((target("arch=rv64gc_zbb"))) > > +__attribute__((target("arch=rv64gc_zba"))); > > + > > +/* > > +** foo: > > +** ... > > +** sh1add\s*a0,a1,a0 > > +** ... > > +*/ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zba1p0" > > } } */ > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-09.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-09.c > > new file mode 100644 > > index 000000000000..ec43ce95998b > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-09.c > > @@ -0,0 +1,19 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +long foo () > > +__attribute__((target("cpu=sifive-e20"))) > > +__attribute__((target("cpu=sifive-u74"))); > > + > > +/* > > +** foo: > > +** ... > > +** # tune = sifive-7-series > > +** ... > > +*/ > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-10.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-10.c > > new file mode 100644 > > index 000000000000..86a79c7d6ccf > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-10.c > > @@ -0,0 +1,19 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +long foo () > > +__attribute__((target("tune=rocket"))) > > +__attribute__((target("tune=sifive-u74"))); > > + > > +/* > > +** foo: > > +** ... > > +** # tune = sifive-7-series > > +** ... > > +*/ > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-11.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-11.c > > new file mode 100644 > > index 000000000000..6e02a98f1206 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-11.c > > @@ -0,0 +1,22 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +long foo () > > +__attribute__((target("arch=rv64gc_zbb"))); > > + > > +long foo () > > +__attribute__((target("arch=rv64gc_zba"))); > > + > > +/* > > +** foo: > > +** ... > > +** sh1add\s*a0,a1,a0 > > +** ... > > +*/ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zba1p0" > > } } */ > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-12.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-12.c > > new file mode 100644 > > index 000000000000..e0f8eafa040a > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-12.c > > @@ -0,0 +1,21 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +long foo () > > +__attribute__((target("cpu=sifive-e20"))); > > + > > +long foo () > > +__attribute__((target("cpu=sifive-u74"))); > > + > > +/* > > +** foo: > > +** ... > > +** # tune = sifive-7-series > > +** ... > > +*/ > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-13.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-13.c > > new file mode 100644 > > index 000000000000..0a26111956b9 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-13.c > > @@ -0,0 +1,21 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +long foo () > > +__attribute__((target("tune=rocket"))); > > + > > +long foo () > > +__attribute__((target("tune=sifive-u74"))); > > + > > +/* > > +** foo: > > +** ... > > +** # tune = sifive-7-series > > +** ... > > +*/ > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-14.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-14.c > > new file mode 100644 > > index 000000000000..59de060eec38 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-14.c > > @@ -0,0 +1,42 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +/* > > +** foo: > > +** ... > > +** sh1add\s*a0,a1,a0 > > +** ... > > +*/ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zba1p0" > > } } */ > > +long foo () __attribute__((target("arch=rv64gc_zba"))); > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > + > > +/* > > +** bar: > > +** ... > > +** slli\s*a1,a1,1 > > +** add\s*a0,a1,a0 > > +** ... > > +*/ > > +long bar (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > + > > +/* > > +** foo_th: > > +** ... > > +** th.addsl\s*a0,a0,a1,1 > > +** ... > > +*/ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_xtheadba1p0" > > } } */ > > +long foo_th () __attribute__((target("arch=rv64gc_xtheadba"))); > > +long foo_th (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > diff --git a/gcc/testsuite/gcc.target/riscv/target-attr-15.c > > b/gcc/testsuite/gcc.target/riscv/target-attr-15.c > > new file mode 100644 > > index 000000000000..5120ad7b1d62 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/riscv/target-attr-15.c > > @@ -0,0 +1,42 @@ > > +/* { dg-do compile } */ > > +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ > > +/* { dg-options "-march=rv64gc -O2 -mabi=lp64" } */ > > +/* { dg-final { check-function-bodies "**" "" } } */ > > + > > +/* > > +** foo: > > +** ... > > +** sh1add\s*a0,a1,a0 > > +** ... > > +*/ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_zba1p0" > > } } */ > > +long foo () __attribute__((target("arch=rv64gc_zba"))); > > +long foo (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > + > > +/* > > +** bar: > > +** ... > > +** slli\s*a1,a1,1 > > +** add\s*a0,a1,a0 > > +** ... > > +*/ > > +long bar (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > + > > +/* > > +** foo_th: > > +** ... > > +** th.addsl\s*a0,a0,a1,1 > > +** ... > > +*/ > > +/* { dg-final { scan-assembler ".option arch, > > rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_zaamo1p0_zalrsc1p0_xtheadba1p0" > > } } */ > > +long foo_th () __attribute__((target("arch=+xtheadba"))); > > +long foo_th (long a, long b) > > +{ > > + return a + (b * 2); > > +} > > -- > > 2.45.2 > >