Skip to content

Commit 79891c4

Browse files
committed
Add support for target_version attribute
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. 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. (handle_target_attribute): Amend comment. (handle_target_clones_attribute): Ditto. 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.
1 parent 73d5d3e commit 79891c4

14 files changed

Lines changed: 124 additions & 23 deletions

File tree

gcc/ada/gcc-interface/utils.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,16 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
146146

147147
static const struct attribute_spec::exclusions attr_target_exclusions[] =
148148
{
149-
{ "target_clones", true, true, true },
149+
{ "target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
150+
TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE },
150151
{ NULL, false, false, false },
151152
};
152153

153154
static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
154155
{
155156
{ "always_inline", true, true, true },
156-
{ "target", true, true, true },
157+
{ "target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE,
158+
TARGET_HAS_FMV_TARGET_ATTRIBUTE },
157159
{ NULL, false, false, false },
158160
};
159161

gcc/attribs.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,8 @@ decl_attributes (tree *node, tree attributes, int flags,
675675
options to the attribute((target(...))) list. */
676676
if (TREE_CODE (*node) == FUNCTION_DECL
677677
&& current_target_pragma
678-
&& targetm.target_option.valid_attribute_p (*node, NULL_TREE,
678+
&& targetm.target_option.valid_attribute_p (*node,
679+
get_identifier ("target"),
679680
current_target_pragma, 0))
680681
{
681682
tree cur_attr = lookup_attribute ("target", attributes);
@@ -1276,8 +1277,9 @@ make_dispatcher_decl (const tree decl)
12761277
return func_decl;
12771278
}
12781279

1279-
/* Returns true if decl is multi-versioned and DECL is the default function,
1280-
that is it is not tagged with target specific optimization. */
1280+
/* Returns true if DECL is multi-versioned using the target attribute, and this
1281+
is the default version. This function can only be used for targets that do
1282+
not support the "target_version" attribute. */
12811283

12821284
bool
12831285
is_function_default_version (const tree decl)

gcc/c-family/c-attribs.cc

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *);
151151
static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *);
152152
static tree handle_assume_attribute (tree *, tree, tree, int, bool *);
153153
static tree handle_target_attribute (tree *, tree, tree, int, bool *);
154+
static tree handle_target_version_attribute (tree *, tree, tree, int, bool *);
154155
static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
155156
static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
156157
static tree ignore_attribute (tree *, tree, tree, int, bool *);
@@ -233,14 +234,23 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
233234

234235
static const struct attribute_spec::exclusions attr_target_exclusions[] =
235236
{
236-
ATTR_EXCL ("target_clones", true, true, true),
237+
ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
238+
TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
237239
ATTR_EXCL (NULL, false, false, false),
238240
};
239241

240242
static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
241243
{
242244
ATTR_EXCL ("always_inline", true, true, true),
243-
ATTR_EXCL ("target", true, true, true),
245+
ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
246+
TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
247+
ATTR_EXCL ("target_version", true, true, true),
248+
ATTR_EXCL (NULL, false, false, false),
249+
};
250+
251+
static const struct attribute_spec::exclusions attr_target_version_exclusions[] =
252+
{
253+
ATTR_EXCL ("target_clones", true, true, true),
244254
ATTR_EXCL (NULL, false, false, false),
245255
};
246256

@@ -512,6 +522,9 @@ const struct attribute_spec c_common_gnu_attributes[] =
512522
{ "target", 1, -1, true, false, false, false,
513523
handle_target_attribute,
514524
attr_target_exclusions },
525+
{ "target_version", 1, 1, true, false, false, false,
526+
handle_target_version_attribute,
527+
attr_target_version_exclusions },
515528
{ "target_clones", 1, -1, true, false, false, false,
516529
handle_target_clones_attribute,
517530
attr_target_clones_exclusions },
@@ -5830,7 +5843,7 @@ static tree
58305843
handle_target_attribute (tree *node, tree name, tree args, int flags,
58315844
bool *no_add_attrs)
58325845
{
5833-
/* Ensure we have a function type. */
5846+
/* Ensure we have a function declaration. */
58345847
if (TREE_CODE (*node) != FUNCTION_DECL)
58355848
{
58365849
warning (OPT_Wattributes, "%qE attribute ignored", name);
@@ -5856,13 +5869,32 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
58565869
return NULL_TREE;
58575870
}
58585871

5872+
/* Handle a "target_version" attribute. */
5873+
5874+
static tree
5875+
handle_target_version_attribute (tree *node, tree name, tree args, int flags,
5876+
bool *no_add_attrs)
5877+
{
5878+
/* Ensure we have a function declaration. */
5879+
if (TREE_CODE (*node) != FUNCTION_DECL)
5880+
{
5881+
warning (OPT_Wattributes, "%qE attribute ignored", name);
5882+
*no_add_attrs = true;
5883+
}
5884+
else if (!targetm.target_option.valid_version_attribute_p (*node, name, args,
5885+
flags))
5886+
*no_add_attrs = true;
5887+
5888+
return NULL_TREE;
5889+
}
5890+
58595891
/* Handle a "target_clones" attribute. */
58605892

58615893
static tree
58625894
handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
58635895
int ARG_UNUSED (flags), bool *no_add_attrs)
58645896
{
5865-
/* Ensure we have a function type. */
5897+
/* Ensure we have a function declaration. */
58665898
if (TREE_CODE (*node) == FUNCTION_DECL)
58675899
{
58685900
for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))

gcc/cgraphclones.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. If not see
7878
#include "tree-eh.h"
7979
#include "tree-cfg.h"
8080
#include "tree-inline.h"
81+
#include "attribs.h"
8182
#include "dumpfile.h"
8283
#include "gimple-pretty-print.h"
8384
#include "alloc-pool.h"
@@ -1048,7 +1049,17 @@ cgraph_node::create_version_clone_with_body
10481049
location_t saved_loc = input_location;
10491050
tree v = TREE_VALUE (target_attributes);
10501051
input_location = DECL_SOURCE_LOCATION (new_decl);
1051-
bool r = targetm.target_option.valid_attribute_p (new_decl, NULL, v, 1);
1052+
bool r;
1053+
tree name_id = get_attribute_name (target_attributes);
1054+
const char *name_str = IDENTIFIER_POINTER (name_id);
1055+
if (strcmp (name_str, "target") == 0)
1056+
r = targetm.target_option.valid_attribute_p (new_decl, name_id, v, 1);
1057+
else if (strcmp (name_str, "target_version") == 0)
1058+
r = targetm.target_option.valid_version_attribute_p (new_decl, name_id,
1059+
v, 1);
1060+
else
1061+
gcc_unreachable();
1062+
10521063
input_location = saved_loc;
10531064
if (!r)
10541065
return NULL;

gcc/cp/decl2.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -834,8 +834,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
834834
tree c2 = get_constraints (fndecl);
835835

836836
/* While finding a match, same types and params are not enough
837-
if the function is versioned. Also check version ("target")
838-
attributes. */
837+
if the function is versioned. Also check for different target
838+
specific attributes. */
839839
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
840840
TREE_TYPE (TREE_TYPE (fndecl)))
841841
&& compparms (p1, p2)

gcc/d/d-attribs.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,16 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
128128

129129
static const struct attribute_spec::exclusions attr_target_exclusions[] =
130130
{
131-
ATTR_EXCL ("target_clones", true, true, true),
131+
ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
132+
TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
132133
ATTR_EXCL (NULL, false, false, false),
133134
};
134135

135136
static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
136137
{
137138
ATTR_EXCL ("always_inline", true, true, true),
138-
ATTR_EXCL ("target", true, true, true),
139+
ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
140+
TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
139141
ATTR_EXCL (NULL, false, false, false),
140142
};
141143

gcc/defaults.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
877877
#endif
878878
#endif
879879

880+
/* Indicate whether the target uses "target" attributes for function
881+
multiversioning. This is used to choose between the "target" and
882+
"target_version" attributes when expanding a "target_clones" attribute, and
883+
determine whether the "target" and "target_clones" attributes are mutually
884+
exclusive. */
885+
#ifndef TARGET_HAS_FMV_TARGET_ATTRIBUTE
886+
#define TARGET_HAS_FMV_TARGET_ATTRIBUTE 1
887+
#endif
888+
889+
880890
/* Select a format to encode pointers in exception handling data. We
881891
prefer those that result in fewer dynamic relocations. Assume no
882892
special support here and encode direct references. */

gcc/doc/tm.texi

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10741,6 +10741,18 @@ the function declaration to hold a pointer to a target-specific
1074110741
@code{struct cl_target_option} structure.
1074210742
@end deftypefn
1074310743

10744+
@deftypefn {Target Hook} bool TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P (tree @var{fndecl}, tree @var{name}, tree @var{args}, int @var{flags})
10745+
This hook is called to parse @code{attribute(target_version("..."))},
10746+
which allows setting target-specific options on individual function versions.
10747+
These function-specific options may differ
10748+
from the options specified on the command line. The hook should return
10749+
@code{true} if the options are valid.
10750+
10751+
The hook should set the @code{DECL_FUNCTION_SPECIFIC_TARGET} field in
10752+
the function declaration to hold a pointer to a target-specific
10753+
@code{struct cl_target_option} structure.
10754+
@end deftypefn
10755+
1074410756
@deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set})
1074510757
This hook is called to save any additional target-specific information
1074610758
in the @code{struct cl_target_option} structure for function-specific

gcc/doc/tm.texi.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7066,6 +7066,8 @@ on this implementation detail.
70667066

70677067
@hook TARGET_OPTION_VALID_ATTRIBUTE_P
70687068

7069+
@hook TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P
7070+
70697071
@hook TARGET_OPTION_SAVE
70707072

70717073
@hook TARGET_OPTION_RESTORE

gcc/multiple_target.cc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ create_dispatcher_calls (struct cgraph_node *node)
6666
{
6767
ipa_ref *ref;
6868

69-
if (!DECL_FUNCTION_VERSIONED (node->decl)
70-
|| !is_function_default_version (node->decl))
71-
return;
72-
7369
if (!targetm.has_ifunc_p ())
7470
{
7571
error_at (DECL_SOURCE_LOCATION (node->decl),
@@ -377,6 +373,8 @@ expand_target_clones (struct cgraph_node *node, bool definition)
377373
return false;
378374
}
379375

376+
const char *new_attr_name = (TARGET_HAS_FMV_TARGET_ATTRIBUTE
377+
? "target" : "target_version");
380378
cgraph_function_version_info *decl1_v = NULL;
381379
cgraph_function_version_info *decl2_v = NULL;
382380
cgraph_function_version_info *before = NULL;
@@ -392,7 +390,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
392390
char *attr = attrs[i];
393391

394392
/* Create new target clone. */
395-
tree attributes = make_attribute ("target", attr,
393+
tree attributes = make_attribute (new_attr_name, attr,
396394
DECL_ATTRIBUTES (node->decl));
397395

398396
char *suffix = XNEWVEC (char, strlen (attr) + 1);
@@ -430,7 +428,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
430428
XDELETEVEC (attr_str);
431429

432430
/* Setting new attribute to initial function. */
433-
tree attributes = make_attribute ("target", "default",
431+
tree attributes = make_attribute (new_attr_name, "default",
434432
DECL_ATTRIBUTES (node->decl));
435433
DECL_ATTRIBUTES (node->decl) = attributes;
436434
node->local = false;

0 commit comments

Comments
 (0)