From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id F228B3858D35 for ; Thu, 14 Dec 2023 14:58:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F228B3858D35 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F228B3858D35 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702565911; cv=none; b=rf0UkxvncxbXcjlVW3fAFSF5tCZhD6qi9nSvPdZToGRGYYpHC4Hvp7UAVLUUWP9Gzuu9ci1FCzns1s7qvdJ3wD64hgO/xA0GOo39LVWwo5k+Ayb6sO+6sSxyJ9It4DFs+BAq2uFVIvZ2bCmzehK6xhcBrWaL67cfjsfCj9udWZs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702565911; c=relaxed/simple; bh=MmC6VAZ1xIqeDxcap2Ilg7y7mqBxGuf2Sd04bLEiWEM=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=Qh2O2jgmhKsjlLTiy4UQnHav3wmAYaQHHEvrT54nXjF5dakZF1ml3QEHLZIQ1sRifuHJ0qelJXQHLXipiZTMpc/d0vtrwTJNWkboqNFTtDKWnRBRDeHP0y4lBlNfupPTV+x8Ub+A8fumjTStr3/J799FEn7RTYzanaMrCA5hLpk= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 02FDBC15; Thu, 14 Dec 2023 06:59:11 -0800 (PST) Received: from localhost (e121540-lin.manchester.arm.com [10.32.110.72]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C14973F5A1; Thu, 14 Dec 2023 06:58:24 -0800 (PST) From: Richard Sandiford To: Andrew Carlotti Mail-Followup-To: Andrew Carlotti ,gcc-patches@gcc.gnu.org, Richard Biener , richard.sandiford@arm.com Cc: gcc-patches@gcc.gnu.org, Richard Biener Subject: Re: [PATCH v3 4/5] Add support for target_version attribute References: <4cdd7089-edd4-96b9-5c0e-120d5357f01b@e124511.cambridge.arm.com> Date: Thu, 14 Dec 2023 14:58:23 +0000 In-Reply-To: (Andrew Carlotti's message of "Wed, 6 Dec 2023 12:46:29 +0000") Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Status: No, score=-21.6 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_NONE,KAM_DMARC_STATUS,KAM_LAZY_DOMAIN_SECURITY,KAM_LOTSOFHASH,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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. */ > +/* 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 b3b41ef123a0f171f57acb1b7f7fdde716428c00..eabc11c00f09125b7d6e2c47f3b083a03909825c 100644 > --- a/gcc/c-family/c-attribs.cc > +++ b/gcc/c-family/c-attribs.cc > @@ -149,6 +149,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 *); > @@ -230,14 +231,23 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] = > > static const struct attribute_spec::exclusions attr_target_exclusions[] = > { > - ATTR_EXCL ("target_clones", true, true, true), > + ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE, > + TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), > ATTR_EXCL (NULL, false, false, false), > }; > > static const struct attribute_spec::exclusions attr_target_clones_exclusions[] = > { > ATTR_EXCL ("always_inline", true, true, true), > - ATTR_EXCL ("target", true, true, true), > + ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, > + TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), > + ATTR_EXCL ("target_version", true, true, true), > + ATTR_EXCL (NULL, false, false, false), > +}; > + > +static const struct attribute_spec::exclusions attr_target_version_exclusions[] = > +{ > + ATTR_EXCL ("target_clones", true, true, true), > ATTR_EXCL (NULL, false, false, false), > }; > > @@ -505,6 +515,9 @@ const struct attribute_spec c_common_attribute_table[] = > { "target", 1, -1, true, false, false, false, > handle_target_attribute, > attr_target_exclusions }, > + { "target_version", 1, 1, true, false, false, false, > + handle_target_version_attribute, > + attr_target_version_exclusions }, > { "target_clones", 1, -1, true, false, false, false, > handle_target_clones_attribute, > attr_target_clones_exclusions }, > @@ -5670,6 +5683,25 @@ 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. */ Sorry for not noticing before, but: s/function type/function declaration/. Thanks, Richard > + if (TREE_CODE (*node) != FUNCTION_DECL) > + { > + warning (OPT_Wattributes, "%qE attribute ignored", name); > + *no_add_attrs = true; > + } > + else if (!targetm.target_option.valid_version_attribute_p (*node, name, args, > + flags)) > + *no_add_attrs = true; > + > + return NULL_TREE; > +} > + > /* Handle a "target_clones" attribute. */ > > static tree > diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc > index 29d28ef895a73a223695cbb86aafbc845bbe7688..3ba5a4a2dd9fd4b7206d95f01c990818d0440334 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_unreachable(); > + > input_location = saved_loc; > if (!r) > return NULL; > diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc > index 9e666e5eecee07ae7c742c3a2b27e85899945c4e..e607aa14d284d545d122e04b0eae1247fd301882 100644 > --- a/gcc/cp/decl2.cc > +++ b/gcc/cp/decl2.cc > @@ -832,8 +832,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/d/d-attribs.cc b/gcc/d/d-attribs.cc > index c0dc0e24ded871c136e54e5527e901d16cfa5ceb..13911c75948075a838914caca88802ac325f3107 100644 > --- a/gcc/d/d-attribs.cc > +++ b/gcc/d/d-attribs.cc > @@ -128,14 +128,16 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] = > > static const struct attribute_spec::exclusions attr_target_exclusions[] = > { > - ATTR_EXCL ("target_clones", true, true, true), > + ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE, > + TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), > ATTR_EXCL (NULL, false, false, false), > }; > > static const struct attribute_spec::exclusions attr_target_clones_exclusions[] = > { > ATTR_EXCL ("always_inline", true, true, true), > - ATTR_EXCL ("target", true, true, true), > + ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, > + TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), > ATTR_EXCL (NULL, false, false, false), > }; > > diff --git a/gcc/defaults.h b/gcc/defaults.h > index dc6f09cacae8a85873c6d6685eea91fb749cc367..6f0959694102ca28fd993aaff7ec3f5d09334c39 100644 > --- a/gcc/defaults.h > +++ b/gcc/defaults.h > @@ -877,6 +877,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see > #endif > #endif > > +/* Indicate whether the target uses "target" attributes for function > + multiversioning. This is used to choose between the "target" and > + "target_version" attributes when expanding a "target_clones" attribute, and > + determine whether the "target" and "target_clones" attributes are mutually > + exclusive. */ > +#ifndef TARGET_HAS_FMV_TARGET_ATTRIBUTE > +#define TARGET_HAS_FMV_TARGET_ATTRIBUTE 1 > +#endif > + > + > /* Select a format to encode pointers in exception handling data. We > prefer those that result in fewer dynamic relocations. Assume no > special support here and encode direct references. */ > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > index c0f949b538c04b3f409217e0508967dfca131604..1dc1b0523decff48f895703303a72fd93202bf7c 100644 > --- a/gcc/doc/tm.texi > +++ b/gcc/doc/tm.texi > @@ -10650,6 +10650,18 @@ 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 > + > @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 ef04c89d7b6fd27332f09ba844c11d4bbcf3bbe0..c452108ad54a7828762f17a864f700d1682a3964 100644 > --- a/gcc/doc/tm.texi.in > +++ b/gcc/doc/tm.texi.in > @@ -7031,6 +7031,8 @@ on this implementation detail. > > @hook TARGET_OPTION_VALID_ATTRIBUTE_P > > +@hook TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P > + > @hook TARGET_OPTION_SAVE > > @hook TARGET_OPTION_RESTORE > diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc > index a2ed048d7dd28ec470953fcd8a0dc86817e4b7dc..a832d1e8ff83d99acd7579c276b083141102f3e1 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,8 @@ expand_target_clones (struct cgraph_node *node, bool definition) > return false; > } > > + const char *new_attr_name = (TARGET_HAS_FMV_TARGET_ATTRIBUTE > + ? "target" : "target_version"); > cgraph_function_version_info *decl1_v = NULL; > cgraph_function_version_info *decl2_v = NULL; > cgraph_function_version_info *before = NULL; > @@ -392,7 +390,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 +428,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 eae7959cdccbfe669d234afe45c39545eae64234..ccdd3c56f5a9d74a14899ba60ac5c41de6bc192d 100644 > --- a/gcc/target.def > +++ b/gcc/target.def > @@ -6540,6 +6540,23 @@ 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) > + > /* 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 26695abe41e46d4d73402734c15892cfef6cf829..9e76326166c39a381ef3c9fbb9300d1523d9bb47 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 a2dc7331c24d100405434ec670678fcacadaee9b..aabba67787fbe91ae5f5dc50d7c2a29c410944a7 100644 > --- a/gcc/targhooks.cc > +++ b/gcc/targhooks.cc > @@ -1789,7 +1789,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"); > + "% 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, > + "% attribute is not supported on this machine"); > > return false; > } > diff --git a/gcc/tree.h b/gcc/tree.h > index 086b55f0375435d53a1604b6659da4f19fce3d17..d7841af19b20b0dc0ae28b433d5150e9c4763eff 100644 > --- a/gcc/tree.h > +++ b/gcc/tree.h > @@ -3500,8 +3500,8 @@ extern vec **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) >