OSDN Git Service

* cgraph.c (cgraph_clone_node): Add redirect_callers parameter.
[pf3gnuchains/gcc-fork.git] / gcc / cgraph.c
index ea47aa3..15dd60a 100644 (file)
@@ -84,6 +84,7 @@ The callgraph:
 #include "tree-dump.h"
 #include "tree-flow.h"
 #include "value-prof.h"
+#include "except.h"
 
 static void cgraph_node_remove_callers (struct cgraph_node *node);
 static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
@@ -404,6 +405,33 @@ hash_node (const void *p)
   return (hashval_t) DECL_UID (n->decl);
 }
 
+
+/* Return the cgraph node associated with function DECL.  If none
+   exists, return NULL.  */
+
+struct cgraph_node *
+cgraph_node_for_decl (tree decl)
+{
+  struct cgraph_node *node;
+  void **slot;
+
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+
+  node = NULL;
+  if (cgraph_hash)
+    {
+      struct cgraph_node key;
+
+      key.decl = decl;
+      slot = htab_find_slot (cgraph_hash, &key, NO_INSERT);
+      if (slot && *slot)
+       node = (struct cgraph_node *) *slot;
+    }
+
+  return node;
+}
+
+
 /* Returns nonzero if P1 and P2 are equal.  */
 
 static int
@@ -493,6 +521,29 @@ cgraph_node (tree decl)
   return node;
 }
 
+/* Returns the cgraph node assigned to DECL or NULL if no cgraph node
+   is assigned.  */
+
+struct cgraph_node *
+cgraph_get_node (tree decl)
+{
+  struct cgraph_node key, *node = NULL, **slot;
+
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+
+  if (!cgraph_hash)
+    cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
+
+  key.decl = decl;
+
+  slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
+                                                NO_INSERT);
+
+  if (slot && *slot)
+    node = *slot;
+  return node;
+}
+
 /* Insert already constructed node into hashtable.  */
 
 void
@@ -654,8 +705,8 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt)
     }
 }
 
-/* Like cgraph_set_call_stmt but walk the clone tree and update all clones sharing
-   same function body.  */
+/* Like cgraph_set_call_stmt but walk the clone tree and update all
+   clones sharing the same function body.  */
 
 void
 cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
@@ -666,8 +717,10 @@ cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
 
   if (edge)
     cgraph_set_call_stmt (edge, new_stmt);
-  if (orig->clones)
-    for (node = orig->clones; node != orig;)
+
+  node = orig->clones;
+  if (node)
+    while (node != orig)
       {
        struct cgraph_edge *edge = cgraph_edge (node, old_stmt);
        if (edge)
@@ -690,29 +743,36 @@ cgraph_set_call_stmt_including_clones (struct cgraph_node *orig,
    same function body.  
    
    TODO: COUNT and LOOP_DEPTH should be properly distributed based on relative
-   frequencies of the clones.
-   */
+   frequencies of the clones.  */
 
 void
-cgraph_create_edge_including_clones (struct cgraph_node *orig, struct cgraph_node *callee,
-                                    gimple stmt, gcov_type count, int freq,
-                                    int loop_depth,
+cgraph_create_edge_including_clones (struct cgraph_node *orig,
+                                    struct cgraph_node *callee,
+                                    gimple stmt, gcov_type count,
+                                    int freq, int loop_depth,
                                     cgraph_inline_failed_t reason)
 {
   struct cgraph_node *node;
+  struct cgraph_edge *edge;
 
   if (!cgraph_edge (orig, stmt))
-     cgraph_create_edge (orig, callee, stmt,
-                        count, freq, loop_depth)->inline_failed = reason;
+    {
+      edge = cgraph_create_edge (orig, callee, stmt, count, freq, loop_depth);
+      edge->inline_failed = reason;
+    }
 
-  if (orig->clones)
-    for (node = orig->clones; node != orig;)
+  node = orig->clones;
+  if (node)
+    while (node != orig)
       {
         /* It is possible that we already constant propagated into the clone
           and turned indirect call into dirrect call.  */
         if (!cgraph_edge (node, stmt))
-         cgraph_create_edge (node, callee, stmt, count, freq,
-                             loop_depth)->inline_failed = reason;
+         {
+           edge = cgraph_create_edge (node, callee, stmt, count,
+                                      freq, loop_depth);
+           edge->inline_failed = reason;
+         }
 
        if (node->clones)
          node = node->clones;
@@ -1596,11 +1656,13 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
    by node.  */
 struct cgraph_node *
 cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq,
-                  int loop_nest, bool update_original)
+                  int loop_nest, bool update_original,
+                  VEC(cgraph_edge_p,heap) *redirect_callers)
 {
   struct cgraph_node *new_node = cgraph_create_node ();
   struct cgraph_edge *e;
   gcov_type count_scale;
+  unsigned i;
 
   new_node->decl = n->decl;
   new_node->origin = n->origin;
@@ -1631,6 +1693,14 @@ cgraph_clone_node (struct cgraph_node *n, gcov_type count, int freq,
        n->count = 0;
     }
 
+  for (i = 0; VEC_iterate (cgraph_edge_p, redirect_callers, i, e); i++)
+    {
+      /* Redirect calls to the old version node to point to its new
+        version.  */
+      cgraph_redirect_edge_callee (e, new_node);
+    }
+
+
   for (e = n->callees;e; e=e->next_callee)
     cgraph_clone_edge (e, new_node, e->call_stmt, count_scale, freq, loop_nest,
                       update_original);
@@ -1684,8 +1754,6 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
   struct cgraph_node *new_node = NULL;
   tree new_decl;
   struct cgraph_node key, **slot;
-  unsigned i;
-  struct cgraph_edge *e;
 
   gcc_assert  (tree_versionable_function_p (old_decl));
 
@@ -1702,7 +1770,8 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
   SET_DECL_RTL (new_decl, NULL);
 
   new_node = cgraph_clone_node (old_node, old_node->count,
-                               CGRAPH_FREQ_BASE, 0, false);
+                               CGRAPH_FREQ_BASE, 0, false,
+                               redirect_callers);
   new_node->decl = new_decl;
   /* Update the properties.
      Make clone visible only within this translation unit.  Make sure
@@ -1761,13 +1830,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
       gcc_assert (!*aslot);
       *aslot = new_node;
     }
-   for (i = 0; VEC_iterate (cgraph_edge_p, redirect_callers, i, e); i++)
-     {
-       /* Redirect calls to the old version node to point to its new
-         version.  */
-       cgraph_redirect_edge_callee (e, new_node);
-     }
-  
+
   return new_node;
 }
 
@@ -1861,9 +1924,6 @@ cgraph_add_new_function (tree fndecl, bool lowered)
            push_cfun (DECL_STRUCT_FUNCTION (fndecl));
            current_function_decl = fndecl;
            gimple_register_cfg_hooks ();
-           /* C++ Thunks are emitted late via this function, gimplify them.  */
-           if (!gimple_body (fndecl))
-             gimplify_function_tree (fndecl);
            tree_lowering_passes (fndecl);
            bitmap_obstack_initialize (NULL);
            if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
@@ -1897,6 +1957,12 @@ cgraph_add_new_function (tree fndecl, bool lowered)
        current_function_decl = NULL;
        break;
     }
+
+  /* Set a personality if required and we already passed EH lowering.  */
+  if (lowered
+      && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl))
+         == eh_personality_lang))
+    DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
 }
 
 /* Return true if NODE can be made local for API change.