1289 lines
34 KiB
Diff
1289 lines
34 KiB
Diff
|
2013-01-21 Jakub Jelinek <jakub@redhat.com>
|
||
|
|
||
|
PR c++/55742
|
||
|
* config/i386/i386.c (ix86_valid_target_attribute_inner_p): Diagnose
|
||
|
invalid args instead of ICEing on it.
|
||
|
(ix86_valid_target_attribute_tree): Return error_mark_node if
|
||
|
ix86_valid_target_attribute_inner_p failed.
|
||
|
(ix86_valid_target_attribute_p): Return false only if
|
||
|
ix86_valid_target_attribute_tree returned error_mark_node. Allow
|
||
|
target("default") attribute.
|
||
|
(sorted_attr_string): Change argument from const char * to tree,
|
||
|
merge in all target attribute arguments rather than just one.
|
||
|
Formatting fix. Use XNEWVEC instead of xmalloc and XDELETEVEC
|
||
|
instead of free. Avoid using strcat.
|
||
|
(ix86_mangle_function_version_assembler_name): Mangle
|
||
|
target("default") as if no target attribute is present. Adjust
|
||
|
sorted_attr_string caller. Avoid leaking memory. Use XNEWVEC
|
||
|
instead of xmalloc and XDELETEVEC instead of free.
|
||
|
(ix86_function_versions): Don't return true if one of the decls
|
||
|
doesn't have target attribute. If they don't and one of the decls
|
||
|
is DECL_FUNCTION_VERSIONED, report an error. Adjust
|
||
|
sorted_attr_string caller. Use XDELETEVEC instead of free.
|
||
|
(ix86_supports_function_versions): Remove.
|
||
|
(make_name): Fix up formatting.
|
||
|
(make_dispatcher_decl): Remove resolver_name and its initialization.
|
||
|
Avoid leaking memory.
|
||
|
(is_function_default_version): Return true if there is
|
||
|
target("default") attribute rather than no target attribute at all.
|
||
|
(make_resolver_func): Avoid leaking memory.
|
||
|
(ix86_generate_version_dispatcher_body): Likewise.
|
||
|
(TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS): Remove.
|
||
|
* target.def (supports_function_versions): Remove.
|
||
|
* doc/tm.texi.in (SUPPORTS_FUNCTION_VERSIONS): Remove.
|
||
|
* doc/tm.texi: Regenerated.
|
||
|
|
||
|
* c-common.c (handle_target_attribute): Revert 2012-12-26 change.
|
||
|
|
||
|
* g++.dg/mv1.C: Moved to...
|
||
|
* g++.dg/ext/mv1.C: ... here. Adjust test.
|
||
|
* g++.dg/mv2.C: Moved to...
|
||
|
* g++.dg/ext/mv2.C: ... here. Adjust test.
|
||
|
* g++.dg/mv3.C: Moved to...
|
||
|
* g++.dg/ext/mv3.C: ... here.
|
||
|
* g++.dg/mv4.C: Moved to...
|
||
|
* g++.dg/ext/mv4.C: ... here.
|
||
|
* g++.dg/mv5.C: Moved to...
|
||
|
* g++.dg/ext/mv5.C: ... here. Adjust test.
|
||
|
* g++.dg/mv6.C: Moved to...
|
||
|
* g++.dg/ext/mv6.C: ... here. Adjust test.
|
||
|
* g++.dg/ext/mv7.C: New test.
|
||
|
* g++.dg/ext/mv8.C: New test.
|
||
|
* g++.dg/ext/mv9.C: New test.
|
||
|
* g++.dg/ext/mv10.C: New test.
|
||
|
* g++.dg/ext/mv11.C: New test.
|
||
|
|
||
|
--- gcc/config/i386/i386.c.jj 2013-01-21 10:57:08.325945469 +0100
|
||
|
+++ gcc/config/i386/i386.c 2013-01-21 12:02:59.384701394 +0100
|
||
|
@@ -4223,7 +4223,10 @@ ix86_valid_target_attribute_inner_p (tre
|
||
|
}
|
||
|
|
||
|
else if (TREE_CODE (args) != STRING_CST)
|
||
|
- gcc_unreachable ();
|
||
|
+ {
|
||
|
+ error ("attribute %<target%> argument not a string");
|
||
|
+ return false;
|
||
|
+ }
|
||
|
|
||
|
/* Handle multiple arguments separated by commas. */
|
||
|
next_optstr = ASTRDUP (TREE_STRING_POINTER (args));
|
||
|
@@ -4368,7 +4371,7 @@ ix86_valid_target_attribute_tree (tree a
|
||
|
/* Process each of the options on the chain. */
|
||
|
if (! ix86_valid_target_attribute_inner_p (args, option_strings,
|
||
|
&enum_opts_set))
|
||
|
- return NULL_TREE;
|
||
|
+ return error_mark_node;
|
||
|
|
||
|
/* If the changed options are different from the default, rerun
|
||
|
ix86_option_override_internal, and then save the options away.
|
||
|
@@ -4433,6 +4436,15 @@ ix86_valid_target_attribute_p (tree fnde
|
||
|
{
|
||
|
struct cl_target_option cur_target;
|
||
|
bool ret = true;
|
||
|
+
|
||
|
+ /* attribute((target("default"))) does nothing, beyond
|
||
|
+ affecting multi-versioning. */
|
||
|
+ if (TREE_VALUE (args)
|
||
|
+ && TREE_CODE (TREE_VALUE (args)) == STRING_CST
|
||
|
+ && TREE_CHAIN (args) == NULL_TREE
|
||
|
+ && strcmp (TREE_STRING_POINTER (TREE_VALUE (args)), "default") == 0)
|
||
|
+ return true;
|
||
|
+
|
||
|
tree old_optimize = build_optimization_node ();
|
||
|
tree new_target, new_optimize;
|
||
|
tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
|
||
|
@@ -4449,10 +4461,10 @@ ix86_valid_target_attribute_p (tree fnde
|
||
|
new_target = ix86_valid_target_attribute_tree (args);
|
||
|
new_optimize = build_optimization_node ();
|
||
|
|
||
|
- if (!new_target)
|
||
|
+ if (new_target == error_mark_node)
|
||
|
ret = false;
|
||
|
|
||
|
- else if (fndecl)
|
||
|
+ else if (fndecl && new_target)
|
||
|
{
|
||
|
DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
|
||
|
|
||
|
@@ -28946,26 +28958,44 @@ attr_strcmp (const void *v1, const void
|
||
|
return strcmp (c1, c2);
|
||
|
}
|
||
|
|
||
|
-/* STR is the argument to target attribute. This function tokenizes
|
||
|
+/* ARGLIST is the argument to target attribute. This function tokenizes
|
||
|
the comma separated arguments, sorts them and returns a string which
|
||
|
is a unique identifier for the comma separated arguments. It also
|
||
|
replaces non-identifier characters "=,-" with "_". */
|
||
|
|
||
|
static char *
|
||
|
-sorted_attr_string (const char *str)
|
||
|
+sorted_attr_string (tree arglist)
|
||
|
{
|
||
|
+ tree arg;
|
||
|
+ size_t str_len_sum = 0;
|
||
|
char **args = NULL;
|
||
|
char *attr_str, *ret_str;
|
||
|
char *attr = NULL;
|
||
|
unsigned int argnum = 1;
|
||
|
unsigned int i;
|
||
|
|
||
|
- for (i = 0; i < strlen (str); i++)
|
||
|
- if (str[i] == ',')
|
||
|
- argnum++;
|
||
|
-
|
||
|
- attr_str = (char *)xmalloc (strlen (str) + 1);
|
||
|
- strcpy (attr_str, str);
|
||
|
+ for (arg = arglist; arg; arg = TREE_CHAIN (arg))
|
||
|
+ {
|
||
|
+ const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
|
||
|
+ size_t len = strlen (str);
|
||
|
+ str_len_sum += len + 1;
|
||
|
+ if (arg != arglist)
|
||
|
+ argnum++;
|
||
|
+ for (i = 0; i < strlen (str); i++)
|
||
|
+ if (str[i] == ',')
|
||
|
+ argnum++;
|
||
|
+ }
|
||
|
+
|
||
|
+ attr_str = XNEWVEC (char, str_len_sum);
|
||
|
+ str_len_sum = 0;
|
||
|
+ for (arg = arglist; arg; arg = TREE_CHAIN (arg))
|
||
|
+ {
|
||
|
+ const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
|
||
|
+ size_t len = strlen (str);
|
||
|
+ memcpy (attr_str + str_len_sum, str, len);
|
||
|
+ attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
|
||
|
+ str_len_sum += len + 1;
|
||
|
+ }
|
||
|
|
||
|
/* Replace "=,-" with "_". */
|
||
|
for (i = 0; i < strlen (attr_str); i++)
|
||
|
@@ -28986,18 +29016,20 @@ sorted_attr_string (const char *str)
|
||
|
attr = strtok (NULL, ",");
|
||
|
}
|
||
|
|
||
|
- qsort (args, argnum, sizeof (char*), attr_strcmp);
|
||
|
+ qsort (args, argnum, sizeof (char *), attr_strcmp);
|
||
|
|
||
|
- ret_str = (char *)xmalloc (strlen (str) + 1);
|
||
|
- strcpy (ret_str, args[0]);
|
||
|
- for (i = 1; i < argnum; i++)
|
||
|
+ ret_str = XNEWVEC (char, str_len_sum);
|
||
|
+ str_len_sum = 0;
|
||
|
+ for (i = 0; i < argnum; i++)
|
||
|
{
|
||
|
- strcat (ret_str, "_");
|
||
|
- strcat (ret_str, args[i]);
|
||
|
+ size_t len = strlen (args[i]);
|
||
|
+ memcpy (ret_str + str_len_sum, args[i], len);
|
||
|
+ ret_str[str_len_sum + len] = i < argnum - 1 ? '_' : '\0';
|
||
|
+ str_len_sum += len + 1;
|
||
|
}
|
||
|
|
||
|
- free (args);
|
||
|
- free (attr_str);
|
||
|
+ XDELETEVEC (args);
|
||
|
+ XDELETEVEC (attr_str);
|
||
|
return ret_str;
|
||
|
}
|
||
|
|
||
|
@@ -29009,8 +29041,8 @@ static tree
|
||
|
ix86_mangle_function_version_assembler_name (tree decl, tree id)
|
||
|
{
|
||
|
tree version_attr;
|
||
|
- const char *orig_name, *version_string, *attr_str;
|
||
|
- char *assembler_name;
|
||
|
+ const char *orig_name, *version_string;
|
||
|
+ char *attr_str, *assembler_name;
|
||
|
|
||
|
if (DECL_DECLARED_INLINE_P (decl)
|
||
|
&& lookup_attribute ("gnu_inline",
|
||
|
@@ -29034,9 +29066,11 @@ ix86_mangle_function_version_assembler_n
|
||
|
version_string
|
||
|
= TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (version_attr)));
|
||
|
|
||
|
- attr_str = sorted_attr_string (version_string);
|
||
|
- assembler_name = (char *) xmalloc (strlen (orig_name)
|
||
|
- + strlen (attr_str) + 2);
|
||
|
+ if (strcmp (version_string, "default") == 0)
|
||
|
+ return id;
|
||
|
+
|
||
|
+ attr_str = sorted_attr_string (TREE_VALUE (version_attr));
|
||
|
+ assembler_name = XNEWVEC (char, strlen (orig_name) + strlen (attr_str) + 2);
|
||
|
|
||
|
sprintf (assembler_name, "%s.%s", orig_name, attr_str);
|
||
|
|
||
|
@@ -29044,7 +29078,10 @@ ix86_mangle_function_version_assembler_n
|
||
|
if (DECL_ASSEMBLER_NAME_SET_P (decl))
|
||
|
SET_DECL_RTL (decl, NULL);
|
||
|
|
||
|
- return get_identifier (assembler_name);
|
||
|
+ tree ret = get_identifier (assembler_name);
|
||
|
+ XDELETEVEC (attr_str);
|
||
|
+ XDELETEVEC (assembler_name);
|
||
|
+ return ret;
|
||
|
}
|
||
|
|
||
|
/* This function returns true if FN1 and FN2 are versions of the same function,
|
||
|
@@ -29055,10 +29092,9 @@ static bool
|
||
|
ix86_function_versions (tree fn1, tree fn2)
|
||
|
{
|
||
|
tree attr1, attr2;
|
||
|
- const char *attr_str1, *attr_str2;
|
||
|
char *target1, *target2;
|
||
|
bool result;
|
||
|
-
|
||
|
+
|
||
|
if (TREE_CODE (fn1) != FUNCTION_DECL
|
||
|
|| TREE_CODE (fn2) != FUNCTION_DECL)
|
||
|
return false;
|
||
|
@@ -29070,15 +29106,35 @@ ix86_function_versions (tree fn1, tree f
|
||
|
if (attr1 == NULL_TREE && attr2 == NULL_TREE)
|
||
|
return false;
|
||
|
|
||
|
- /* If one function does not have a target attribute, these are versions. */
|
||
|
+ /* Diagnose missing target attribute if one of the decls is already
|
||
|
+ multi-versioned. */
|
||
|
if (attr1 == NULL_TREE || attr2 == NULL_TREE)
|
||
|
- return true;
|
||
|
-
|
||
|
- attr_str1 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr1)));
|
||
|
- attr_str2 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr2)));
|
||
|
+ {
|
||
|
+ if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2))
|
||
|
+ {
|
||
|
+ if (attr2 != NULL_TREE)
|
||
|
+ {
|
||
|
+ tree tem = fn1;
|
||
|
+ fn1 = fn2;
|
||
|
+ fn2 = tem;
|
||
|
+ attr1 = attr2;
|
||
|
+ }
|
||
|
+ error_at (DECL_SOURCE_LOCATION (fn2),
|
||
|
+ "missing %<target%> attribute for multi-versioned %D",
|
||
|
+ fn2);
|
||
|
+ error_at (DECL_SOURCE_LOCATION (fn1),
|
||
|
+ "previous declaration of %D", fn1);
|
||
|
+ /* Prevent diagnosing of the same error multiple times. */
|
||
|
+ DECL_ATTRIBUTES (fn2)
|
||
|
+ = tree_cons (get_identifier ("target"),
|
||
|
+ copy_node (TREE_VALUE (attr1)),
|
||
|
+ DECL_ATTRIBUTES (fn2));
|
||
|
+ }
|
||
|
+ return false;
|
||
|
+ }
|
||
|
|
||
|
- target1 = sorted_attr_string (attr_str1);
|
||
|
- target2 = sorted_attr_string (attr_str2);
|
||
|
+ target1 = sorted_attr_string (TREE_VALUE (attr1));
|
||
|
+ target2 = sorted_attr_string (TREE_VALUE (attr2));
|
||
|
|
||
|
/* The sorted target strings must be different for fn1 and fn2
|
||
|
to be versions. */
|
||
|
@@ -29087,20 +29143,12 @@ ix86_function_versions (tree fn1, tree f
|
||
|
else
|
||
|
result = true;
|
||
|
|
||
|
- free (target1);
|
||
|
- free (target2);
|
||
|
+ XDELETEVEC (target1);
|
||
|
+ XDELETEVEC (target2);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
-/* This target supports function multiversioning. */
|
||
|
-
|
||
|
-static bool
|
||
|
-ix86_supports_function_versions (void)
|
||
|
-{
|
||
|
- return true;
|
||
|
-}
|
||
|
-
|
||
|
static tree
|
||
|
ix86_mangle_decl_assembler_name (tree decl, tree id)
|
||
|
{
|
||
|
@@ -29141,10 +29189,10 @@ make_name (tree decl, const char *suffix
|
||
|
|
||
|
/* Use '.' to concatenate names as it is demangler friendly. */
|
||
|
if (make_unique)
|
||
|
- snprintf (global_var_name, name_len, "%s.%s.%s", name,
|
||
|
- unique_name, suffix);
|
||
|
+ snprintf (global_var_name, name_len, "%s.%s.%s", name, unique_name,
|
||
|
+ suffix);
|
||
|
else
|
||
|
- snprintf (global_var_name, name_len, "%s.%s", name, suffix);
|
||
|
+ snprintf (global_var_name, name_len, "%s.%s", name, suffix);
|
||
|
|
||
|
return global_var_name;
|
||
|
}
|
||
|
@@ -29159,7 +29207,7 @@ static tree
|
||
|
make_dispatcher_decl (const tree decl)
|
||
|
{
|
||
|
tree func_decl;
|
||
|
- char *func_name, *resolver_name;
|
||
|
+ char *func_name;
|
||
|
tree fn_type, func_type;
|
||
|
bool is_uniq = false;
|
||
|
|
||
|
@@ -29167,14 +29215,13 @@ make_dispatcher_decl (const tree decl)
|
||
|
is_uniq = true;
|
||
|
|
||
|
func_name = make_name (decl, "ifunc", is_uniq);
|
||
|
- resolver_name = make_name (decl, "resolver", is_uniq);
|
||
|
- gcc_assert (resolver_name);
|
||
|
|
||
|
fn_type = TREE_TYPE (decl);
|
||
|
func_type = build_function_type (TREE_TYPE (fn_type),
|
||
|
TYPE_ARG_TYPES (fn_type));
|
||
|
|
||
|
func_decl = build_fn_decl (func_name, func_type);
|
||
|
+ XDELETEVEC (func_name);
|
||
|
TREE_USED (func_decl) = 1;
|
||
|
DECL_CONTEXT (func_decl) = NULL_TREE;
|
||
|
DECL_INITIAL (func_decl) = error_mark_node;
|
||
|
@@ -29196,9 +29243,14 @@ make_dispatcher_decl (const tree decl)
|
||
|
static bool
|
||
|
is_function_default_version (const tree decl)
|
||
|
{
|
||
|
- return (TREE_CODE (decl) == FUNCTION_DECL
|
||
|
- && DECL_FUNCTION_VERSIONED (decl)
|
||
|
- && lookup_attribute ("target", DECL_ATTRIBUTES (decl)) == NULL_TREE);
|
||
|
+ if (TREE_CODE (decl) != FUNCTION_DECL
|
||
|
+ || !DECL_FUNCTION_VERSIONED (decl))
|
||
|
+ return false;
|
||
|
+ tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
|
||
|
+ gcc_assert (attr);
|
||
|
+ attr = TREE_VALUE (TREE_VALUE (attr));
|
||
|
+ return (TREE_CODE (attr) == STRING_CST
|
||
|
+ && strcmp (TREE_STRING_POINTER (attr), "default") == 0);
|
||
|
}
|
||
|
|
||
|
/* Make a dispatcher declaration for the multi-versioned function DECL.
|
||
|
@@ -29392,6 +29444,7 @@ make_resolver_func (const tree default_d
|
||
|
/* Create the alias for dispatch to resolver here. */
|
||
|
/*cgraph_create_function_alias (dispatch_decl, decl);*/
|
||
|
cgraph_same_body_alias (NULL, dispatch_decl, decl);
|
||
|
+ XDELETEVEC (resolver_name);
|
||
|
return decl;
|
||
|
}
|
||
|
|
||
|
@@ -29453,7 +29506,7 @@ ix86_generate_version_dispatcher_body (v
|
||
|
}
|
||
|
|
||
|
dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb);
|
||
|
-
|
||
|
+ fn_ver_vec.release ();
|
||
|
rebuild_cgraph_edges ();
|
||
|
pop_cfun ();
|
||
|
return resolver_decl;
|
||
|
@@ -42441,10 +42494,6 @@ ix86_memmodel_check (unsigned HOST_WIDE_
|
||
|
#undef TARGET_OPTION_FUNCTION_VERSIONS
|
||
|
#define TARGET_OPTION_FUNCTION_VERSIONS ix86_function_versions
|
||
|
|
||
|
-#undef TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS
|
||
|
-#define TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS \
|
||
|
- ix86_supports_function_versions
|
||
|
-
|
||
|
#undef TARGET_CAN_INLINE_P
|
||
|
#define TARGET_CAN_INLINE_P ix86_can_inline_p
|
||
|
|
||
|
--- gcc/target.def.jj 2013-01-11 09:02:32.000000000 +0100
|
||
|
+++ gcc/target.def 2013-01-21 11:25:29.145124702 +0100
|
||
|
@@ -2831,14 +2831,6 @@ DEFHOOK
|
||
|
bool, (tree decl1, tree decl2),
|
||
|
hook_bool_tree_tree_false)
|
||
|
|
||
|
-/* This function returns true if the target supports function
|
||
|
- multiversioning. */
|
||
|
-DEFHOOK
|
||
|
-(supports_function_versions,
|
||
|
- "",
|
||
|
- bool, (void),
|
||
|
- hook_bool_void_false)
|
||
|
-
|
||
|
/* Function to determine if one function can inline another function. */
|
||
|
#undef HOOK_PREFIX
|
||
|
#define HOOK_PREFIX "TARGET_"
|
||
|
--- gcc/doc/tm.texi.in.jj 2013-01-11 09:02:26.000000000 +0100
|
||
|
+++ gcc/doc/tm.texi.in 2013-01-21 11:25:57.789962584 +0100
|
||
|
@@ -9768,11 +9768,6 @@ different target specific attributes, th
|
||
|
different target machines.
|
||
|
@end deftypefn
|
||
|
|
||
|
-@hook TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS
|
||
|
-This target hook returns @code{true} if the target supports function
|
||
|
-multiversioning.
|
||
|
-@end deftypefn
|
||
|
-
|
||
|
@hook TARGET_CAN_INLINE_P
|
||
|
This target hook returns @code{false} if the @var{caller} function
|
||
|
cannot inline @var{callee}, based on target specific information. By
|
||
|
--- gcc/doc/tm.texi.jj 2013-01-11 09:02:26.000000000 +0100
|
||
|
+++ gcc/doc/tm.texi 2013-01-21 11:26:08.647897014 +0100
|
||
|
@@ -9907,11 +9907,6 @@ different target specific attributes, th
|
||
|
different target machines.
|
||
|
@end deftypefn
|
||
|
|
||
|
-@deftypefn {Target Hook} bool TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS (void)
|
||
|
-This target hook returns @code{true} if the target supports function
|
||
|
-multiversioning.
|
||
|
-@end deftypefn
|
||
|
-
|
||
|
@deftypefn {Target Hook} bool TARGET_CAN_INLINE_P (tree @var{caller}, tree @var{callee})
|
||
|
This target hook returns @code{false} if the @var{caller} function
|
||
|
cannot inline @var{callee}, based on target specific information. By
|
||
|
--- gcc/c-family/c-common.c.jj 2013-01-21 10:56:55.165014693 +0100
|
||
|
+++ gcc/c-family/c-common.c 2013-01-21 10:59:04.305285038 +0100
|
||
|
@@ -8759,12 +8759,8 @@ handle_target_attribute (tree *node, tre
|
||
|
warning (OPT_Wattributes, "%qE attribute ignored", name);
|
||
|
*no_add_attrs = true;
|
||
|
}
|
||
|
- /* Do not strip invalid target attributes for targets which support function
|
||
|
- multiversioning as the target string is used to determine versioned
|
||
|
- functions. */
|
||
|
else if (! targetm.target_option.valid_attribute_p (*node, name, args,
|
||
|
- flags)
|
||
|
- && ! targetm.target_option.supports_function_versions ())
|
||
|
+ flags))
|
||
|
*no_add_attrs = true;
|
||
|
|
||
|
return NULL_TREE;
|
||
|
--- gcc/testsuite/g++.dg/mv1.C.jj 2013-01-21 10:56:54.564017815 +0100
|
||
|
+++ gcc/testsuite/g++.dg/mv1.C 2013-01-21 11:35:42.260684508 +0100
|
||
|
@@ -1,130 +0,0 @@
|
||
|
-/* Test case to check if Multiversioning works. */
|
||
|
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
-/* { dg-require-ifunc "" } */
|
||
|
-/* { dg-options "-O2 -fPIC" } */
|
||
|
-
|
||
|
-#include <assert.h>
|
||
|
-
|
||
|
-/* Default version. */
|
||
|
-int foo ();
|
||
|
-/* The other versions of foo. Mix up the ordering and
|
||
|
- check if the dispatching does it in the order of priority. */
|
||
|
-/* Check combination of target attributes. */
|
||
|
-int foo () __attribute__ ((target("arch=corei7,popcnt")));
|
||
|
-/* The target operands in this declaration and the definition are re-ordered.
|
||
|
- This should still work. */
|
||
|
-int foo () __attribute__ ((target("ssse3,avx2")));
|
||
|
-
|
||
|
-/* Check for all target attributes for which dispatchers are available. */
|
||
|
-/* Check arch= */
|
||
|
-int foo () __attribute__((target("arch=core2")));
|
||
|
-int foo () __attribute__((target("arch=corei7")));
|
||
|
-int foo () __attribute__((target("arch=atom")));
|
||
|
-/* Check ISAs */
|
||
|
-int foo () __attribute__((target("avx")));
|
||
|
-int foo () __attribute__ ((target("arch=core2,sse4.2")));
|
||
|
-/* Check more arch=. */
|
||
|
-int foo () __attribute__((target("arch=amdfam10")));
|
||
|
-int foo () __attribute__((target("arch=bdver1")));
|
||
|
-int foo () __attribute__((target("arch=bdver2")));
|
||
|
-
|
||
|
-int (*p)() = &foo;
|
||
|
-int main ()
|
||
|
-{
|
||
|
- int val = foo ();
|
||
|
- assert (val == (*p)());
|
||
|
-
|
||
|
- /* Check in the exact same order in which the dispatching
|
||
|
- is expected to happen. */
|
||
|
- if (__builtin_cpu_is ("bdver1"))
|
||
|
- assert (val == 1);
|
||
|
- else if (__builtin_cpu_is ("bdver2"))
|
||
|
- assert (val == 2);
|
||
|
- else if (__builtin_cpu_supports ("avx2")
|
||
|
- && __builtin_cpu_supports ("ssse3"))
|
||
|
- assert (val == 3);
|
||
|
- else if (__builtin_cpu_supports ("avx"))
|
||
|
- assert (val == 4);
|
||
|
- else if (__builtin_cpu_is ("corei7")
|
||
|
- && __builtin_cpu_supports ("popcnt"))
|
||
|
- assert (val == 5);
|
||
|
- else if (__builtin_cpu_is ("corei7"))
|
||
|
- assert (val == 6);
|
||
|
- else if (__builtin_cpu_is ("amdfam10h"))
|
||
|
- assert (val == 7);
|
||
|
- else if (__builtin_cpu_is ("core2")
|
||
|
- && __builtin_cpu_supports ("sse4.2"))
|
||
|
- assert (val == 8);
|
||
|
- else if (__builtin_cpu_is ("core2"))
|
||
|
- assert (val == 9);
|
||
|
- else if (__builtin_cpu_is ("atom"))
|
||
|
- assert (val == 10);
|
||
|
- else
|
||
|
- assert (val == 0);
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int foo ()
|
||
|
-{
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=corei7,popcnt")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 5;
|
||
|
-}
|
||
|
-int __attribute__ ((target("avx2,ssse3")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 3;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=core2")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 9;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=corei7")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 6;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=atom")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 10;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("avx")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 4;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=core2,sse4.2")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 8;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=amdfam10")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 7;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=bdver1")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 1;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("arch=bdver2")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 2;
|
||
|
-}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv1.C.jj 2013-01-21 11:36:16.084491175 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv1.C 2013-01-21 11:42:52.975315718 +0100
|
||
|
@@ -0,0 +1,132 @@
|
||
|
+/* Test case to check if Multiversioning works. */
|
||
|
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
+/* { dg-require-ifunc "" } */
|
||
|
+/* { dg-options "-O2 -fPIC" } */
|
||
|
+
|
||
|
+#include <assert.h>
|
||
|
+
|
||
|
+/* Default version. */
|
||
|
+int foo (); // Extra declaration that is merged with the second one.
|
||
|
+int foo () __attribute__ ((target("default")));
|
||
|
+/* The other versions of foo. Mix up the ordering and
|
||
|
+ check if the dispatching does it in the order of priority. */
|
||
|
+/* Check combination of target attributes. */
|
||
|
+int foo () __attribute__ ((target("arch=corei7,popcnt")));
|
||
|
+/* The target operands in this declaration and the definition are re-ordered.
|
||
|
+ This should still work. */
|
||
|
+int foo () __attribute__ ((target("ssse3,avx2")));
|
||
|
+
|
||
|
+/* Check for all target attributes for which dispatchers are available. */
|
||
|
+/* Check arch= */
|
||
|
+int foo () __attribute__((target("arch=core2")));
|
||
|
+int foo () __attribute__((target("arch=corei7")));
|
||
|
+int foo () __attribute__((target("arch=atom")));
|
||
|
+/* Check ISAs */
|
||
|
+int foo () __attribute__((target("avx")));
|
||
|
+int foo () __attribute__ ((target("arch=core2,sse4.2")));
|
||
|
+/* Check more arch=. */
|
||
|
+int foo () __attribute__((target("arch=amdfam10")));
|
||
|
+int foo () __attribute__((target("arch=bdver1")));
|
||
|
+int foo () __attribute__((target("arch=bdver2")));
|
||
|
+
|
||
|
+int (*p)() = &foo;
|
||
|
+int main ()
|
||
|
+{
|
||
|
+ int val = foo ();
|
||
|
+ assert (val == (*p)());
|
||
|
+
|
||
|
+ /* Check in the exact same order in which the dispatching
|
||
|
+ is expected to happen. */
|
||
|
+ if (__builtin_cpu_is ("bdver1"))
|
||
|
+ assert (val == 1);
|
||
|
+ else if (__builtin_cpu_is ("bdver2"))
|
||
|
+ assert (val == 2);
|
||
|
+ else if (__builtin_cpu_supports ("avx2")
|
||
|
+ && __builtin_cpu_supports ("ssse3"))
|
||
|
+ assert (val == 3);
|
||
|
+ else if (__builtin_cpu_supports ("avx"))
|
||
|
+ assert (val == 4);
|
||
|
+ else if (__builtin_cpu_is ("corei7")
|
||
|
+ && __builtin_cpu_supports ("popcnt"))
|
||
|
+ assert (val == 5);
|
||
|
+ else if (__builtin_cpu_is ("corei7"))
|
||
|
+ assert (val == 6);
|
||
|
+ else if (__builtin_cpu_is ("amdfam10h"))
|
||
|
+ assert (val == 7);
|
||
|
+ else if (__builtin_cpu_is ("core2")
|
||
|
+ && __builtin_cpu_supports ("sse4.2"))
|
||
|
+ assert (val == 8);
|
||
|
+ else if (__builtin_cpu_is ("core2"))
|
||
|
+ assert (val == 9);
|
||
|
+ else if (__builtin_cpu_is ("atom"))
|
||
|
+ assert (val == 10);
|
||
|
+ else
|
||
|
+ assert (val == 0);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("default")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=corei7,popcnt")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 5;
|
||
|
+}
|
||
|
+int __attribute__ ((target("avx2,ssse3")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 3;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=core2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 9;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=corei7")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 6;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=atom")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 10;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("avx")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 4;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=core2,sse4.2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 8;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=amdfam10")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 7;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=bdver1")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("arch=bdver2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 2;
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/mv2.C.jj 2013-01-21 10:56:54.465018354 +0100
|
||
|
+++ gcc/testsuite/g++.dg/mv2.C 2013-01-21 11:35:45.088666745 +0100
|
||
|
@@ -1,118 +0,0 @@
|
||
|
-/* Test case to check if Multiversioning chooses the correct
|
||
|
- dispatching order when versions are for various ISAs. */
|
||
|
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
-/* { dg-require-ifunc "" } */
|
||
|
-/* { dg-options "-O2" } */
|
||
|
-
|
||
|
-#include <assert.h>
|
||
|
-
|
||
|
-/* Default version. */
|
||
|
-int foo ();
|
||
|
-/* The dispatch checks should be in the exact reverse order of the
|
||
|
- declarations below. */
|
||
|
-int foo () __attribute__ ((target ("mmx")));
|
||
|
-int foo () __attribute__ ((target ("sse")));
|
||
|
-int foo () __attribute__ ((target ("sse2")));
|
||
|
-int foo () __attribute__ ((target ("sse3")));
|
||
|
-int foo () __attribute__ ((target ("ssse3")));
|
||
|
-int foo () __attribute__ ((target ("sse4.1")));
|
||
|
-int foo () __attribute__ ((target ("sse4.2")));
|
||
|
-int foo () __attribute__ ((target ("popcnt")));
|
||
|
-int foo () __attribute__ ((target ("avx")));
|
||
|
-int foo () __attribute__ ((target ("avx2")));
|
||
|
-
|
||
|
-int main ()
|
||
|
-{
|
||
|
- int val = foo ();
|
||
|
-
|
||
|
- if (__builtin_cpu_supports ("avx2"))
|
||
|
- assert (val == 1);
|
||
|
- else if (__builtin_cpu_supports ("avx"))
|
||
|
- assert (val == 2);
|
||
|
- else if (__builtin_cpu_supports ("popcnt"))
|
||
|
- assert (val == 3);
|
||
|
- else if (__builtin_cpu_supports ("sse4.2"))
|
||
|
- assert (val == 4);
|
||
|
- else if (__builtin_cpu_supports ("sse4.1"))
|
||
|
- assert (val == 5);
|
||
|
- else if (__builtin_cpu_supports ("ssse3"))
|
||
|
- assert (val == 6);
|
||
|
- else if (__builtin_cpu_supports ("sse3"))
|
||
|
- assert (val == 7);
|
||
|
- else if (__builtin_cpu_supports ("sse2"))
|
||
|
- assert (val == 8);
|
||
|
- else if (__builtin_cpu_supports ("sse"))
|
||
|
- assert (val == 9);
|
||
|
- else if (__builtin_cpu_supports ("mmx"))
|
||
|
- assert (val == 10);
|
||
|
- else
|
||
|
- assert (val == 0);
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("mmx")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 10;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("sse")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 9;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("sse2")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 8;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("sse3")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 7;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("ssse3")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 6;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("sse4.1")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 5;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("sse4.2")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 4;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("popcnt")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 3;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("avx")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 2;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target("avx2")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 1;
|
||
|
-}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv2.C.jj 2013-01-21 11:36:16.085491165 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv2.C 2013-01-21 10:58:57.000000000 +0100
|
||
|
@@ -0,0 +1,118 @@
|
||
|
+/* Test case to check if Multiversioning chooses the correct
|
||
|
+ dispatching order when versions are for various ISAs. */
|
||
|
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
+/* { dg-require-ifunc "" } */
|
||
|
+/* { dg-options "-O2" } */
|
||
|
+
|
||
|
+#include <assert.h>
|
||
|
+
|
||
|
+/* Default version. */
|
||
|
+int foo () __attribute__ ((target ("default")));
|
||
|
+/* The dispatch checks should be in the exact reverse order of the
|
||
|
+ declarations below. */
|
||
|
+int foo () __attribute__ ((target ("mmx")));
|
||
|
+int foo () __attribute__ ((target ("sse")));
|
||
|
+int foo () __attribute__ ((target ("sse2")));
|
||
|
+int foo () __attribute__ ((target ("sse3")));
|
||
|
+int foo () __attribute__ ((target ("ssse3")));
|
||
|
+int foo () __attribute__ ((target ("sse4.1")));
|
||
|
+int foo () __attribute__ ((target ("sse4.2")));
|
||
|
+int foo () __attribute__ ((target ("popcnt")));
|
||
|
+int foo () __attribute__ ((target ("avx")));
|
||
|
+int foo () __attribute__ ((target ("avx2")));
|
||
|
+
|
||
|
+int main ()
|
||
|
+{
|
||
|
+ int val = foo ();
|
||
|
+
|
||
|
+ if (__builtin_cpu_supports ("avx2"))
|
||
|
+ assert (val == 1);
|
||
|
+ else if (__builtin_cpu_supports ("avx"))
|
||
|
+ assert (val == 2);
|
||
|
+ else if (__builtin_cpu_supports ("popcnt"))
|
||
|
+ assert (val == 3);
|
||
|
+ else if (__builtin_cpu_supports ("sse4.2"))
|
||
|
+ assert (val == 4);
|
||
|
+ else if (__builtin_cpu_supports ("sse4.1"))
|
||
|
+ assert (val == 5);
|
||
|
+ else if (__builtin_cpu_supports ("ssse3"))
|
||
|
+ assert (val == 6);
|
||
|
+ else if (__builtin_cpu_supports ("sse3"))
|
||
|
+ assert (val == 7);
|
||
|
+ else if (__builtin_cpu_supports ("sse2"))
|
||
|
+ assert (val == 8);
|
||
|
+ else if (__builtin_cpu_supports ("sse"))
|
||
|
+ assert (val == 9);
|
||
|
+ else if (__builtin_cpu_supports ("mmx"))
|
||
|
+ assert (val == 10);
|
||
|
+ else
|
||
|
+ assert (val == 0);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("default")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("mmx")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 10;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("sse")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 9;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("sse2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 8;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("sse3")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 7;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("ssse3")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 6;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("sse4.1")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 5;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("sse4.2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 4;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("popcnt")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 3;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("avx")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 2;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("avx2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 1;
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/mv3.C.jj 2013-01-18 21:23:45.000000000 +0100
|
||
|
+++ gcc/testsuite/g++.dg/mv3.C 2013-01-21 11:35:52.400626435 +0100
|
||
|
@@ -1,36 +0,0 @@
|
||
|
-/* Test case to check if a call to a multiversioned function
|
||
|
- is replaced with a direct call to the particular version when
|
||
|
- the most specialized version's target attributes match the
|
||
|
- caller.
|
||
|
-
|
||
|
- In this program, foo is multiversioned but there is no default
|
||
|
- function. This is an error if the call has to go through a
|
||
|
- dispatcher. However, the call to foo in bar can be replaced
|
||
|
- with a direct call to the popcnt version of foo. Hence, this
|
||
|
- test should pass. */
|
||
|
-
|
||
|
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
-/* { dg-options "-O2" } */
|
||
|
-
|
||
|
-
|
||
|
-int __attribute__ ((target ("sse")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 1;
|
||
|
-}
|
||
|
-int __attribute__ ((target ("popcnt")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int __attribute__ ((target ("popcnt")))
|
||
|
-bar ()
|
||
|
-{
|
||
|
- return foo ();
|
||
|
-}
|
||
|
-
|
||
|
-int main ()
|
||
|
-{
|
||
|
- return bar ();
|
||
|
-}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv3.C.jj 2013-01-21 11:36:16.086491156 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv3.C 2013-01-18 21:23:45.000000000 +0100
|
||
|
@@ -0,0 +1,36 @@
|
||
|
+/* Test case to check if a call to a multiversioned function
|
||
|
+ is replaced with a direct call to the particular version when
|
||
|
+ the most specialized version's target attributes match the
|
||
|
+ caller.
|
||
|
+
|
||
|
+ In this program, foo is multiversioned but there is no default
|
||
|
+ function. This is an error if the call has to go through a
|
||
|
+ dispatcher. However, the call to foo in bar can be replaced
|
||
|
+ with a direct call to the popcnt version of foo. Hence, this
|
||
|
+ test should pass. */
|
||
|
+
|
||
|
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
+/* { dg-options "-O2" } */
|
||
|
+
|
||
|
+
|
||
|
+int __attribute__ ((target ("sse")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+int __attribute__ ((target ("popcnt")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target ("popcnt")))
|
||
|
+bar ()
|
||
|
+{
|
||
|
+ return foo ();
|
||
|
+}
|
||
|
+
|
||
|
+int main ()
|
||
|
+{
|
||
|
+ return bar ();
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/mv4.C.jj 2013-01-18 21:23:45.000000000 +0100
|
||
|
+++ gcc/testsuite/g++.dg/mv4.C 2013-01-21 11:35:54.308616223 +0100
|
||
|
@@ -1,24 +0,0 @@
|
||
|
-/* Test case to check if the compiler generates an error message
|
||
|
- when the default version of a multiversioned function is absent
|
||
|
- and its pointer is taken. */
|
||
|
-
|
||
|
-/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
|
||
|
-/* { dg-require-ifunc "" } */
|
||
|
-/* { dg-options "-O2" } */
|
||
|
-
|
||
|
-int __attribute__ ((target ("sse")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 1;
|
||
|
-}
|
||
|
-int __attribute__ ((target ("popcnt")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int main ()
|
||
|
-{
|
||
|
- int (*p)() = &foo; /* { dg-error "use of multiversioned function without a default" {} } */
|
||
|
- return (*p)();
|
||
|
-}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv4.C.jj 2013-01-21 11:36:16.088491133 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv4.C 2013-01-18 21:23:45.000000000 +0100
|
||
|
@@ -0,0 +1,24 @@
|
||
|
+/* Test case to check if the compiler generates an error message
|
||
|
+ when the default version of a multiversioned function is absent
|
||
|
+ and its pointer is taken. */
|
||
|
+
|
||
|
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
|
||
|
+/* { dg-require-ifunc "" } */
|
||
|
+/* { dg-options "-O2" } */
|
||
|
+
|
||
|
+int __attribute__ ((target ("sse")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+int __attribute__ ((target ("popcnt")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int main ()
|
||
|
+{
|
||
|
+ int (*p)() = &foo; /* { dg-error "use of multiversioned function without a default" {} } */
|
||
|
+ return (*p)();
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/mv5.C.jj 2013-01-21 10:56:54.582017723 +0100
|
||
|
+++ gcc/testsuite/g++.dg/mv5.C 2013-01-21 11:35:56.027606185 +0100
|
||
|
@@ -1,25 +0,0 @@
|
||
|
-/* Test case to check if multiversioned functions are still generated if they are
|
||
|
- marked comdat with inline keyword. */
|
||
|
-
|
||
|
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
-/* { dg-require-ifunc "" } */
|
||
|
-/* { dg-options "-O2" } */
|
||
|
-
|
||
|
-
|
||
|
-/* Default version. */
|
||
|
-inline int
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-inline int __attribute__ ((target ("popcnt")))
|
||
|
-foo ()
|
||
|
-{
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int main ()
|
||
|
-{
|
||
|
- return foo ();
|
||
|
-}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv5.C.jj 2013-01-21 11:36:16.089491123 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv5.C 2013-01-21 10:58:57.000000000 +0100
|
||
|
@@ -0,0 +1,25 @@
|
||
|
+/* Test case to check if multiversioned functions are still generated if they are
|
||
|
+ marked comdat with inline keyword. */
|
||
|
+
|
||
|
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
+/* { dg-require-ifunc "" } */
|
||
|
+/* { dg-options "-O2" } */
|
||
|
+
|
||
|
+
|
||
|
+/* Default version. */
|
||
|
+inline int __attribute__ ((target ("default")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+inline int __attribute__ ((target ("popcnt")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int main ()
|
||
|
+{
|
||
|
+ return foo ();
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/mv6.C.jj 2013-01-21 10:56:54.504018081 +0100
|
||
|
+++ gcc/testsuite/g++.dg/mv6.C 2013-01-21 11:35:57.514597697 +0100
|
||
|
@@ -1,27 +0,0 @@
|
||
|
-/* Test to check if member version multiversioning works correctly. */
|
||
|
-
|
||
|
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
-/* { dg-require-ifunc "" } */
|
||
|
-/* { dg-options "-march=x86-64" } */
|
||
|
-
|
||
|
-class Foo
|
||
|
-{
|
||
|
- public:
|
||
|
- /* Default version of foo. */
|
||
|
- int foo ()
|
||
|
- {
|
||
|
- return 0;
|
||
|
- }
|
||
|
- /* corei7 version of foo. */
|
||
|
- __attribute__ ((target("arch=corei7")))
|
||
|
- int foo ()
|
||
|
- {
|
||
|
- return 0;
|
||
|
- }
|
||
|
-};
|
||
|
-
|
||
|
-int main ()
|
||
|
-{
|
||
|
- Foo f;
|
||
|
- return f.foo ();
|
||
|
-}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv6.C.jj 2013-01-21 11:36:16.090491117 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv6.C 2013-01-21 10:58:57.000000000 +0100
|
||
|
@@ -0,0 +1,28 @@
|
||
|
+/* Test to check if member version multiversioning works correctly. */
|
||
|
+
|
||
|
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
|
||
|
+/* { dg-require-ifunc "" } */
|
||
|
+/* { dg-options "-march=x86-64" } */
|
||
|
+
|
||
|
+class Foo
|
||
|
+{
|
||
|
+ public:
|
||
|
+ /* Default version of foo. */
|
||
|
+ __attribute__ ((target("default")))
|
||
|
+ int foo ()
|
||
|
+ {
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ /* corei7 version of foo. */
|
||
|
+ __attribute__ ((target("arch=corei7")))
|
||
|
+ int foo ()
|
||
|
+ {
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+};
|
||
|
+
|
||
|
+int main ()
|
||
|
+{
|
||
|
+ Foo f;
|
||
|
+ return f.foo ();
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv7.C.jj 2013-01-21 11:39:21.789460493 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv7.C 2013-01-21 11:45:05.098589632 +0100
|
||
|
@@ -0,0 +1,12 @@
|
||
|
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
|
||
|
+// { dg-options "" }
|
||
|
+
|
||
|
+__attribute__((target ("default")))
|
||
|
+void foo (void) // { dg-error "previously defined here" }
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+__attribute__((target (128)))
|
||
|
+void foo (void) // { dg-error "(not a string|redefinition)" }
|
||
|
+{
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv8.C.jj 2013-01-21 11:41:17.147836101 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv8.C 2013-01-21 11:45:13.493544256 +0100
|
||
|
@@ -0,0 +1,7 @@
|
||
|
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
|
||
|
+// { dg-options "" }
|
||
|
+
|
||
|
+__attribute__((target (11,12)))
|
||
|
+void foo (void) // { dg-error "not a string" }
|
||
|
+{
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv9.C.jj 2013-01-21 11:44:31.634774921 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv9.C 2013-01-21 11:45:18.275516266 +0100
|
||
|
@@ -0,0 +1,9 @@
|
||
|
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
|
||
|
+// { dg-options "" }
|
||
|
+
|
||
|
+void foo ();
|
||
|
+void foo () __attribute__((target ("sse4")));
|
||
|
+void foo () __attribute__((target ("default"))); // { dg-error "previous declaration" }
|
||
|
+void foo () // { dg-error "attribute for multi-versioned" }
|
||
|
+{
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv10.C.jj 2013-01-21 12:12:29.354541630 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv10.C 2013-01-21 12:12:56.207392886 +0100
|
||
|
@@ -0,0 +1,12 @@
|
||
|
+// { dg-do assemble { target i?86-*-* x86_64-*-* } }
|
||
|
+// { dg-options "" }
|
||
|
+
|
||
|
+__attribute__((target ("popcnt"), used))
|
||
|
+void foo (void)
|
||
|
+{
|
||
|
+}
|
||
|
+
|
||
|
+__attribute__((target ("popcnt","avx"), used))
|
||
|
+void foo (void)
|
||
|
+{
|
||
|
+}
|
||
|
--- gcc/testsuite/g++.dg/ext/mv11.C.jj 2013-01-21 12:16:26.381285535 +0100
|
||
|
+++ gcc/testsuite/g++.dg/ext/mv11.C 2013-01-21 12:17:33.380918996 +0100
|
||
|
@@ -0,0 +1,23 @@
|
||
|
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
|
||
|
+// { dg-options "-msse2" }
|
||
|
+
|
||
|
+int foo () __attribute__ ((target("default")));
|
||
|
+int foo () __attribute__ ((target("sse2")));
|
||
|
+
|
||
|
+int
|
||
|
+main ()
|
||
|
+{
|
||
|
+ return foo ();
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("default")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int __attribute__ ((target("sse2")))
|
||
|
+foo ()
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|