]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Rewrite target attribute handling
authorChristoph Müllner <christoph.muellner@vrull.eu>
Sat, 22 Jun 2024 19:59:04 +0000 (21:59 +0200)
committerChristoph Müllner <christoph.muellner@vrull.eu>
Mon, 15 Jul 2024 17:06:12 +0000 (19:06 +0200)
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 target/115554
PR target/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.muellner@vrull.eu>
23 files changed:
gcc/common/config/riscv/riscv-common.cc
gcc/config/riscv/riscv-c.cc
gcc/config/riscv/riscv-subset.h
gcc/config/riscv/riscv-target-attr.cc
gcc/config/riscv/riscv.cc
gcc/config/riscv/riscv.opt
gcc/testsuite/gcc.target/riscv/pr115554.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/pr115562.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-01.c
gcc/testsuite/gcc.target/riscv/target-attr-02.c
gcc/testsuite/gcc.target/riscv/target-attr-03.c
gcc/testsuite/gcc.target/riscv/target-attr-04.c
gcc/testsuite/gcc.target/riscv/target-attr-05.c
gcc/testsuite/gcc.target/riscv/target-attr-06.c
gcc/testsuite/gcc.target/riscv/target-attr-07.c
gcc/testsuite/gcc.target/riscv/target-attr-08.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-09.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-12.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/target-attr-15.c [new file with mode: 0644]

index d883efa7a3ab7783311b11b5b225db9863947049..8e9beb6801f98870e2bbbec96f1fc00604cf4a94 100644 (file)
@@ -462,110 +462,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;
@@ -1644,8 +1547,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();
 }
@@ -1833,8 +1736,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,
@@ -1861,8 +1763,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
@@ -1878,15 +1778,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);
 }
index 43c8eecbb6fff360dc338b975404e705d1ac3c67..71112d9c66d769b4192db5877752617a2dc6af5c 100644 (file)
@@ -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;
 
index 7dc196a2007403b314bce39910bd956e48fb07f3..279716feab572ffebe4dec873f35d61d881e5468 100644 (file)
@@ -112,11 +112,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 *);
 
index 3d7753f6457410367a244108c0eaece56bd097cf..3178061439491495a4575f3023bb96b4ec2bdc66 100644 (file)
@@ -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;
 }
index 084a592a313cf97d68a9d1be0fb27e83b97b2b58..19b9b2daa9507401842efdbf12f356e0796a0dde 100644 (file)
@@ -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)
@@ -9441,17 +9450,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)
index a1d70b6363821847910ea267b724a931d0250efc..edf1c6d85f396663dc50947da8221642baeae8ed 100644 (file)
@@ -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 (file)
index 0000000..e7dcde6
--- /dev/null
@@ -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 (file)
index 0000000..b20f69d
--- /dev/null
@@ -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) {}
index b3f3d65d543f2819c6dd2c84906275673ee18591..bea1986dc5b487afa7809161b52b3aefdbe97e8e 100644 (file)
@@ -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_zca1p0_zcd1p0_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);
 }
index c010089a823b871df788a5f6cab83f0117068d02..6ff617fe3731e6f9d5c4245ccb92271d10ee118f 100644 (file)
@@ -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_zca1p0_zcd1p0_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);
 }
index b4896cb2e27705b2d7b33f9f3f16d043b74cc761..44fabf68fd0743ec367c7ad15fb5eab5ecd865ff 100644 (file)
@@ -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 "**" "" } } */
 
 **   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);
 }
index 369d6514e5aa34807d3ca0420be5b1f19f5b5cdd..258eaf4eb58443be6abd0ae696ee706dff886650 100644 (file)
@@ -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 "**" "" } } */
 
 **   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);
 }
index c75368dcebf9c41d693b9aa8253817b391d5fcbb..1474f319e414d2bf753bec5b03d687913bb590eb 100644 (file)
@@ -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);
 }
index 369c95eeb54bc6eae931c9b142711ddbc2786074..32ecfaee319ac4cf085edf7b8ffb1d5682fbcff7 100644 (file)
@@ -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 "**" "" } } */
 
 **   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);
 }
index 4ff81166a62637c205ba5256668bd76be77d635f..f3066f4fcfea20e4dd2e0906722396c4296de1d3 100644 (file)
@@ -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 (file)
index 0000000..0c4ac16
--- /dev/null
@@ -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_zca1p0_zcd1p0_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 (file)
index 0000000..ec43ce9
--- /dev/null
@@ -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 (file)
index 0000000..86a79c7
--- /dev/null
@@ -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 (file)
index 0000000..d6eec04
--- /dev/null
@@ -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_zca1p0_zcd1p0_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 (file)
index 0000000..e0f8eaf
--- /dev/null
@@ -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 (file)
index 0000000..0a26111
--- /dev/null
@@ -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 (file)
index 0000000..03063c9
--- /dev/null
@@ -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_zca1p0_zcd1p0_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_zca1p0_zcd1p0_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 (file)
index 0000000..914e1e6
--- /dev/null
@@ -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_zca1p0_zcd1p0_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_zca1p0_zcd1p0_xtheadba1p0" } } */
+long foo_th () __attribute__((target("arch=+xtheadba")));
+long foo_th (long a, long b)
+{
+  return a + (b * 2);
+}