cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
authorJan Hubicka <jh@suse.cz>
Thu, 5 Sep 2013 23:06:10 +0000 (01:06 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 5 Sep 2013 23:06:10 +0000 (23:06 +0000)
* cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
(analyze_functions): ... here.

From-SVN: r202299

gcc/ChangeLog
gcc/cgraphunit.c

index dd93373df5497be078d0c445c26db3496b346676..9e56b4a947901497d2f28a00ca2b2f7074bd05eb 100644 (file)
@@ -1,3 +1,8 @@
+2013-09-04  Jan Hubicka  <jh@suse.cz>
+
+       * cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
+       (analyze_functions): ... here.
+
 2013-09-04  Jan Hubicka  <jh@suse.cz>
 
        PR middle-end/58201
index 125fb3b587e36d223bf5f98bc270825c19e92555..08e0ff277f2f7f14aa160199a0d68f6ade9704fc 100644 (file)
@@ -821,6 +821,76 @@ varpool_finalize_decl (tree decl)
     varpool_assemble_decl (node);
 }
 
+/* EDGE is an polymorphic call.  Mark all possible targets as reachable
+   and if there is only one target, perform trivial devirtualization. 
+   REACHABLE_CALL_TARGETS collects target lists we already walked to
+   avoid udplicate work.  */
+
+static void
+walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
+                              struct cgraph_edge *edge)
+{
+  unsigned int i;
+  void *cache_token;
+  bool final;
+  vec <cgraph_node *>targets
+    = possible_polymorphic_call_targets
+       (edge, &final, &cache_token);
+
+  if (!pointer_set_insert (reachable_call_targets,
+                          cache_token))
+    {
+      if (cgraph_dump_file)
+       dump_possible_polymorphic_call_targets 
+         (cgraph_dump_file, edge);
+
+      for (i = 0; i < targets.length(); i++)
+       {
+         /* Do not bother to mark virtual methods in anonymous namespace;
+            either we will find use of virtual table defining it, or it is
+            unused.  */
+         if (targets[i]->symbol.definition
+             && TREE_CODE
+                 (TREE_TYPE (targets[i]->symbol.decl))
+                  == METHOD_TYPE
+             && !type_in_anonymous_namespace_p
+                  (method_class_type
+                    (TREE_TYPE (targets[i]->symbol.decl))))
+         enqueue_node ((symtab_node) targets[i]);
+       }
+    }
+
+  /* Very trivial devirtualization; when the type is
+     final or anonymous (so we know all its derivation)
+     and there is only one possible virtual call target,
+     make the edge direct.  */
+  if (final)
+    {
+      gcc_assert (targets.length());
+      if (targets.length() == 1)
+       {
+         if (cgraph_dump_file)
+           {
+             fprintf (cgraph_dump_file,
+                      "Devirtualizing call: ");
+             print_gimple_stmt (cgraph_dump_file,
+                                edge->call_stmt, 0,
+                                TDF_SLIM);
+           }
+         cgraph_make_edge_direct (edge, targets[0]);
+         cgraph_redirect_edge_call_stmt_to_callee (edge);
+         if (cgraph_dump_file)
+           {
+             fprintf (cgraph_dump_file,
+                      "Devirtualized as: ");
+             print_gimple_stmt (cgraph_dump_file,
+                                edge->call_stmt, 0,
+                                TDF_SLIM);
+           }
+       }
+    }
+}
+
 
 /* Discover all functions and variables that are trivially needed, analyze
    them as well as all functions and variables referred by them  */
@@ -923,71 +993,13 @@ analyze_functions (void)
              if (optimize && flag_devirtualize)
                {
                  struct cgraph_edge *next;
-                 for (edge = cnode->indirect_calls; edge; edge = next)
+
+                 for (edge = cnode->indirect_calls; edge; edge = next)
                    {
                      next = edge->next_callee;
                      if (edge->indirect_info->polymorphic)
-                       {
-                         unsigned int i;
-                         void *cache_token;
-                         bool final;
-                         vec <cgraph_node *>targets
-                           = possible_polymorphic_call_targets
-                               (edge, &final, &cache_token);
-
-                         if (!pointer_set_insert (reachable_call_targets,
-                                                  cache_token))
-                           {
-                             if (cgraph_dump_file)
-                               dump_possible_polymorphic_call_targets 
-                                 (cgraph_dump_file, edge);
-
-                             for (i = 0; i < targets.length(); i++)
-                               {
-                                 /* Do not bother to mark virtual methods in anonymous namespace;
-                                    either we will find use of virtual table defining it, or it is
-                                    unused.  */
-                                 if (targets[i]->symbol.definition
-                                     && TREE_CODE
-                                         (TREE_TYPE (targets[i]->symbol.decl))
-                                          == METHOD_TYPE
-                                     && !type_in_anonymous_namespace_p
-                                          (method_class_type
-                                            (TREE_TYPE (targets[i]->symbol.decl))))
-                                 enqueue_node ((symtab_node) targets[i]);
-                               }
-                           }
-
-                         /* Very trivial devirtualization; when the type is
-                            final or anonymous (so we know all its derivation)
-                            and there is only one possible virtual call target,
-                            make the edge direct.  */
-                         if (final)
-                           {
-                             gcc_assert (targets.length());
-                             if (targets.length() == 1)
-                               {
-                                 if (cgraph_dump_file)
-                                   {
-                                     fprintf (cgraph_dump_file,
-                                              "Devirtualizing call: ");
-                                     print_gimple_stmt (cgraph_dump_file,
-                                                        edge->call_stmt, 0,
-                                                        TDF_SLIM);
-                                   }
-                                 cgraph_make_edge_direct (edge, targets[0]);
-                                 cgraph_redirect_edge_call_stmt_to_callee (edge);
-                                 if (cgraph_dump_file)
-                                   {
-                                     fprintf (cgraph_dump_file,
-                                              "Devirtualized as: ");
-                                     print_gimple_stmt (cgraph_dump_file,
-                                                        edge->call_stmt, 0,
-                                                        TDF_SLIM);
-                                   }
-                               }
-                           }
-                       }
+                       walk_polymorphic_call_targets (reachable_call_targets,
+                                                      edge);
                    }
                }