OSDN Git Service

2009-11-19 Janus Weil <janus@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / cgraphunit.c
index 7b8b738..e934b3d 100644 (file)
@@ -620,6 +620,18 @@ verify_cgraph_node (struct cgraph_node *node)
          error ("caller edge frequency is too large");
          error_found = true;
        }
+      if (gimple_has_body_p (e->caller->decl)
+          && !e->caller->global.inlined_to
+          && (e->frequency
+             != compute_call_stmt_bb_frequency (e->caller->decl,
+                                                gimple_bb (e->call_stmt))))
+       {
+         error ("caller edge frequency %i does not match BB freqency %i",
+                e->frequency,
+                compute_call_stmt_bb_frequency (e->caller->decl,
+                                                gimple_bb (e->call_stmt)));
+         error_found = true;
+       }
       if (!e->inline_failed)
        {
          if (node->global.inlined_to
@@ -884,6 +896,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
       if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
        {
          mark_decl_referenced (decl);
+         vnode->force_output = true;
          if (vnode->finalized)
            varpool_mark_needed_node (vnode);
        }
@@ -1027,7 +1040,7 @@ cgraph_analyze_functions (void)
 static void
 cgraph_emit_thunks (void)
 {
-  struct cgraph_node *n;
+  struct cgraph_node *n, *alias;
 
   for (n = cgraph_nodes; n; n = n->next)
     {
@@ -1040,7 +1053,12 @@ cgraph_emit_thunks (void)
         cgraph_mark_functions_to_output in cgraph_optimize).  */
       if (n->reachable
          && !DECL_EXTERNAL (n->decl))
-       lang_hooks.callgraph.emit_associated_thunks (n->decl);
+       {
+         lang_hooks.callgraph.emit_associated_thunks (n->decl);
+         for (alias = n->same_body; alias; alias = alias->next)
+           if (!DECL_EXTERNAL (alias->decl))
+             lang_hooks.callgraph.emit_associated_thunks (alias->decl);
+       }
     }
 }
 
@@ -1162,6 +1180,14 @@ cgraph_expand_function (struct cgraph_node *node)
   /* Make sure that BE didn't give up on compiling.  */
   gcc_assert (TREE_ASM_WRITTEN (decl));
   current_function_decl = NULL;
+  if (node->same_body)
+    {
+      struct cgraph_node *alias;
+      bool saved_alias = node->alias;
+      for (alias = node->same_body; alias; alias = alias->next)
+       assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl));
+      node->alias = saved_alias;
+    }
   gcc_assert (!cgraph_preserve_function_body_p (decl));
   cgraph_release_function_body (node);
   /* Eliminate all call edges.  This is important so the GIMPLE_CALL no longer
@@ -1422,7 +1448,10 @@ cgraph_optimize (void)
 
   /* Do nothing else if any IPA pass found errors.  */
   if (errorcount || sorrycount)
-    return;
+    {
+      timevar_pop (TV_CGRAPHOPT);
+      return;
+    }
 
   /* This pass remove bodies of extern inline functions we never inlined.
      Do this later so other IPA passes see what is really going on.  */
@@ -1773,8 +1802,8 @@ save_inline_function_body (struct cgraph_node *node)
   TREE_PUBLIC (first_clone->decl) = 0;
   DECL_COMDAT (first_clone->decl) = 0;
   VEC_free (ipa_opt_pass, heap,
-            DECL_STRUCT_FUNCTION (first_clone->decl)->ipa_transforms_to_apply);
-  DECL_STRUCT_FUNCTION (first_clone->decl)->ipa_transforms_to_apply = NULL;
+            first_clone->ipa_transforms_to_apply);
+  first_clone->ipa_transforms_to_apply = NULL;
 
 #ifdef ENABLE_CHECKING
   verify_cgraph_node (first_clone);
@@ -1806,6 +1835,8 @@ cgraph_materialize_clone (struct cgraph_node *node)
     node->clone_of->clones = node->next_sibling_clone;
   node->next_sibling_clone = NULL;
   node->prev_sibling_clone = NULL;
+  if (!node->clone_of->analyzed && !node->clone_of->clones)
+    cgraph_remove_node (node->clone_of);
   node->clone_of = NULL;
   bitmap_obstack_release (NULL);
 }
@@ -1906,7 +1937,22 @@ cgraph_materialize_all_clones (void)
              {
                gimple new_stmt;
                gimple_stmt_iterator gsi;
-               
+
+               if (e->callee->same_body)
+                 {
+                   struct cgraph_node *alias;
+
+                   for (alias = e->callee->same_body;
+                        alias;
+                        alias = alias->next)
+                     if (decl == alias->decl)
+                       break;
+                   /* Don't update call from same body alias to the real
+                      function.  */
+                   if (alias)
+                     continue;
+                 }
+
                if (cgraph_dump_file)
                  {
                    fprintf (cgraph_dump_file, "updating call of %s in %s:",