OSDN Git Service

2008-06-07 Xinliang David Li <davidxl@google.com>
[pf3gnuchains/gcc-fork.git] / gcc / cgraphbuild.c
index a2df564..e37ca86 100644 (file)
@@ -6,7 +6,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -36,7 +35,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    Called via walk_tree: TP is pointer to tree to be examined.  */
 
 static tree
-record_reference (tree *tp, int *walk_subtrees, void *data)
+record_reference (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
   tree t = *tp;
 
@@ -47,8 +46,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
        {
          varpool_mark_needed_node (varpool_node (t));
          if (lang_hooks.callgraph.analyze_expr)
-           return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees,
-                                                     data);
+           return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees);
        }
       break;
 
@@ -74,7 +72,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
        }
 
       if ((unsigned int) TREE_CODE (t) >= LAST_AND_UNUSED_TREE_CODE)
-       return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees, data);
+       return lang_hooks.callgraph.analyze_expr (tp, walk_subtrees);
       break;
     }
 
@@ -99,6 +97,8 @@ initialize_inline_failed (struct cgraph_node *node)
                           "considered for inlining");
       else if (!node->local.inlinable)
        e->inline_failed = N_("function not inlinable");
+      else if (CALL_STMT_CANNOT_INLINE_P (e->call_stmt))
+       e->inline_failed = N_("mismatched arguments");
       else
        e->inline_failed = N_("function not considered for inlining");
     }
@@ -115,6 +115,10 @@ build_cgraph_edges (void)
   struct pointer_set_t *visited_nodes = pointer_set_create ();
   block_stmt_iterator bsi;
   tree step;
+  int entry_freq = ENTRY_BLOCK_PTR->frequency;
+
+  if (!entry_freq)
+    entry_freq = 1;
 
   /* Create the callgraph edges and record the nodes referenced by the function.
      body.  */
@@ -127,11 +131,18 @@ build_cgraph_edges (void)
 
        if (call && (decl = get_callee_fndecl (call)))
          {
+           int i;
+           int n = call_expr_nargs (call);
+           int freq = (!bb->frequency && !entry_freq ? CGRAPH_FREQ_BASE
+                       : bb->frequency * CGRAPH_FREQ_BASE / entry_freq);
+           if (freq > CGRAPH_FREQ_MAX)
+             freq = CGRAPH_FREQ_MAX;
            cgraph_create_edge (node, cgraph_node (decl), stmt,
-                               bb->count,
+                               bb->count, freq,
                                bb->loop_depth);
-           walk_tree (&TREE_OPERAND (call, 1),
-                      record_reference, node, visited_nodes);
+           for (i = 0; i < n; i++)
+             walk_tree (&CALL_EXPR_ARG (call, i),
+                        record_reference, node, visited_nodes);
            if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
              walk_tree (&GIMPLE_STMT_OPERAND (stmt, 0),
                         record_reference, node, visited_nodes);
@@ -141,7 +152,7 @@ build_cgraph_edges (void)
       }
 
   /* Look for initializers of constant variables and private statics.  */
-  for (step = cfun->unexpanded_var_list;
+  for (step = cfun->local_decls;
        step;
        step = TREE_CHAIN (step))
     {
@@ -159,8 +170,10 @@ build_cgraph_edges (void)
   return 0;
 }
 
-struct tree_opt_pass pass_build_cgraph_edges =
+struct gimple_opt_pass pass_build_cgraph_edges =
 {
+ {
+  GIMPLE_PASS,
   NULL,                                        /* name */
   NULL,                                        /* gate */
   build_cgraph_edges,                  /* execute */
@@ -172,8 +185,8 @@ struct tree_opt_pass pass_build_cgraph_edges =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  0,                                   /* todo_flags_finish */
-  0                                    /* letter */
+  0                                    /* todo_flags_finish */
+ }
 };
 
 /* Record references to functions and other variables present in the
@@ -190,12 +203,16 @@ record_references_in_initializer (tree decl)
 /* Rebuild cgraph edges for current function node.  This needs to be run after
    passes that don't update the cgraph.  */
 
-static unsigned int
+unsigned int
 rebuild_cgraph_edges (void)
 {
   basic_block bb;
   struct cgraph_node *node = cgraph_node (current_function_decl);
   block_stmt_iterator bsi;
+  int entry_freq = ENTRY_BLOCK_PTR->frequency;
+
+  if (!entry_freq)
+    entry_freq = 1;
 
   cgraph_node_remove_callees (node);
 
@@ -209,17 +226,24 @@ rebuild_cgraph_edges (void)
        tree decl;
 
        if (call && (decl = get_callee_fndecl (call)))
-         cgraph_create_edge (node, cgraph_node (decl), stmt,
-                             bb->count,
-                             bb->loop_depth);
+         {
+           int freq = (!bb->frequency && !entry_freq ? CGRAPH_FREQ_BASE
+                       : bb->frequency * CGRAPH_FREQ_BASE / entry_freq);
+           if (freq > CGRAPH_FREQ_MAX)
+             freq = CGRAPH_FREQ_MAX;
+           cgraph_create_edge (node, cgraph_node (decl), stmt,
+                               bb->count, freq, bb->loop_depth);
+          }
       }
   initialize_inline_failed (node);
   gcc_assert (!node->global.inlined_to);
   return 0;
 }
 
-struct tree_opt_pass pass_rebuild_cgraph_edges =
+struct gimple_opt_pass pass_rebuild_cgraph_edges =
 {
+ {
+  GIMPLE_PASS,
   NULL,                                        /* name */
   NULL,                                        /* gate */
   rebuild_cgraph_edges,                        /* execute */
@@ -232,5 +256,5 @@ struct tree_opt_pass pass_rebuild_cgraph_edges =
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
   0,                                   /* todo_flags_finish */
-  0                                    /* letter */
+ }
 };