OSDN Git Service

PR middle-end/40084
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 May 2009 11:36:11 +0000 (11:36 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 10 May 2009 11:36:11 +0000 (11:36 +0000)
* cgraph.c (cgraph_update_edges_for_call_stmt_node): Take old_call argument;
rewrite.
(cgraph_update_edges_for_call_stmt): Take old_decl argument.
* cgraph.h (cgraph_update_edges_for_call_stmt): Update prototype.
* tree-inline.c (copy_bb): Set frequency correctly.
(fold_marked_statements): Update call of cgraph_update_edges_for_call_stmt.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147337 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/tree-inline.c

index 687757c..932044d 100644 (file)
@@ -1,3 +1,13 @@
+2009-05-10  Jan Hubicka  <jh@suse.cz>
+
+       PR middle-end/40084
+       * cgraph.c (cgraph_update_edges_for_call_stmt_node): Take old_call argument;
+       rewrite.
+       (cgraph_update_edges_for_call_stmt): Take old_decl argument.
+       * cgraph.h (cgraph_update_edges_for_call_stmt): Update prototype.
+       * tree-inline.c (copy_bb): Set frequency correctly.
+       (fold_marked_statements): Update call of cgraph_update_edges_for_call_stmt.
+
 2009-05-10  Joseph Myers  <joseph@codesourcery.com>
 
        * config/arc/arc.c (arc_handle_interrupt_attribute): Use %qE for
index 2f68d94..5d2cc1d 100644 (file)
@@ -898,64 +898,81 @@ cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
 
 
 /* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
-   OLD_STMT changed into NEW_STMT.  */
+   OLD_STMT changed into NEW_STMT.  OLD_CALL is gimple_call_fndecl
+   of OLD_STMT if it was previously call statement.  */
 
 static void
 cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
-                                       gimple old_stmt, gimple new_stmt)
+                                       gimple old_stmt, tree old_call, gimple new_stmt)
 {
-  tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fn (new_stmt) : 0;
-  tree old_call = (is_gimple_call (old_stmt)) ? gimple_call_fn (old_stmt) : 0;
+  tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fndecl (new_stmt) : 0;
 
+  /* We are seeing indirect calls, then there is nothing to update.  */
+  if (!new_call && !old_call)
+    return;
+  /* See if we turned indirect call into direct call or folded call to one builtin
+     into different bultin.  */
   if (old_call != new_call)
     {
       struct cgraph_edge *e = cgraph_edge (node, old_stmt);
       struct cgraph_edge *ne = NULL;
-      tree new_decl;
+      gcov_type count;
+      int frequency;
+      int loop_nest;
 
       if (e)
        {
-         gcov_type count = e->count;
-         int frequency = e->frequency;
-         int loop_nest = e->loop_nest;
-
+         /* See if the call is already there.  It might be because of indirect
+            inlining already found it.  */
+         if (new_call && e->callee->decl == new_call)
+           return;
+
+         /* Otherwise remove edge and create new one; we can't simply redirect
+            since function has changed, so inline plan and other information
+            attached to edge is invalid.  */
          cgraph_remove_edge (e);
-         if (new_call)
-           {
-             new_decl = gimple_call_fndecl (new_stmt);
-             if (new_decl)
-               {
-                 ne = cgraph_create_edge (node, cgraph_node (new_decl),
-                                          new_stmt, count, frequency,
-                                          loop_nest);
-                 gcc_assert (ne->inline_failed);
-               }
-           }
+         count = e->count;
+         frequency = e->frequency;
+         loop_nest = e->loop_nest;
+       }
+      else
+       {
+         /* We are seeing new direct call; compute profile info based on BB.  */
+         basic_block bb = gimple_bb (new_stmt);
+         count = bb->count;
+         frequency = compute_call_stmt_bb_frequency (current_function_decl,
+                                                     bb);
+         loop_nest = bb->loop_depth;
        }
-    }
-  else if (old_stmt != new_stmt)
-    {
-      struct cgraph_edge *e = cgraph_edge (node, old_stmt);
 
-      if (e)
-       cgraph_set_call_stmt (e, new_stmt);
+      if (new_call)
+       {
+         ne = cgraph_create_edge (node, cgraph_node (new_call),
+                                  new_stmt, count, frequency,
+                                  loop_nest);
+         gcc_assert (ne->inline_failed);
+       }
     }
+  /* We only updated the call stmt; update pointer in cgraph edge..  */
+  else if (old_stmt != new_stmt)
+    cgraph_set_call_stmt (cgraph_edge (node, old_stmt), new_stmt);
 }
 
 /* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
-   OLD_STMT changed into NEW_STMT.  */
+   OLD_STMT changed into NEW_STMT.  OLD_DECL is gimple_call_fndecl
+   of OLD_STMT before it was updated (updating can happen inplace).  */
 
 void
-cgraph_update_edges_for_call_stmt (gimple old_stmt, gimple new_stmt)
+cgraph_update_edges_for_call_stmt (gimple old_stmt, tree old_decl, gimple new_stmt)
 {
   struct cgraph_node *orig = cgraph_node (cfun->decl);
   struct cgraph_node *node;
 
-  cgraph_update_edges_for_call_stmt_node (orig, old_stmt, new_stmt);
+  cgraph_update_edges_for_call_stmt_node (orig, old_stmt, old_decl, new_stmt);
   if (orig->clones)
     for (node = orig->clones; node != orig;)
       {
-        cgraph_update_edges_for_call_stmt_node (node, old_stmt, new_stmt);
+        cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl, new_stmt);
        if (node->clones)
          node = node->clones;
        else if (node->next_sibling_clone)
index b94fcff..c1a1a0a 100644 (file)
@@ -385,7 +385,7 @@ void cgraph_create_edge_including_clones (struct cgraph_node *,
                                          struct cgraph_node *,
                                          gimple, gcov_type, int, int,
                                          cgraph_inline_failed_t);
-void cgraph_update_edges_for_call_stmt (gimple, gimple);
+void cgraph_update_edges_for_call_stmt (gimple, tree, gimple);
 struct cgraph_local_info *cgraph_local_info (tree);
 struct cgraph_global_info *cgraph_global_info (tree);
 struct cgraph_rtl_info *cgraph_rtl_info (tree);
index 0a38376..403b5a0 100644 (file)
@@ -1522,7 +1522,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
                gcc_assert (dest->needed || !dest->analyzed);
                if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
                  cgraph_create_edge_including_clones (id->dst_node, dest, stmt,
-                                                      bb->count, CGRAPH_FREQ_BASE,
+                                                      bb->count,
+                                                      compute_call_stmt_bb_frequency (id->dst_node->decl, bb),
                                                       bb->loop_depth,
                                                       CIF_ORIGINALLY_INDIRECT_CALL);
                else
@@ -3542,6 +3543,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
          if (pointer_set_contains (statements, gsi_stmt (gsi)))
            {
              gimple old_stmt = gsi_stmt (gsi);
+             tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
 
              if (fold_stmt (&gsi))
                {
@@ -3550,8 +3552,9 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
                  gimple new_stmt = gsi_stmt (gsi);
                  update_stmt (new_stmt);
 
-                 if (is_gimple_call (old_stmt))
-                   cgraph_update_edges_for_call_stmt (old_stmt, new_stmt);
+                 if (is_gimple_call (old_stmt)
+                     || is_gimple_call (new_stmt))
+                   cgraph_update_edges_for_call_stmt (old_stmt, old_decl, new_stmt);
 
                  if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
                    gimple_purge_dead_eh_edges (BASIC_BLOCK (first));