@@ -6132,12 +6132,28 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
}
}
- auto_vec<string_slice> versions= get_clone_attr_versions (args, NULL);
-
- if (versions.length () == 1)
- {
+ int num_defaults = 0;
+ auto_vec<string_slice> versions= get_clone_attr_versions (args,
+ &num_defaults,
+ DECL_SOURCE_LOCATION (*node),
+ false);
+
+ for (auto v : versions)
+ if (targetm.reject_function_clone_version
+ (v, DECL_SOURCE_LOCATION (*node)))
warning (OPT_Wattributes,
- "single %<target_clones%> attribute is ignored");
+ "invalid %<target_clones%> version %qB ignored",
+ &v);
+
+ /* Lone target_clones version is always ignored for target attr semantics.
+ Only ignore under target_version semantics if it is a default
+ version. */
+ if (versions.length () == 1 && (TARGET_HAS_FMV_TARGET_ATTRIBUTE
+ || num_defaults == 1))
+ {
+ if (TARGET_HAS_FMV_TARGET_ATTRIBUTE)
+ warning (OPT_Wattributes,
+ "single %<target_clones%> attribute is ignored");
*no_add_attrs = true;
}
else
@@ -31229,6 +31229,23 @@ aarch64_expand_reversed_crc_using_pmull (scalar_mode crc_mode,
}
}
+bool
+aarch64_reject_target_clone_version (string_slice str,
+ location_t loc ATTRIBUTE_UNUSED)
+{
+ str = str.strip ();
+
+ if (str == "default")
+ return false;
+
+ enum aarch_parse_opt_result parse_res;
+ auto isa_flags = aarch64_asm_isa_flags;
+ parse_res = aarch64_parse_fmv_features (str, &isa_flags, NULL, NULL);
+
+ /* Reject any version which does not parse. */
+ return parse_res != AARCH_PARSE_OK;
+}
+
/* Target-specific selftests. */
#if CHECKING_P
@@ -32052,6 +32069,9 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_OPTION_FUNCTION_VERSIONS
#define TARGET_OPTION_FUNCTION_VERSIONS aarch64_common_function_versions
+#undef TARGET_REJECT_FUNCTION_CLONE_VERSION
+#define TARGET_REJECT_FUNCTION_CLONE_VERSION aarch64_reject_target_clone_version
+
#undef TARGET_COMPARE_VERSION_PRIORITY
#define TARGET_COMPARE_VERSION_PRIORITY aarch64_compare_version_priority
@@ -13211,6 +13211,21 @@ riscv_common_function_versions (tree fn1, tree fn2)
return riscv_compare_version_priority (fn1, fn2) != 0;
}
+bool
+riscv_reject_target_clone_version (string_slice str, location_t loc)
+{
+ struct riscv_feature_bits mask;
+ int prio;
+
+ /* Currently it is not possible to parse without emitting errors on failure
+ so do not reject on a failed parse, as this would then emit two
+ diagnostics. Instead let errors be emitted which will halt
+ compilation. */
+ parse_features_for_version (str, loc, mask, prio);
+
+ return false;
+}
+
/* Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME, to add function multiversioning
suffixes. */
@@ -14349,6 +14364,9 @@ bool need_shadow_stack_push_pop_p ()
#undef TARGET_COMPARE_VERSION_PRIORITY
#define TARGET_COMPARE_VERSION_PRIORITY riscv_compare_version_priority
+#undef TARGET_REJECT_FUNCTION_CLONE_VERSION
+#define TARGET_REJECT_FUNCTION_CLONE_VERSION riscv_reject_target_clone_version
+
#undef TARGET_OPTION_FUNCTION_VERSIONS
#define TARGET_OPTION_FUNCTION_VERSIONS riscv_common_function_versions
@@ -12272,6 +12272,11 @@ function version at run-time for a given set of function versions.
body must be generated.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_REJECT_FUNCTION_CLONE_VERSION (string_slice @var{str}, location_t @var{loc})
+This hook is used to ignore versions specified in a target_clones
+annotation. @var{str} is the version to be considered.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_PREDICT_DOLOOP_P (class loop *@var{loop})
Return true if we can predict it is possible to use a low-overhead loop
for a particular loop. The parameter @var{loop} is a pointer to the loop.
@@ -7885,6 +7885,8 @@ to by @var{ce_info}.
@hook TARGET_GENERATE_VERSION_DISPATCHER_BODY
+@hook TARGET_REJECT_FUNCTION_CLONE_VERSION
+
@hook TARGET_PREDICT_DOLOOP_P
@hook TARGET_HAVE_COUNT_REG_DECR_P
@@ -578,3 +578,9 @@ hook_optmode_mode_uhwi_none (machine_mode, unsigned HOST_WIDE_INT)
{
return opt_machine_mode ();
}
+
+bool
+hook_stringslice_locationt_false (string_slice, location_t)
+{
+ return false;
+}
@@ -136,4 +136,7 @@ extern const char *hook_constcharptr_int_const_tree_const_tree_null (int, const_
extern opt_machine_mode hook_optmode_mode_uhwi_none (machine_mode,
unsigned HOST_WIDE_INT);
+
+extern bool hook_stringslice_locationt_false (string_slice, location_t);
+
#endif
@@ -2588,6 +2588,14 @@ version at run-time. @var{decl} is one version from a set of semantically\n\
identical versions.",
tree, (void *decl), NULL)
+/* Target hook is used to ignore certain versions specified in a target_clones
+ annoration. STR is the version to be considered. */
+DEFHOOK
+(reject_function_clone_version ,
+ "This hook is used to ignore versions specified in a target_clones\n\
+annotation. @var{str} is the version to be considered.",
+ bool, (string_slice str, location_t loc), hook_stringslice_locationt_false)
+
/* Returns a code for a target-specific builtin that implements
reciprocal of a target-specific function, or NULL_TREE if not available. */
DEFHOOK
@@ -15350,7 +15350,10 @@ get_attr_nonstring_decl (tree expr, tree *ref)
ARGLIST. DEFAULT_COUNT is incremented for each default version found. */
auto_vec<string_slice>
-get_clone_attr_versions (const tree arglist, int *default_count)
+get_clone_attr_versions (const tree arglist,
+ int *default_count,
+ location_t loc,
+ bool filter)
{
gcc_assert (TREE_CODE (arglist) == TREE_LIST);
auto_vec<string_slice> versions;
@@ -15366,6 +15369,9 @@ get_clone_attr_versions (const tree arglist, int *default_count)
string_slice attr = string_slice::tokenize (&str, separators);
attr = attr.strip ();
+ if (filter && targetm.reject_function_clone_version (attr, loc))
+ continue;
+
if (attr == "default" && default_count)
(*default_count)++;
versions.safe_push (attr);
@@ -15384,7 +15390,9 @@ get_clone_versions (const tree decl, int *default_count)
if (!attr)
return auto_vec<string_slice> ();
tree arglist = TREE_VALUE (attr);
- return get_clone_attr_versions (arglist, default_count);
+ return get_clone_attr_versions (arglist,
+ default_count,
+ DECL_SOURCE_LOCATION (decl));
}
/* If DECL has a target_version attribute, returns a string_slice containing the
@@ -7058,7 +7058,11 @@ extern string_slice get_target_version (const tree);
a decl. Can also record the number of default versions found. */
extern auto_vec<string_slice> get_clone_versions (const tree, int * = NULL);
/* Returns a vector of the version strings from a target_clones attribute
- directly. */
-extern auto_vec<string_slice> get_clone_attr_versions (const tree, int *);
+ directly. Additionally takes a location for potential diagnostics to be
+ emmitted for and a bool to control whether or not the results should
+ be filtered with TARGET_REJECT_FUNCTION_CLONE_VERSION. */
+extern auto_vec<string_slice> get_clone_attr_versions (const tree, int *,
+ location_t loc,
+ bool = true);
#endif /* GCC_TREE_H */