cgraph.c (insert_new_cgraph_node_version): Use cgraph_get_node instead of cgraph_get_...
authorSriraman Tallam <tmsriram@google.com>
Tue, 13 Nov 2012 21:56:30 +0000 (21:56 +0000)
committerSriraman Tallam <tmsriram@gcc.gnu.org>
Tue, 13 Nov 2012 21:56:30 +0000 (21:56 +0000)
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

12 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/config/i386/i386.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/mv4.C
gcc/testsuite/g++.dg/mv5.C
gcc/testsuite/g++.dg/mv6.C

index 32b0102ac630a4161a98a7773c0d3f6fdc680c31..4966b5dc1bc15d617677ea914f68a094c2b3543f 100644 (file)
@@ -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
index 556eaff29d429e84931f0d340daee40c495fd5ac..1969576d00f079e1924a5327b82c8b289ca2f9b5 100644 (file)
@@ -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)
index 3af1cf8a6784b0f2aab096ddac543689afcce2bb..de94d4b0f7cbe9a5a442550422629dfc315841a4 100644 (file)
@@ -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;
 }
 
index 0f23cbca9b7c4ba9238e00862787f07adcf8939e..8d12568a6758ca14fbc1fd70be9686934051e8e5 100644 (file)
@@ -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
index 4373bce69313f276dce2775e6abbc7a00976b481..bbeea8526291d9f1322615f8fc219fc3cf09a596 100644 (file)
@@ -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;
index d3d9aed7ff786145f39ddeaaec919679cc363f3f..0665e90f5a0bdba1e3588904a06d095e3aeeae67 100644 (file)
@@ -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;
-    }
-}
 \f
 /* 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);
index be7bc0b0269c74e9ef1b00af5de4e4c15f633537..7dd6679868c715c0ceccfe9ba6d822c0fdaf1e93 100644 (file)
@@ -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);
index 420937e2ad08f2d1602f9b7b1903efc35d945fca..115c567d6ddb30a6fcc0564b75d582d97f5640b9 100644 (file)
@@ -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);
     }
 
index 41a91af7de52b2794cdf2abd777bfc2f338266b2..fec239c5ecba1cb650d91e7c4237b97931f42b7b 100644 (file)
@@ -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
index 1a7290643acd612039140dc0ac4efe3943101dd7..ac5c5481c665835d8313350a5b93604d94bc32ba 100644 (file)
@@ -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)();
 }
index 33d72804bcfc636318bcfbbbf32e5bbf8f369bca..cac6d04e2e3d77d5d71e3eb4ac47613cf3afc713 100644 (file)
@@ -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" } */
 
 
index 7e5aa29d0bb0e39a4c4e1f9457b4f337cf9e70d3..a2cde53362b570f9282b512d63a8e841a8386b72 100644 (file)
@@ -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
 {