Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P for LoongArch.
This is used to determine whether the attribute ((target_version ("...")))
is valid and process it.

Define TARGET_HAS_FMV_TARGET_ATTRIBUTE to 0 to use "target_version"
for function versioning.

gcc/ChangeLog:

        * config/loongarch/loongarch.cc
        (loongarch_process_target_version_attr): New function.
        (loongarch_option_valid_version_attribute_p): New function.
        (TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P): Define.
        * config/loongarch/loongarch.h
        (TARGET_HAS_FMV_TARGET_ATTRIBUTE): Define it to 0.

---
 gcc/config/loongarch/loongarch.cc | 92 +++++++++++++++++++++++++++++++
 gcc/config/loongarch/loongarch.h  |  2 +
 2 files changed, 94 insertions(+)

diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 3fe8c766cc7..65b8ff74d90 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -11264,6 +11264,94 @@ loongarch_can_inline_p (tree caller, tree callee)
   return true;
 }
 
+/* Parse the tree in ARGS that contains the target_version attribute
+   information and update the global target options space.  If LOC is nonnull,
+   report diagnostics against *LOC, otherwise remain silent.  */
+
+bool
+loongarch_process_target_version_attr (tree args, tree fndecl)
+{
+  location_t loc = DECL_SOURCE_LOCATION (fndecl);
+
+  if (TREE_CODE (args) == TREE_LIST)
+    {
+      if (TREE_CHAIN (args))
+       {
+         if (loc)
+           error_at (loc, "attribute %<target_version%> "
+                     "has multiple values");
+         return false;
+       }
+      args = TREE_VALUE (args);
+    }
+
+  if (!args || TREE_CODE (args) != STRING_CST)
+    {
+      if (loc)
+       error_at (loc, "attribute %<target_version%> argument not a string");
+      return false;
+    }
+
+  string_slice str = TREE_STRING_POINTER (args);
+
+  if (str == "default")
+    return true;
+
+  return loongarch_process_target_attr (args, fndecl);
+}
+
+/* Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P.  This is used to
+   process attribute ((target_version ("..."))).  */
+
+static bool
+loongarch_option_valid_version_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);
+
+  /* Save the current target options to restore at the end.  */
+  cl_target_option_save (&cur_target, &global_options, &global_options_set);
+
+  /* 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)
+    {
+      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
+    cl_target_option_restore (&global_options, &global_options_set,
+                             TREE_TARGET_OPTION (target_option_current_node));
+
+  ret = loongarch_process_target_version_attr (args, fndecl);
+
+  /* Set up any additional state.  */
+  if (ret)
+    {
+      loongarch_option_override_internal (&la_target,
+                                         &global_options,
+                                         &global_options_set);
+      new_target = build_target_option_node (&global_options,
+                                            &global_options_set);
+    }
+  else
+    new_target = NULL;
+
+  if (fndecl && ret)
+    DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
+
+  cl_target_option_restore (&global_options, &global_options_set, &cur_target);
+
+  return ret;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -11547,6 +11635,10 @@ loongarch_can_inline_p (tree caller, tree callee)
 #undef TARGET_CAN_INLINE_P
 #define TARGET_CAN_INLINE_P loongarch_can_inline_p
 
+#undef TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P
+#define TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P \
+  loongarch_option_valid_version_attribute_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-loongarch.h"
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index e8819bf1480..b3fb4828057 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -1293,3 +1293,5 @@ struct GTY (()) machine_function
 
 #define TARGET_EXPLICIT_RELOCS \
   (la_opt_explicit_relocs == EXPLICIT_RELOCS_ALWAYS)
+
+#define TARGET_HAS_FMV_TARGET_ATTRIBUTE 0
-- 
2.34.1

Reply via email to