From: Alfie Richards <[email protected]>

This changes the hook from being symmetric, to explicitly taking a version
string from the old decl and one from the new decl.

Additionally, it documents that we support emitting a diagnostic if the strings
do imply the same version, but are incompatible.

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 to use the correct decl in
        call to hook.
        * doc/tm.texi: Regenerate.
---
 gcc/doc/tm.texi |  6 ++++--
 gcc/target.def  | 10 ++++++----
 gcc/tree.cc     | 22 +++++++++++++++++-----
 3 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 989e01fbd18..d044084f91f 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10997,9 +10997,11 @@ 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{old_str}, string_slice @var{new_str})
 This target hook returns @code{true} if the target/target-version strings
-@var{fn1} and @var{fn2} imply the same function version.
+@var{old_str} and @var{new_str} imply the same function version.
+Can also produce a diagnostic if the version strings do imply the same
+version, but are incompatible.
 @end deftypefn
 
 @deftypefn {Target Hook} bool TARGET_OPTION_FUNCTIONS_B_RESOLVABLE_FROM_A 
(tree @var{decl_a}, tree @var{decl_v}, tree @var{base})
diff --git a/gcc/target.def b/gcc/target.def
index 3e58dcf54a9..58be3eaa9f4 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -6925,13 +6925,15 @@ 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 OLD_STR and NEW_STR define the same version
+   of a function.  */
 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),
+@var{old_str} and @var{new_str} imply the same function version.\n\
+Can also produce a diagnostic if the version strings do imply the same\n\
+version, but are incompatible.",
+ bool, (string_slice old_str, string_slice new_str),
  hook_stringslice_stringslice_unreachable)
 
 /* Checks if we can be certain that function DECL_A could resolve DECL_B.  */
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 966da8052a4..16d9e454d77 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -15557,8 +15557,12 @@ disjoint_version_decls (tree fn1, tree fn2)
     {
       /* As this is symmetric, can remove the case where fn2 is target clone
         and fn1 is target version by swapping here.  */
+      bool swapped = false;
       if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (fn2)))
-       std::swap (fn1, fn2);
+       {
+         swapped = true;
+         std::swap (fn1, fn2);
+       }
 
       if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (fn1)))
        {
@@ -15571,8 +15575,12 @@ 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))
-                     return false;
+                   {
+                     if (swapped)
+                       std::swap (v1, v2);
+                     if (targetm.target_option.same_function_versions (v1, v2))
+                       return false;
+                   }
                }
              return true;
            }
@@ -15589,8 +15597,12 @@ 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))
-                 return false;
+               {
+                 if (swapped)
+                   std::swap (v1, v2);
+                 if (targetm.target_option.same_function_versions (v1, v2))
+                   return false;
+               }
              return true;
            }
        }
-- 
2.34.1

Reply via email to