On Mon, Dec 15, 2025 at 11:28 PM Andrew Pinski
<[email protected]> wrote:
>
> On Fri, Nov 7, 2025 at 8:08 AM Alfie Richards <[email protected]> wrote:
> >
> > 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 argument.
> >         * config/riscv/riscv.cc (riscv_same_function_versions): Update hook 
> > impl
> >         for new argument.
> >         * hooks.cc (hook_stringslice_stringslice_unreachable): Changed to...
> >         (hook_stringslice_stringslice_locationtptr_unreachable ): ...this 
> > and
> >         add extra argument.
> > ---
> >  gcc/config/aarch64/aarch64.cc | 19 +++++++++++--------
> >  gcc/config/riscv/riscv.cc     |  2 +-
> >  gcc/doc/tm.texi               |  8 +++++++-
> >  gcc/hooks.cc                  |  2 +-
> >  gcc/target.def                | 18 +++++++++++++-----
> >  gcc/tree.cc                   | 34 +++++++++++++++++++---------------
> >  6 files changed, 52 insertions(+), 31 deletions(-)
> >
> > diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> > index b3e752bbd8c..abc5bafb50d 100644
> > --- a/gcc/config/aarch64/aarch64.cc
> > +++ b/gcc/config/aarch64/aarch64.cc
> > @@ -21278,19 +21278,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, string_slice new_str,
> > +                               location_t *)
> >  {
> >    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
> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> > index 7d723fc4d69..a8962860a6b 100644
> > --- a/gcc/config/riscv/riscv.cc
> > +++ b/gcc/config/riscv/riscv.cc
> > @@ -14744,7 +14744,7 @@ 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, string_slice v2, location_t 
> > *)
> >  {
> >    struct riscv_feature_bits mask1, mask2;
> >    int prio1, prio2;
> > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> > index fd208f53844..17d8c3ac40e 100644
> > --- a/gcc/doc/tm.texi
> > +++ b/gcc/doc/tm.texi
> > @@ -10997,9 +10997,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}, string_slice @var{fn2}, location_t *@var{loc})
> >  This target hook returns @code{true} if the target/target-version strings
> >  @var{fn1} and @var{fn2} imply the same function version.
> > +
> > +If @var{loc} is 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 at @var{loc}.
>
> Constantify loc since this target hook should NOT be changing what loc
> points to.
> I am not sure I like the idea of passing a pointer here for making
> this specify if we are merging from the same decl or from different
> declarations.
> Also it would be useful to print out where the old declaration was.
> So I think the interface should be:
> (string_slice fn1, location_t loc1, string_slice fn2, location_t loc2)
>
> And then have UNKNOWN_LOC for both locations for the case of not from
> an earlier/later declaration.
> And then in aarch64, do an error for the new decl (loc2) and a note
> where the old one was.

The other option is to pass both decls. That actually might be the
better option here.
That is:
(string_slice fn1, tree old_decl, string_slice fn2, tree new_decl)

And then the error message in aarch64 would be something like:
error ("%q+D has an inconsistent function multi-version priority
value", new_decl);
note("%q+D was previously declared here with priority value of %d",
old_decl, old_priority);

Thanks,
Andrew Pinski

>
> Thanks,
> Andrew
>
> >  @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/hooks.cc b/gcc/hooks.cc
> > index 5321142495b..ff2bd80ae77 100644
> > --- a/gcc/hooks.cc
> > +++ b/gcc/hooks.cc
> > @@ -595,7 +595,7 @@ hook_stringslice_locationtptr_true (string_slice, 
> > location_t *)
> >  }
> >
> >  bool
> > -hook_stringslice_stringslice_unreachable (string_slice, string_slice)
> > +hook_stringslice_stringslice_locationtptr_unreachable (string_slice, 
> > string_slice, location_t *)
> >  {
> >    gcc_unreachable ();
> >  }
> > diff --git a/gcc/target.def b/gcc/target.def
> > index f288329ffca..dae7da331c2 100644
> > --- a/gcc/target.def
> > +++ b/gcc/target.def
> > @@ -6954,14 +6954,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 LOC 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{loc} is non @code{NULL} then @var{fn1} and @var{fn2} are from an\n\
> > +earlier and a later declaration respectively, and the hook diagnoses any\n\
> > +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 at @var{loc}.",
> > + bool, (string_slice fn1, string_slice fn2, location_t *loc),
> > + hook_stringslice_stringslice_locationtptr_unreachable)
> >
> >  /* Checks if we can be certain that function DECL_A could resolve DECL_B.  
> > */
> >  DEFHOOK
> > diff --git a/gcc/tree.cc b/gcc/tree.cc
> > index 298784e6960..c4cb65e3220 100644
> > --- a/gcc/tree.cc
> > +++ b/gcc/tree.cc
> > @@ -15605,7 +15605,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, 
> > v2,
> > +                                                                     NULL))
> >                       return false;
> >                 }
> >               return true;
> > @@ -15623,7 +15624,7 @@ 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, v2, 
> > NULL))
> >                   return false;
> >               return true;
> >             }
> > @@ -15642,7 +15643,7 @@ 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, v2, NULL))
> >             return false;
> >
> >           return true;
> > @@ -15690,30 +15691,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, newv, &DECL_SOURCE_LOCATION (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, newv, &DECL_SOURCE_LOCATION (new_decl)))
> >               matched = true;
> >           if (!matched)
> >             mergeable = false;
> > @@ -15762,9 +15765,10 @@ 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, new_target_attr,
> > +             &DECL_SOURCE_LOCATION (new_decl)));
> >  }
> >
> >  void
> > --
> > 2.34.1
> >

Reply via email to