From: Andrew Carlotti <andrew.carlotti@arm.com>
To: gcc-patches@gcc.gnu.org
Cc: jason@redhat.com, nathan@acm.org, rguenther@suse.de,
richard.sandiford@arm.com
Subject: [1/3] Add support for target_version attribute
Date: Wed, 18 Oct 2023 16:42:36 +0100 [thread overview]
Message-ID: <2a9e5b6e-9720-602b-5449-28fb5d88a40c@e124511.cambridge.arm.com> (raw)
In-Reply-To: <26bbc7e4-9d5a-fef3-2f78-1b7a03865050@e124511.cambridge.arm.com>
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.
Note that C++ is currently the only frontend which supports
multiversioning using the "target" attribute, whereas the
"target_clones" attribute is additionally supported in C, D and Ada.
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.
I could have implemented the target hooks slightly differently, by reusing the
valid_attribute_p hook and adding attribute name checks to each backend
implementation (c.f. the aarch64 implementation in patch 2/3). Would this be
preferable?
Otherwise, is this ok for master?
gcc/c-family/ChangeLog:
* c-attribs.cc (handle_target_version_attribute): New.
(c_common_attribute_table): Add target_version.
(handle_target_clones_attribute): Add conflict with
target_version attribute.
gcc/ChangeLog:
* attribs.cc (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.
* target.def (valid_version_attribute_p): New hook.
(expanded_clones_attribute): New hook.
* doc/tm.texi.in: Add new hooks.
* doc/tm.texi: Regenerate.
* multiple_target.cc (create_dispatcher_calls): Remove redundant
is_function_default_version check.
(expand_target_clones): Use target hook for 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/cp/ChangeLog:
* decl2.cc (check_classfn): Update comment to include
target_version attributes.
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index b1300018d1e8ed8e02ded1ea721dc192a6d32a49..a3c4a81e8582ea4fd06b9518bf51fad7c998ddd6 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -1233,8 +1233,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 b/gcc/c-family/c-attribs.cc
index 072cfb69147bd6b314459c0bd48a0c1fb92d3e4d..1a224c036277d51ab4dc0d33a403177bd226e48a 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -148,6 +148,7 @@ static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *);
static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *);
static tree handle_assume_attribute (tree *, tree, tree, int, bool *);
static tree handle_target_attribute (tree *, tree, tree, int, bool *);
+static tree handle_target_version_attribute (tree *, tree, tree, int, bool *);
static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
static tree ignore_attribute (tree *, tree, tree, int, bool *);
@@ -480,6 +481,8 @@ const struct attribute_spec c_common_attribute_table[] =
handle_error_attribute, NULL },
{ "target", 1, -1, true, false, false, false,
handle_target_attribute, NULL },
+ { "target_version", 1, -1, true, false, false, false,
+ handle_target_version_attribute, NULL },
{ "target_clones", 1, -1, true, false, false, false,
handle_target_clones_attribute, NULL },
{ "optimize", 1, -1, true, false, false, false,
@@ -5569,6 +5572,45 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
return NULL_TREE;
}
+/* Handle a "target_version" attribute. */
+
+static tree
+handle_target_version_attribute (tree *node, tree name, tree args, int flags,
+ bool *no_add_attrs)
+{
+ /* Ensure we have a function type. */
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+ else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with %qs attribute", name, "target_clones");
+ *no_add_attrs = true;
+ }
+ else if (!targetm.target_option.valid_version_attribute_p (*node, name, args,
+ flags))
+ *no_add_attrs = true;
+
+ /* Check that there's no empty string in values of the attribute. */
+ for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
+ {
+ tree value = TREE_VALUE (t);
+ if (TREE_CODE (value) == STRING_CST
+ && TREE_STRING_LENGTH (value) == 1
+ && TREE_STRING_POINTER (value)[0] == '\0')
+ {
+ warning (OPT_Wattributes,
+ "empty string in attribute %<target_version%>");
+ *no_add_attrs = true;
+ }
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "target_clones" attribute. */
static tree
@@ -5601,6 +5643,12 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
"with %qs attribute", name, "target");
*no_add_attrs = true;
}
+ else if (lookup_attribute ("target_version", DECL_ATTRIBUTES (*node)))
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored due to conflict "
+ "with %qs attribute", name, "target_version");
+ *no_add_attrs = true;
+ }
else if (get_target_clone_attr_len (args) == -1)
{
warning (OPT_Wattributes,
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 29d28ef895a73a223695cbb86aafbc845bbe7688..8af6b23d8c0306920e0fdcb3559ef047a16689f4 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "tree-cfg.h"
#include "tree-inline.h"
+#include "attribs.h"
#include "dumpfile.h"
#include "gimple-pretty-print.h"
#include "alloc-pool.h"
@@ -1048,7 +1049,17 @@ cgraph_node::create_version_clone_with_body
location_t saved_loc = input_location;
tree v = TREE_VALUE (target_attributes);
input_location = DECL_SOURCE_LOCATION (new_decl);
- bool r = targetm.target_option.valid_attribute_p (new_decl, NULL, v, 1);
+ bool r;
+ tree name_id = get_attribute_name (target_attributes);
+ const char* name_str = IDENTIFIER_POINTER (name_id);
+ if (strcmp (name_str, "target") == 0)
+ r = targetm.target_option.valid_attribute_p (new_decl, name_id, v, 1);
+ else if (strcmp (name_str, "target_version") == 0)
+ r = targetm.target_option.valid_version_attribute_p (new_decl, name_id,
+ v, 1);
+ else
+ gcc_assert(false);
+
input_location = saved_loc;
if (!r)
return NULL;
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 9594be4092c3c00fddc9d4c6da5931ea3b7e8792..ec78d5a5440bedd360ac8e5bc44e164da3dab410 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -829,8 +829,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
tree c2 = get_constraints (fndecl);
/* While finding a match, same types and params are not enough
- if the function is versioned. Also check version ("target")
- attributes. */
+ if the function is versioned. Also check for different target
+ specific attributes. */
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)))
&& compparms (p1, p2)
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 33e7ffc8af5a9d48430145ef9b8e7924613b7dd7..97b3e9c31631a943d95f1cf7739716a574afcfb7 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -10507,6 +10507,23 @@ the function declaration to hold a pointer to a target-specific
@code{struct cl_target_option} structure.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P (tree @var{fndecl}, tree @var{name}, tree @var{args}, int @var{flags})
+This hook is called to parse @code{attribute(target_version("..."))},
+which allows setting target-specific options on individual function versions.
+These function-specific options may differ
+from the options specified on the command line. The hook should return
+@code{true} if the options are valid.
+
+The hook should set the @code{DECL_FUNCTION_SPECIFIC_TARGET} field in
+the function declaration to hold a pointer to a target-specific
+@code{struct cl_target_option} structure.
+@end deftypefn
+
+@deftypevr {Target Hook} {const char *} TARGET_OPTION_EXPANDED_CLONES_ATTRIBUTE
+Contains the name of the attribute used for the version description string
+when expanding clones for a function with the target_clones attribute.
+@end deftypevr
+
@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set})
This hook is called to save any additional target-specific information
in the @code{struct cl_target_option} structure for function-specific
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index c98b2447e28aa17996b1cbf8af7ed02d70db54f2..56fa3de6bba06bc0ac124bb3a41324be1997e209 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -6979,6 +6979,10 @@ on this implementation detail.
@hook TARGET_OPTION_VALID_ATTRIBUTE_P
+@hook TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P
+
+@hook TARGET_OPTION_EXPANDED_CLONES_ATTRIBUTE
+
@hook TARGET_OPTION_SAVE
@hook TARGET_OPTION_RESTORE
diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc
index a2ed048d7dd28ec470953fcd8a0dc86817e4b7dc..3db57c2b13d612a37240d9dcf58ad21b2286633c 100644
--- a/gcc/multiple_target.cc
+++ b/gcc/multiple_target.cc
@@ -66,10 +66,6 @@ create_dispatcher_calls (struct cgraph_node *node)
{
ipa_ref *ref;
- if (!DECL_FUNCTION_VERSIONED (node->decl)
- || !is_function_default_version (node->decl))
- return;
-
if (!targetm.has_ifunc_p ())
{
error_at (DECL_SOURCE_LOCATION (node->decl),
@@ -377,6 +373,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
return false;
}
+ const char *new_attr_name = targetm.target_option.expanded_clones_attribute;
cgraph_function_version_info *decl1_v = NULL;
cgraph_function_version_info *decl2_v = NULL;
cgraph_function_version_info *before = NULL;
@@ -392,7 +389,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
char *attr = attrs[i];
/* Create new target clone. */
- tree attributes = make_attribute ("target", attr,
+ tree attributes = make_attribute (new_attr_name, attr,
DECL_ATTRIBUTES (node->decl));
char *suffix = XNEWVEC (char, strlen (attr) + 1);
@@ -430,7 +427,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
XDELETEVEC (attr_str);
/* Setting new attribute to initial function. */
- tree attributes = make_attribute ("target", "default",
+ tree attributes = make_attribute (new_attr_name, "default",
DECL_ATTRIBUTES (node->decl));
DECL_ATTRIBUTES (node->decl) = attributes;
node->local = false;
diff --git a/gcc/target.def b/gcc/target.def
index cda6c51e5167f85625168c7c26b777d6c8ccad82..39acea04db01ebaf918910b7dd73d397de6a84ec 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -6492,6 +6492,31 @@ the function declaration to hold a pointer to a target-specific\n\
bool, (tree fndecl, tree name, tree args, int flags),
default_target_option_valid_attribute_p)
+/* Function to validate the attribute((target_version(...))) strings. If
+ the option is validated, the hook should also fill in
+ DECL_FUNCTION_SPECIFIC_TARGET in the function decl node. */
+DEFHOOK
+(valid_version_attribute_p,
+ "This hook is called to parse @code{attribute(target_version(\"...\"))},\n\
+which allows setting target-specific options on individual function versions.\n\
+These function-specific options may differ\n\
+from the options specified on the command line. The hook should return\n\
+@code{true} if the options are valid.\n\
+\n\
+The hook should set the @code{DECL_FUNCTION_SPECIFIC_TARGET} field in\n\
+the function declaration to hold a pointer to a target-specific\n\
+@code{struct cl_target_option} structure.",
+ bool, (tree fndecl, tree name, tree args, int flags),
+ default_target_option_valid_version_attribute_p)
+
+/* Attribute to be used when expanding clones for functions with
+ target_clones attribute. */
+DEFHOOKPOD
+(expanded_clones_attribute,
+ "Contains the name of the attribute used for the version description string\n\
+when expanding clones for a function with the target_clones attribute.",
+ const char *, "target")
+
/* Function to save any extra target state in the target options structure. */
DEFHOOK
(save,
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 1a0db8dddd594d9b1fb04ae0d9a66ad6b7a396dc..0efc993d82ef59b581a1df74ee0de71135a28703 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -192,6 +192,7 @@ extern bool default_hard_regno_scratch_ok (unsigned int);
extern bool default_mode_dependent_address_p (const_rtx, addr_space_t);
extern bool default_new_address_profitable_p (rtx, rtx_insn *, rtx);
extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
+extern bool default_target_option_valid_version_attribute_p (tree, tree, tree, int);
extern bool default_target_option_pragma_parse (tree, tree);
extern bool default_target_can_inline_p (tree, tree);
extern bool default_update_ipa_fn_target_info (unsigned int &, const gimple *);
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index e190369f87a92e6a92372dc348d9374c3a965c0a..7fc7bf455e80c333cced1bac7085210c2b108f8d 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -1787,7 +1787,19 @@ default_target_option_valid_attribute_p (tree ARG_UNUSED (fndecl),
int ARG_UNUSED (flags))
{
warning (OPT_Wattributes,
- "target attribute is not supported on this machine");
+ "%<target%> attribute is not supported on this machine");
+
+ return false;
+}
+
+bool
+default_target_option_valid_version_attribute_p (tree ARG_UNUSED (fndecl),
+ tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags))
+{
+ warning (OPT_Wattributes,
+ "%<target_version%> attribute is not supported on this machine");
return false;
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 0b72663e6a1a94406127f6253460f498b7a3ea9c..ebd89ce79566c350eaaab210c0dca3cc1ac2048e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3438,8 +3438,8 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
(FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_optimization)
/* In FUNCTION_DECL, this is set if this function has other versions generated
- using "target" attributes. The default version is the one which does not
- have any "target" attribute set. */
+ to support different architecture feature sets, e.g. using "target" or
+ "target_version" attributes. */
#define DECL_FUNCTION_VERSIONED(NODE)\
(FUNCTION_DECL_CHECK (NODE)->function_decl.versioned_function)
next prev parent reply other threads:[~2023-10-18 15:42 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-18 15:39 [0/3] target_version and aarch64 function multiversioning Andrew Carlotti
2023-10-18 15:42 ` Andrew Carlotti [this message]
2023-10-19 7:04 ` [1/3] Add support for target_version attribute Richard Biener
2023-10-19 16:13 ` Andrew Carlotti
2023-10-26 18:41 ` Richard Sandiford
2023-11-03 12:43 ` Andrew Carlotti
2023-11-05 20:18 ` Richard Sandiford
2023-10-18 15:44 ` [2/3] [aarch64] Add function multiversioning support Andrew Carlotti
2023-10-30 22:35 ` Richard Sandiford
2023-10-18 15:44 ` [3/3] WIP/RFC: Fix name mangling for target_clones Andrew Carlotti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2a9e5b6e-9720-602b-5449-28fb5d88a40c@e124511.cambridge.arm.com \
--to=andrew.carlotti@arm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=jason@redhat.com \
--cc=nathan@acm.org \
--cc=rguenther@suse.de \
--cc=richard.sandiford@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).