Before this patch...

Before this patch, function multiversioning determines that two functions
are different by comparing the arch type and isa flags that are set
after the target string is processed. This leads to cases where  the
versions become identical when the command-line target options are
altered.

This patch modifies the function version determination to
just compare the target string.


2012-12-27  Sriraman Tallam  <tmsriram@google.com>

	* doc/tm.texi.in (TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS): Document
	new target hook.
	* doc/tm.texi: Regenerate.
	* c-family/c-common.c (handle_target_attribute): Retain target attribute
	for targets that support versioning.
	* target.def (supports_function_versions): New hook.
	* cp/class.c (add_method): Remove calls
	to DECL_FUNCTION_SPECIFIC_TARGET.
	* config/i386/i386.c (ix86_function_versions): Use target string
	to check for function versions instead of target flags.
	* (ix86_supports_function_versions): New function.
	* (is_function_default_version): Check target string.
	* TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS: New macro.

2012-12-27  Sriraman Tallam  <tmsriram@google.com>

	* testsuite/g++.dg/mv1.C: Remove target options.
	* testsuite/g++.dg/mv2.C: Ditto.
	* testsuite/g++.dg/mv3.C: Ditto.
	* testsuite/g++.dg/mv4.C: Ditto.
	* testsuite/g++.dg/mv5.C: Ditto.

From-SVN: r194730
This commit is contained in:
Sriraman Tallam 2012-12-27 01:58:06 +00:00
parent 1b9c5a882f
commit eb745e40fe
13 changed files with 114 additions and 50 deletions

View File

@ -1,7 +1,26 @@
<<<<<<< .mine
2012-12-26 Sriraman Tallam <tmsriram@google.com>
* doc/tm.texi.in (TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS): Document
new target hook.
* doc/tm.texi: Regenerate.
* c-family/c-common.c (handle_target_attribute): Retain target attribute
for targets that support versioning.
* target.def (supports_function_versions): New hook.
* cp/class.c (add_method): Remove calls
to DECL_FUNCTION_SPECIFIC_TARGET.
* config/i386/i386.c (ix86_function_versions): Use target string
to check for function versions instead of target flags.
* (ix86_supports_function_versions): New function.
* (is_function_default_version): Check target string.
* TARGET_OPTION_SUPPORTS_FUNCTION_VERSIONS: New macro.
=======
2012-12-27 Steven Bosscher <steven@gcc.gnu.org>
* cgraph.c (verify_cgraph_node): Don't allocate/free visited_nodes set.
>>>>>>> .r194729
2012-12-25 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/53789

View File

@ -8742,8 +8742,12 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
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))
flags)
&& ! targetm.target_option.supports_function_versions ())
*no_add_attrs = true;
return NULL_TREE;

View File

@ -28945,47 +28945,6 @@ dispatch_function_versions (tree dispatch_decl,
return 0;
}
/* This function returns true if FN1 and FN2 are versions of the same function,
that is, the targets of the function decls are different. This assumes
that FN1 and FN2 have the same signature. */
static bool
ix86_function_versions (tree fn1, tree fn2)
{
tree attr1, attr2;
struct cl_target_option *target1, *target2;
if (TREE_CODE (fn1) != FUNCTION_DECL
|| TREE_CODE (fn2) != FUNCTION_DECL)
return false;
attr1 = DECL_FUNCTION_SPECIFIC_TARGET (fn1);
attr2 = DECL_FUNCTION_SPECIFIC_TARGET (fn2);
/* Atleast one function decl should have target attribute specified. */
if (attr1 == NULL_TREE && attr2 == NULL_TREE)
return false;
if (attr1 == NULL_TREE)
attr1 = target_option_default_node;
else if (attr2 == NULL_TREE)
attr2 = target_option_default_node;
target1 = TREE_TARGET_OPTION (attr1);
target2 = TREE_TARGET_OPTION (attr2);
/* target1 and target2 must be different in some way. */
if (target1->x_ix86_isa_flags == target2->x_ix86_isa_flags
&& target1->x_target_flags == target2->x_target_flags
&& target1->arch == target2->arch
&& target1->tune == target2->tune
&& target1->x_ix86_fpmath == target2->x_ix86_fpmath
&& target1->branch_cost == target2->branch_cost)
return false;
return true;
}
/* Comparator function to be used in qsort routine to sort attribute
specification strings to "target". */
@ -29098,6 +29057,60 @@ ix86_mangle_function_version_assembler_name (tree decl, tree id)
return get_identifier (assembler_name);
}
/* This function returns true if FN1 and FN2 are versions of the same function,
that is, the target strings of the function decls are different. This assumes
that FN1 and FN2 have the same signature. */
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;
attr1 = lookup_attribute ("target", DECL_ATTRIBUTES (fn1));
attr2 = lookup_attribute ("target", DECL_ATTRIBUTES (fn2));
/* At least one function decl should have the target attribute specified. */
if (attr1 == NULL_TREE && attr2 == NULL_TREE)
return false;
/* If one function does not have a target attribute, these are versions. */
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)));
target1 = sorted_attr_string (attr_str1);
target2 = sorted_attr_string (attr_str2);
/* The sorted target strings must be different for fn1 and fn2
to be versions. */
if (strcmp (target1, target2) == 0)
result = false;
else
result = true;
free (target1);
free (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)
{
@ -29195,7 +29208,7 @@ is_function_default_version (const tree decl)
{
return (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_FUNCTION_VERSIONED (decl)
&& DECL_FUNCTION_SPECIFIC_TARGET (decl) == NULL_TREE);
&& lookup_attribute ("target", DECL_ATTRIBUTES (decl)) == NULL_TREE);
}
/* Make a dispatcher declaration for the multi-versioned function DECL.
@ -42463,6 +42476,10 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
#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

View File

@ -1096,8 +1096,6 @@ add_method (tree type, tree method, tree using_decl)
&& TREE_CODE (method) == FUNCTION_DECL
&& !DECL_EXTERN_C_P (fn)
&& !DECL_EXTERN_C_P (method)
&& (DECL_FUNCTION_SPECIFIC_TARGET (fn)
|| DECL_FUNCTION_SPECIFIC_TARGET (method))
&& targetm.target_option.function_versions (fn, method))
{
/* Mark functions as versions if necessary. Modify the mangled

View File

@ -9909,6 +9909,11 @@ different target specific attributes, that is, they are compiled for
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

View File

@ -9770,6 +9770,11 @@ different target specific attributes, that is, they are compiled for
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

View File

@ -2833,6 +2833,14 @@ 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),
hool_bool_void_false)
/* Function to determine if one function can inline another function. */
#undef HOOK_PREFIX
#define HOOK_PREFIX "TARGET_"

View File

@ -1,3 +1,11 @@
2012-12-27 Sriraman Tallam <tmsriram@google.com>
* testsuite/g++.dg/mv1.C: Remove target options.
* testsuite/g++.dg/mv2.C: Ditto.
* testsuite/g++.dg/mv3.C: Ditto.
* testsuite/g++.dg/mv4.C: Ditto.
* testsuite/g++.dg/mv5.C: Ditto.
2012-12-26 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/55539

View File

@ -1,7 +1,7 @@
/* Test case to check if Multiversioning works. */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-require-ifunc "" } */
/* { dg-options "-O2 -fPIC -march=x86-64 -mno-avx -mno-popcnt" } */
/* { dg-options "-O2 -fPIC" } */
#include <assert.h>

View File

@ -2,7 +2,7 @@
dispatching order when versions are for various ISAs. */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-require-ifunc "" } */
/* { dg-options "-O2 -mno-sse -mno-mmx -mno-popcnt -mno-avx" } */
/* { dg-options "-O2" } */
#include <assert.h>

View File

@ -10,7 +10,7 @@
test should pass. */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -mno-sse -mno-popcnt" } */
/* { dg-options "-O2" } */
int __attribute__ ((target ("sse")))

View File

@ -4,7 +4,7 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-require-ifunc "" } */
/* { dg-options "-O2 -mno-sse -mno-popcnt" } */
/* { dg-options "-O2" } */
int __attribute__ ((target ("sse")))
foo ()

View File

@ -3,7 +3,7 @@
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-require-ifunc "" } */
/* { dg-options "-O2 -mno-popcnt" } */
/* { dg-options "-O2" } */
/* Default version. */