aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/c-family/c-common.c6
-rw-r--r--gcc/config/i386/i386.c101
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/doc/tm.texi5
-rw-r--r--gcc/doc/tm.texi.in5
-rw-r--r--gcc/target.def8
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/mv1.C2
-rw-r--r--gcc/testsuite/g++.dg/mv2.C2
-rw-r--r--gcc/testsuite/g++.dg/mv3.C2
-rw-r--r--gcc/testsuite/g++.dg/mv4.C2
-rw-r--r--gcc/testsuite/g++.dg/mv5.C2
13 files changed, 114 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 651ba48..148388d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 872a6a0..0127513 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b466a4f..08eb06c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 82b2c0a..0aecabb 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 75aa867..55a1037 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 95fab18..e820f77 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -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
diff --git a/gcc/target.def b/gcc/target.def
index c5bbfae..79bb955 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -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_"
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 59f3441..0d97252 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/mv1.C b/gcc/testsuite/g++.dg/mv1.C
index 150b451..bad0c44 100644
--- a/gcc/testsuite/g++.dg/mv1.C
+++ b/gcc/testsuite/g++.dg/mv1.C
@@ -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>
diff --git a/gcc/testsuite/g++.dg/mv2.C b/gcc/testsuite/g++.dg/mv2.C
index f94877a..baaa5da 100644
--- a/gcc/testsuite/g++.dg/mv2.C
+++ b/gcc/testsuite/g++.dg/mv2.C
@@ -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>
diff --git a/gcc/testsuite/g++.dg/mv3.C b/gcc/testsuite/g++.dg/mv3.C
index c7088f2..ec2aa1f 100644
--- a/gcc/testsuite/g++.dg/mv3.C
+++ b/gcc/testsuite/g++.dg/mv3.C
@@ -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")))
diff --git a/gcc/testsuite/g++.dg/mv4.C b/gcc/testsuite/g++.dg/mv4.C
index ac5c548..ff1cc2f 100644
--- a/gcc/testsuite/g++.dg/mv4.C
+++ b/gcc/testsuite/g++.dg/mv4.C
@@ -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 ()
diff --git a/gcc/testsuite/g++.dg/mv5.C b/gcc/testsuite/g++.dg/mv5.C
index cac6d04..93daab6 100644
--- a/gcc/testsuite/g++.dg/mv5.C
+++ b/gcc/testsuite/g++.dg/mv5.C
@@ -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. */