#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);
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
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
}
}
-/* 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,
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)
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;
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;
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);
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));
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
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;
}
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)))
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.