aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSriraman Tallam <tmsriram@google.com>2012-11-13 21:56:30 +0000
committerSriraman Tallam <tmsriram@gcc.gnu.org>2012-11-13 21:56:30 +0000
commitbeb42d2022899f07712a3537beedbedd13f67fab (patch)
treee0a478402322716f4df3e0475249558057df7da6
parent73c3ed27fc6dc454b282d6e0d3fa76dbbd18e6dd (diff)
downloadgcc-beb42d2022899f07712a3537beedbedd13f67fab.zip
gcc-beb42d2022899f07712a3537beedbedd13f67fab.tar.gz
gcc-beb42d2022899f07712a3537beedbedd13f67fab.tar.bz2
cgraph.c (insert_new_cgraph_node_version): Use cgraph_get_node instead of cgraph_get_create_node.
2012-11-13 Sriraman Tallam <tmsriram@google.com> * cgraph.c (insert_new_cgraph_node_version): Use cgraph_get_node instead of cgraph_get_create_node. * config/i386/i386.c (ix86_get_function_versions_dispatcher): Move ifunc not supported code to the end. * class.c (mark_versions_used): Remove. (resolve_address_of_overloaded_function): Call target hook for versioned functions. Refactor to call get_function_versions_dispatcher. * decl.c (duplicate_decls): Add comments. * cp/call.c (get_function_version_dispatcher): Expose function. (mark_versions_used): Expose function. * cp/cp-tree.h (mark_versions_used): New declaration. (get_function_version_dispatcher): Ditto. * testsuite/g++.dg/mv4.C: Add require ifunc. Change error message. * testsuite/g++.dg/mv5.C: Add require ifunc. * testsuite/g++.dg/mv6.C: Add require ifunc. From-SVN: r193486
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/cgraph.c2
-rw-r--r--gcc/config/i386/i386.c11
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/cp/class.c69
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/mv4.C3
-rw-r--r--gcc/testsuite/g++.dg/mv5.C1
-rw-r--r--gcc/testsuite/g++.dg/mv6.C1
12 files changed, 56 insertions, 73 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 32b0102..4966b5dc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2012-11-13 Sriraman Tallam <tmsriram@google.com>
+
+ * cgraph.c (insert_new_cgraph_node_version): Use cgraph_get_node
+ instead of cgraph_get_create_node.
+ * config/i386/i386.c (ix86_get_function_versions_dispatcher): Move ifunc
+ not supported code to the end.
+
2012-11-13 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/55253
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 556eaff..1969576 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -206,7 +206,7 @@ insert_new_cgraph_node_version (struct cgraph_node *node)
void
delete_function_version (tree decl)
{
- struct cgraph_node *decl_node = cgraph_get_create_node (decl);
+ struct cgraph_node *decl_node = cgraph_get_node (decl);
struct cgraph_function_version_info *decl_v = NULL;
if (decl_node == NULL)
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 3af1cf8..de94d4b 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -28961,11 +28961,6 @@ ix86_get_function_versions_dispatcher (void *decl)
#if defined (ASM_OUTPUT_TYPE_DIRECTIVE) && HAVE_GNU_INDIRECT_FUNCTION
/* Right now, the dispatching is done via ifunc. */
dispatch_decl = make_dispatcher_decl (default_node->symbol.decl);
-#else
- error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl),
- "Multiversioning needs ifunc which is not supported "
- "in this configuration");
-#endif
dispatcher_node = cgraph_get_create_node (dispatch_decl);
gcc_assert (dispatcher_node != NULL);
@@ -28982,7 +28977,11 @@ ix86_get_function_versions_dispatcher (void *decl)
it_v->dispatcher_resolver = dispatch_decl;
it_v = it_v->next;
}
-
+#else
+ error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl),
+ "multiversioning needs ifunc which is not supported "
+ "in this configuration");
+#endif
return dispatch_decl;
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0f23cbc..8d12568 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2012-11-13 Sriraman Tallam <tmsriram@google.com>
+
+ * class.c (mark_versions_used): Remove.
+ (resolve_address_of_overloaded_function): Call target hook
+ for versioned functions. Refactor to call
+ get_function_versions_dispatcher.
+ * decl.c (duplicate_decls): Add comments.
+ * cp/call.c (get_function_version_dispatcher): Expose function.
+ (mark_versions_used): Expose function.
+ * cp/cp-tree.h (mark_versions_used): New declaration.
+ (get_function_version_dispatcher): Ditto.
+
2012-11-13 Dodji Seketeli <dodji@redhat.com>
PR c++/54466
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4373bce..bbeea85 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6517,7 +6517,7 @@ magic_varargs_p (tree fn)
/* Returns the decl of the dispatcher function if FN is a function version. */
-static tree
+tree
get_function_version_dispatcher (tree fn)
{
tree dispatcher_decl = NULL;
@@ -6530,8 +6530,8 @@ get_function_version_dispatcher (tree fn)
if (dispatcher_decl == NULL)
{
- error_at (input_location, "Call to multiversioned function"
- " without a default is not allowed");
+ error_at (input_location, "use of multiversioned function "
+ "without a default");
return NULL;
}
@@ -6543,7 +6543,7 @@ get_function_version_dispatcher (tree fn)
/* fn is a function version dispatcher that is marked used. Mark all the
semantically identical function versions it will dispatch as used. */
-static void
+void
mark_versions_used (tree fn)
{
struct cgraph_node *node;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index d3d9aed..0665e90 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7068,38 +7068,6 @@ pop_lang_context (void)
{
current_lang_name = VEC_pop (tree, current_lang_base);
}
-
-/* fn is a function version dispatcher that is marked used. Mark all the
- semantically identical function versions it will dispatch as used. */
-
-static void
-mark_versions_used (tree fn)
-{
- struct cgraph_node *node;
- struct cgraph_function_version_info *node_v;
- struct cgraph_function_version_info *it_v;
-
- gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
-
- node = cgraph_get_node (fn);
- if (node == NULL)
- return;
-
- gcc_assert (node->dispatcher_function);
-
- node_v = get_cgraph_node_version (node);
- if (node_v == NULL)
- return;
-
- /* All semantically identical versions are chained. Traverse and mark each
- one of them as used. */
- it_v = node_v->next;
- while (it_v != NULL)
- {
- mark_used (it_v->this_node->symbol.decl);
- it_v = it_v->next;
- }
-}
/* Type instantiation routines. */
@@ -7315,22 +7283,13 @@ resolve_address_of_overloaded_function (tree target_type,
fn = TREE_PURPOSE (matches);
- /* For multi-versioned functions, more than one match is just fine.
- Call decls_match to make sure they are different because they are
- versioned. */
- if (DECL_FUNCTION_VERSIONED (fn))
- {
- for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match))
- if (!DECL_FUNCTION_VERSIONED (TREE_PURPOSE (match))
- || decls_match (fn, TREE_PURPOSE (match)))
- break;
- }
- else
- {
- for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match))
- if (!decls_match (fn, TREE_PURPOSE (match)))
- break;
- }
+ /* For multi-versioned functions, more than one match is just fine and
+ decls_match will return false as they are different. */
+ for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match))
+ if (!decls_match (fn, TREE_PURPOSE (match))
+ && !targetm.target_option.function_versions
+ (fn, TREE_PURPOSE (match)))
+ break;
if (match)
{
@@ -7377,17 +7336,9 @@ resolve_address_of_overloaded_function (tree target_type,
function version at run-time. */
if (DECL_FUNCTION_VERSIONED (fn))
{
- tree dispatcher_decl = NULL;
- gcc_assert (targetm.get_function_versions_dispatcher);
- dispatcher_decl = targetm.get_function_versions_dispatcher (fn);
- if (!dispatcher_decl)
- {
- error_at (input_location, "Pointer to a multiversioned function"
- " without a default is not allowed");
- return error_mark_node;
- }
- retrofit_lang_decl (dispatcher_decl);
- fn = dispatcher_decl;
+ fn = get_function_version_dispatcher (fn);
+ if (fn == NULL)
+ return error_mark_node;
/* Mark all the versions corresponding to the dispatcher as used. */
if (!(flags & tf_conv))
mark_versions_used (fn);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index be7bc0b..7dd6679 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4971,6 +4971,8 @@ extern bool is_list_ctor (tree);
#ifdef ENABLE_CHECKING
extern void validate_conversion_obstack (void);
#endif /* ENABLE_CHECKING */
+extern void mark_versions_used (tree);
+extern tree get_function_version_dispatcher (tree);
/* in class.c */
extern tree build_vfield_ref (tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 420937e..115c567 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2307,12 +2307,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
else if (DECL_PRESERVE_P (newdecl))
DECL_PRESERVE_P (olddecl) = 1;
- /* If the olddecl is a version, so is the newdecl. */
+ /* Merge the DECL_FUNCTION_VERSIONED information. newdecl will be copied
+ to olddecl and deleted. */
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_VERSIONED (olddecl))
{
+ /* Set the flag for newdecl so that it gets copied to olddecl. */
DECL_FUNCTION_VERSIONED (newdecl) = 1;
- /* newdecl will be purged and is no longer a version. */
+ /* newdecl will be purged after copying to olddecl and is no longer
+ a version. */
delete_function_version (newdecl);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 41a91af..fec239c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2012-11-13 Sriraman Tallam <tmsriram@google.com>
+
+ * testsuite/g++.dg/mv4.C: Add require ifunc. Change error message.
+ * testsuite/g++.dg/mv5.C: Add require ifunc.
+ * testsuite/g++.dg/mv6.C: Add require ifunc.
+
2012-11-13 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/55253
diff --git a/gcc/testsuite/g++.dg/mv4.C b/gcc/testsuite/g++.dg/mv4.C
index 1a72906..ac5c548 100644
--- a/gcc/testsuite/g++.dg/mv4.C
+++ b/gcc/testsuite/g++.dg/mv4.C
@@ -3,6 +3,7 @@
and its pointer is taken. */
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
/* { dg-options "-O2 -mno-sse -mno-popcnt" } */
int __attribute__ ((target ("sse")))
@@ -18,6 +19,6 @@ foo ()
int main ()
{
- int (*p)() = &foo; /* { dg-error "Pointer to a multiversioned function without a default is not allowed" {} } */
+ int (*p)() = &foo; /* { dg-error "use of multiversioned function without a default" {} } */
return (*p)();
}
diff --git a/gcc/testsuite/g++.dg/mv5.C b/gcc/testsuite/g++.dg/mv5.C
index 33d7280..cac6d04 100644
--- a/gcc/testsuite/g++.dg/mv5.C
+++ b/gcc/testsuite/g++.dg/mv5.C
@@ -2,6 +2,7 @@
marked comdat with inline keyword. */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
/* { dg-options "-O2 -mno-popcnt" } */
diff --git a/gcc/testsuite/g++.dg/mv6.C b/gcc/testsuite/g++.dg/mv6.C
index 7e5aa29..a2cde53 100644
--- a/gcc/testsuite/g++.dg/mv6.C
+++ b/gcc/testsuite/g++.dg/mv6.C
@@ -1,6 +1,7 @@
/* Test to check if member version multiversioning works correctly. */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-require-ifunc "" } */
class Foo
{