Re: [PATCH v3 4/5] Add support for target_version attribute

2023-12-14 Thread Richard Sandiford
Andrew Carlotti  writes:
> This patch adds support for the "target_version" attribute to the middle
> end and the C++ frontend, which will be used to implement function
> multiversioning in the aarch64 backend.
>
> On targets that don't use the "target" attribute for multiversioning,
> there is no conflict between the "target" and "target_clones"
> attributes.  This patch therefore makes the mutual exclusion in
> C-family, D and Ada conditonal upon the value of the
> expanded_clones_attribute target hook.
>
> The "target_version" attribute is only added to C++ in this patch,
> because this is currently the only frontend which supports
> multiversioning using the "target" attribute.  Support for the
> "target_version" attribute will be extended to C at a later date.
>
> Targets that currently use the "target" attribute for function
> multiversioning (i.e. i386 and rs6000) are not affected by this patch.
>
> Ok for master?
>
> gcc/ChangeLog:
>
>   * attribs.cc (decl_attributes): Pass attribute name to target.
>   (is_function_default_version): Update comment to specify
>   incompatibility with target_version attributes.
>   * cgraphclones.cc (cgraph_node::create_version_clone_with_body):
>   Call valid_version_attribute_p for target_version attributes.
>   * defaults.h (TARGET_HAS_FMV_TARGET_ATTRIBUTE): New macro.
>   * target.def (valid_version_attribute_p): New hook.
>   * doc/tm.texi.in: Add new hook.
>   * doc/tm.texi: Regenerate.
>   * multiple_target.cc (create_dispatcher_calls): Remove redundant
>   is_function_default_version check.
>   (expand_target_clones): Use target macro to pick attribute name.
>   * targhooks.cc (default_target_option_valid_version_attribute_p):
>   New.
>   * targhooks.h (default_target_option_valid_version_attribute_p):
>   New.
>   * tree.h (DECL_FUNCTION_VERSIONED): Update comment to include
>   target_version attributes.
>
> gcc/c-family/ChangeLog:
>
>   * c-attribs.cc (attr_target_exclusions): Make
>   target/target_clones exclusion target-dependent.
>   (attr_target_clones_exclusions): Ditto, and add target_version.
>   (attr_target_version_exclusions): New.
>   (c_common_attribute_table): Add target_version.
>   (handle_target_version_attribute): New.
>
> gcc/ada/ChangeLog:
>
>   * gcc-interface/utils.cc (attr_target_exclusions): Make
>   target/target_clones exclusion target-dependent.
>   (attr_target_clones_exclusions): Ditto.
>
> gcc/d/ChangeLog:
>
>   * d-attribs.cc (attr_target_exclusions): Make
>   target/target_clones exclusion target-dependent.
>   (attr_target_clones_exclusions): Ditto.
>
> gcc/cp/ChangeLog:
>
>   * decl2.cc (check_classfn): Update comment to include
>   target_version attributes.

The front-end changes look mechanical, so: OK with the nit below fixed
unless anyone objects in 24 hours, or asks for more time.

> diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
> index 
> f2c504ddf8d3df11abe81aec695c9eea0b39da6c..5d946c33b212c5ea50e7a73524e8c1d062280956
>  100644
> --- a/gcc/ada/gcc-interface/utils.cc
> +++ b/gcc/ada/gcc-interface/utils.cc
> @@ -145,14 +145,16 @@ static const struct attribute_spec::exclusions 
> attr_noinline_exclusions[] =
>  
>  static const struct attribute_spec::exclusions attr_target_exclusions[] =
>  {
> -  { "target_clones", true, true, true },
> +  { "target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
> +TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE },
>{ NULL, false, false, false },
>  };
>  
>  static const struct attribute_spec::exclusions 
> attr_target_clones_exclusions[] =
>  {
>{ "always_inline", true, true, true },
> -  { "target", true, true, true },
> +  { "target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, 
> TARGET_HAS_FMV_TARGET_ATTRIBUTE,
> +TARGET_HAS_FMV_TARGET_ATTRIBUTE },
>{ NULL, false, false, false },
>  };
>  
> diff --git a/gcc/attribs.cc b/gcc/attribs.cc
> index 
> c7209c26acc9faf699774b0ef669ec6748b9073d..19cccf2d7ca4fdd6a46a01884393c6779333dbc5
>  100644
> --- a/gcc/attribs.cc
> +++ b/gcc/attribs.cc
> @@ -657,7 +657,8 @@ decl_attributes (tree *node, tree attributes, int flags,
>   options to the attribute((target(...))) list.  */
>if (TREE_CODE (*node) == FUNCTION_DECL
>&& current_target_pragma
> -  && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
> +  && targetm.target_option.valid_attribute_p (*node,
> +   get_identifier ("target"),
> current_target_pragma, 0))
>  {
>tree cur_attr = lookup_attribute ("target", attributes);
> @@ -1241,8 +1242,9 @@ make_dispatcher_decl (const tree decl)
>return func_decl;  
>  }
>  
> -/* Returns true if decl is multi-versioned and DECL is the default function,
> -   that is it is not tagged with target specific optimization.  */
> +/* 

[PATCH v3 4/5] Add support for target_version attribute

2023-12-06 Thread Andrew Carlotti
This patch adds support for the "target_version" attribute to the middle
end and the C++ frontend, which will be used to implement function
multiversioning in the aarch64 backend.

On targets that don't use the "target" attribute for multiversioning,
there is no conflict between the "target" and "target_clones"
attributes.  This patch therefore makes the mutual exclusion in
C-family, D and Ada conditonal upon the value of the
expanded_clones_attribute target hook.

The "target_version" attribute is only added to C++ in this patch,
because this is currently the only frontend which supports
multiversioning using the "target" attribute.  Support for the
"target_version" attribute will be extended to C at a later date.

Targets that currently use the "target" attribute for function
multiversioning (i.e. i386 and rs6000) are not affected by this patch.

Ok for master?

gcc/ChangeLog:

* attribs.cc (decl_attributes): Pass attribute name to target.
(is_function_default_version): Update comment to specify
incompatibility with target_version attributes.
* cgraphclones.cc (cgraph_node::create_version_clone_with_body):
Call valid_version_attribute_p for target_version attributes.
* defaults.h (TARGET_HAS_FMV_TARGET_ATTRIBUTE): New macro.
* target.def (valid_version_attribute_p): New hook.
* doc/tm.texi.in: Add new hook.
* doc/tm.texi: Regenerate.
* multiple_target.cc (create_dispatcher_calls): Remove redundant
is_function_default_version check.
(expand_target_clones): Use target macro to pick attribute name.
* targhooks.cc (default_target_option_valid_version_attribute_p):
New.
* targhooks.h (default_target_option_valid_version_attribute_p):
New.
* tree.h (DECL_FUNCTION_VERSIONED): Update comment to include
target_version attributes.

gcc/c-family/ChangeLog:

* c-attribs.cc (attr_target_exclusions): Make
target/target_clones exclusion target-dependent.
(attr_target_clones_exclusions): Ditto, and add target_version.
(attr_target_version_exclusions): New.
(c_common_attribute_table): Add target_version.
(handle_target_version_attribute): New.

gcc/ada/ChangeLog:

* gcc-interface/utils.cc (attr_target_exclusions): Make
target/target_clones exclusion target-dependent.
(attr_target_clones_exclusions): Ditto.

gcc/d/ChangeLog:

* d-attribs.cc (attr_target_exclusions): Make
target/target_clones exclusion target-dependent.
(attr_target_clones_exclusions): Ditto.

gcc/cp/ChangeLog:

* decl2.cc (check_classfn): Update comment to include
target_version attributes.


diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 
f2c504ddf8d3df11abe81aec695c9eea0b39da6c..5d946c33b212c5ea50e7a73524e8c1d062280956
 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -145,14 +145,16 @@ static const struct attribute_spec::exclusions 
attr_noinline_exclusions[] =
 
 static const struct attribute_spec::exclusions attr_target_exclusions[] =
 {
-  { "target_clones", true, true, true },
+  { "target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
+TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE },
   { NULL, false, false, false },
 };
 
 static const struct attribute_spec::exclusions attr_target_clones_exclusions[] 
=
 {
   { "always_inline", true, true, true },
-  { "target", true, true, true },
+  { "target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE,
+TARGET_HAS_FMV_TARGET_ATTRIBUTE },
   { NULL, false, false, false },
 };
 
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index 
c7209c26acc9faf699774b0ef669ec6748b9073d..19cccf2d7ca4fdd6a46a01884393c6779333dbc5
 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -657,7 +657,8 @@ decl_attributes (tree *node, tree attributes, int flags,
  options to the attribute((target(...))) list.  */
   if (TREE_CODE (*node) == FUNCTION_DECL
   && current_target_pragma
-  && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
+  && targetm.target_option.valid_attribute_p (*node,
+ get_identifier ("target"),
  current_target_pragma, 0))
 {
   tree cur_attr = lookup_attribute ("target", attributes);
@@ -1241,8 +1242,9 @@ make_dispatcher_decl (const tree decl)
   return func_decl;  
 }
 
-/* Returns true if decl is multi-versioned and DECL is the default function,
-   that is it is not tagged with target specific optimization.  */
+/* Returns true if DECL is multi-versioned using the target attribute, and this
+   is the default version.  This function can only be used for targets that do
+   not support the "target_version" attribute.  */
 
 bool
 is_function_default_version (const tree decl)
diff --git a/gcc/c-family/c-attribs.cc