]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
targethooks: Change SAME_FUNCTION_VERSIONS hook to support checking mergeability
authorAlfie Richards <alfie.richards@arm.com>
Tue, 7 Oct 2025 13:01:09 +0000 (13:01 +0000)
committerAlfie Richards <alfie.richards@arm.com>
Wed, 7 Jan 2026 11:51:07 +0000 (11:51 +0000)
This changes the hook to support checking version mergeability for cases
where the version strings do imply the same version, but are conflicting
in some other way so cannot be merged.

This is a change required for adding priority version support in aarch64.

gcc/ChangeLog:

* target.def (TARGET_OPTION_SAME_FUNCTION_VERSIONS): Update
documentation.
* tree.cc (disjoint_version_decls): Change for new NULL parameter
to same_function_versions.
(diagnose_versioned_decls): Update to pass diagnostic location to
same_function_versions.
* doc/tm.texi: Regenerate.
* config/aarch64/aarch64.cc (aarch64_same_function_versions):
Update hook impl for new arguments.
* config/riscv/riscv.cc (riscv_same_function_versions): Update
hook impl for new arguments.
* config/loongarch/loongarch.cc
(loongarch_same_function_versions): Likewise
* hooks.cc (hook_stringslice_stringslice_unreachable): Changed
to...
(hook_stringslice_consttree_stringslice_consttree_unreachable):
...this and add extra arguments.
* hooks.h (hook_stringslice_stringslice_unreachable): Changed
to...
(hook_stringslice_consttree_stringslice_consttree_unreachable):
and add extra arguments.

gcc/config/aarch64/aarch64.cc
gcc/config/loongarch/loongarch.cc
gcc/config/riscv/riscv.cc
gcc/doc/tm.texi
gcc/hooks.cc
gcc/hooks.h
gcc/target.def
gcc/tree.cc

index 01828a95bb6210f21034e82864d1c31518bda866..3ba2e686ebfc1b48c5ce1217834b6aa82e1c608e 100644 (file)
@@ -21670,19 +21670,22 @@ aarch64_get_function_versions_dispatcher (void *decl)
    function.  */
 
 bool
-aarch64_same_function_versions (string_slice str1, string_slice str2)
+aarch64_same_function_versions (string_slice old_str, const_tree,
+                               string_slice new_str, const_tree)
 {
   enum aarch_parse_opt_result parse_res;
-  aarch64_fmv_feature_mask feature_mask1;
-  aarch64_fmv_feature_mask feature_mask2;
-  parse_res = aarch64_parse_fmv_features (str1, NULL,
-                                         &feature_mask1, NULL);
+  aarch64_fmv_feature_mask old_feature_mask;
+  aarch64_fmv_feature_mask new_feature_mask;
+
+  parse_res = aarch64_parse_fmv_features (old_str, NULL, &old_feature_mask,
+                                         NULL);
   gcc_assert (parse_res == AARCH_PARSE_OK);
-  parse_res = aarch64_parse_fmv_features (str2, NULL,
-                                         &feature_mask2, NULL);
+
+  parse_res = aarch64_parse_fmv_features (new_str, NULL, &new_feature_mask,
+                                         NULL);
   gcc_assert (parse_res == AARCH_PARSE_OK);
 
-  return feature_mask1 == feature_mask2;
+  return old_feature_mask == new_feature_mask;
 }
 
 /* Implement TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P.  Use an opt-out
index 836a210e02bd05f06927d20d68c73d72101613de..437742c74210ec38e9ac3beb0a099109cbb7b7f3 100644 (file)
@@ -12165,7 +12165,8 @@ loongarch_generate_version_dispatcher_body (void *node_p)
    This assumes that FN1 and FN2 have the same signature.  */
 
 bool
-loongarch_option_same_function_versions (string_slice str1, string_slice str2)
+loongarch_option_same_function_versions (string_slice str1, const_tree,
+                                        string_slice str2, const_tree)
 {
   loongarch_fmv_feature_mask feature_mask1;
   loongarch_fmv_feature_mask feature_mask2;
index 40705e079c754aac8dbe316ebf39ff0ceb66357b..669a9a0935c6398c1b50b73234181f7081622438 100644 (file)
@@ -14869,7 +14869,8 @@ compare_fmv_features (const struct riscv_feature_bits &mask1,
    version.  */
 
 bool
-riscv_same_function_versions (string_slice v1, string_slice v2)
+riscv_same_function_versions (string_slice v1, const_tree, string_slice v2,
+                             const_tree)
 {
   struct riscv_feature_bits mask1, mask2;
   int prio1, prio2;
index 4a6aa7bfa4d0c57a32feb4ac40c22b23d4a9740a..394a46fdbaa590ed686cb94333f24ab6553b2eee 100644 (file)
@@ -11028,9 +11028,15 @@ changed via the optimize attribute or pragma, see
 @code{TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE}
 @end deftypefn
 
-@deftypefn {Target Hook} bool TARGET_OPTION_SAME_FUNCTION_VERSIONS (string_slice @var{fn1}, string_slice @var{fn2})
+@deftypefn {Target Hook} bool TARGET_OPTION_SAME_FUNCTION_VERSIONS (string_slice @var{fn1}, const_tree @var{decl1}, string_slice @var{fn2}, const_tree @var{decl2})
 This target hook returns @code{true} if the target/target-version strings
 @var{fn1} and @var{fn2} imply the same function version.
+
+If @var{decl1} and @var{decl2} are non @code{NULL} then @var{fn1} and
+@var{fn2} are from an earlier and a later declaration respectively, and the
+hook diagnoses any version string incompatibility for these decls.
+If the version strings are incompatible and the declarations can not be
+merged, then hook emits an error.
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_OPTION_FUNCTIONS_B_RESOLVABLE_FROM_A (tree @var{decl_a}, tree @var{decl_v}, tree @var{base})
index 640b648b02dcde815b2162cc46bd5acd565b8230..2b47fd3e50f8e5f484f5fbdc08139dfa5f747159 100644 (file)
@@ -595,7 +595,10 @@ hook_stringslice_locationtptr_true (string_slice, location_t *)
 }
 
 bool
-hook_stringslice_stringslice_unreachable (string_slice, string_slice)
+hook_stringslice_consttree_stringslice_consttree_unreachable (string_slice,
+                                                             const_tree,
+                                                             string_slice,
+                                                             const_tree)
 {
   gcc_unreachable ();
 }
index 32f3fa7dca8cae0aba22bba500251611380f5d1a..1ad4abb5500c456b589d2933f804cf57ce3b9d90 100644 (file)
@@ -139,6 +139,6 @@ extern opt_machine_mode hook_optmode_mode_uhwi_none (machine_mode,
                                                     unsigned HOST_WIDE_INT);
 
 extern bool hook_stringslice_locationtptr_true (string_slice, location_t *);
-extern bool hook_stringslice_stringslice_unreachable (string_slice, string_slice);
+extern bool hook_stringslice_consttree_stringslice_consttree_unreachable (string_slice, const_tree, string_slice, const_tree);
 
 #endif
index 2b9b441f8e3f9a795c948bf358f23e294062d3ce..206c94f8749ba8f242229d36da0049826c342502 100644 (file)
@@ -6971,14 +6971,22 @@ changed via the optimize attribute or pragma, see\n\
  void, (void),
  hook_void_void)
 
-/* This function returns true if FN1 and FN2 define the same version of a
-   function.  */
+/* This function returns true if FN1 and FN2 define the same version
+   of a function.
+   If DECL1 and DECL2 is not-null then emit a diagnostic if the versions do
+   imply the same version, but are not mergeable.  */
 DEFHOOK
 (same_function_versions,
  "This target hook returns @code{true} if the target/target-version strings\n\
-@var{fn1} and @var{fn2} imply the same function version.",
- bool, (string_slice fn1, string_slice fn2),
- hook_stringslice_stringslice_unreachable)
+@var{fn1} and @var{fn2} imply the same function version.\n\
+\n\
+If @var{decl1} and @var{decl2} are non @code{NULL} then @var{fn1} and\n\
+@var{fn2} are from an earlier and a later declaration respectively, and the\n\
+hook diagnoses any version string incompatibility for these decls.\n\
+If the version strings are incompatible and the declarations can not be\n\
+merged, then hook emits an error.",
+ bool, (string_slice fn1, const_tree decl1, string_slice fn2, const_tree decl2),
+ hook_stringslice_consttree_stringslice_consttree_unreachable)
 
 /* Checks if we can be certain that function DECL_A could resolve DECL_B.  */
 DEFHOOK
index 3e02f996965ed9881c56e2e962a4d314f06dc75c..610a3fc82ab8bc3aa53ce63adfe3ad5eeb8674bb 100644 (file)
@@ -15610,7 +15610,8 @@ disjoint_version_decls (tree fn1, tree fn2)
              for (string_slice v1 : fn1_versions)
                {
                  for (string_slice v2 : fn2_versions)
-                   if (targetm.target_option.same_function_versions (v1, v2))
+                   if (targetm.target_option.same_function_versions
+                         (v1, NULL_TREE, v2, NULL_TREE))
                      return false;
                }
              return true;
@@ -15628,7 +15629,8 @@ disjoint_version_decls (tree fn1, tree fn2)
              if (!v2.is_valid ())
                v2 = "default";
              for (string_slice v1 : fn1_versions)
-               if (targetm.target_option.same_function_versions (v1, v2))
+               if (targetm.target_option.same_function_versions
+                     (v1, NULL_TREE, v2, NULL_TREE))
                  return false;
              return true;
            }
@@ -15647,7 +15649,8 @@ disjoint_version_decls (tree fn1, tree fn2)
          if (!v2.is_valid ())
            v2 = "default";
 
-         if (targetm.target_option.same_function_versions (v1, v2))
+         if (targetm.target_option.same_function_versions (v1, NULL_TREE,
+                                                           v2, NULL_TREE))
            return false;
 
          return true;
@@ -15695,30 +15698,32 @@ diagnose_versioned_decls (tree old_decl, tree new_decl)
      the two sets of target_clones imply the same set of versions.  */
   if (old_target_clones_attr && new_target_clones_attr)
     {
-      auto_vec<string_slice> fn1_versions = get_clone_versions (old_decl);
-      auto_vec<string_slice> fn2_versions = get_clone_versions (new_decl);
+      auto_vec<string_slice> old_versions = get_clone_versions (old_decl);
+      auto_vec<string_slice> new_versions = get_clone_versions (new_decl);
 
       bool mergeable = true;
 
-      if (fn1_versions.length () != fn2_versions.length ())
+      if (old_versions.length () != new_versions.length ())
        mergeable = false;
 
       /* Check both inclusion directions.  */
-      for (auto fn1v : fn1_versions)
+      for (auto oldv: old_versions)
        {
          bool matched = false;
-         for (auto fn2v : fn2_versions)
-           if (targetm.target_option.same_function_versions (fn1v, fn2v))
+         for (auto newv: new_versions)
+           if (targetm.target_option.same_function_versions (oldv, old_decl,
+                                                             newv, new_decl))
              matched = true;
          if (!matched)
            mergeable = false;
        }
 
-      for (auto fn2v : fn2_versions)
+      for (auto newv: new_versions)
        {
          bool matched = false;
-         for (auto fn1v : fn1_versions)
-           if (targetm.target_option.same_function_versions (fn1v, fn2v))
+         for (auto oldv: old_versions)
+           if (targetm.target_option.same_function_versions (oldv, old_decl,
+                                                             newv, new_decl))
              matched = true;
          if (!matched)
            mergeable = false;
@@ -15767,9 +15772,9 @@ diagnose_versioned_decls (tree old_decl, tree new_decl)
       return true;
     }
 
-  /* The only remaining case is two target_version annotated decls.  Must
-     be mergeable as otherwise are distinct.  */
-  return false;
+  /* The only remaining case is two target_version annotated decls.  */
+  return !targetm.target_option.same_function_versions
+           (old_target_attr, old_decl, new_target_attr, new_decl);
 }
 
 void