aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-08 21:03:18 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-08 21:03:18 +0000
commitf41db742626eadae691bc51edadd9a491b8ae422 (patch)
treed628a84cad48249917d726d624c73733baf7b169 /gcc/cgraphunit.c
parentd44bd47ca2b25aacbf336063dd04ec033613598c (diff)
* cgraph.c (cgraph_call_edge_duplication_hooks): Export.
(cgraph_create_node_1): Rename to ... (cgraph_create_empty_node): ... this one; export. (cgraph_create_node): Update. (cgraph_set_call_stmt_including_clones): Move to cgraphclones.c (cgraph_create_edge_including_clones): Likewise. (cgraph_find_replacement_node): Likewise. (cgraph_clone_edge): Likewise. (cgraph_clone_node): Likewise. (clone_function_name): Likewise. (cgraph_create_virtual_clone): Likewise. (cgraph_remove_node_and_inline_clones): Likewise. (cgraph_redirect_edge_call_stmt_to_callee): Move here from cgraphunit.c * cgraph.h: Reorder declarations so they match file of origin. (cgraph_create_empty_node): Declare. * cgraphunit.c (update_call_expr): Move to cgraphclones.c (cgraph_copy_node_for_versioning): Likewise. (cgraph_function_versioning): Likewise. (cgraph_materialize_clone): Likewise. (cgraph_redirect_edge_call_stmt_to_callee): Likewise. (cgraph_materialize_all_clones): Likewise. * cgraphclones.c: New file. * Makefile.in: Update for cgraphclones. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187295 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c367
1 files changed, 0 insertions, 367 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index cfb94149ed4..4c44d91af51 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1917,373 +1917,6 @@ init_cgraph (void)
cgraph_dump_file = dump_begin (TDI_cgraph, NULL);
}
-/* The edges representing the callers of the NEW_VERSION node were
- fixed by cgraph_function_versioning (), now the call_expr in their
- respective tree code should be updated to call the NEW_VERSION. */
-
-static void
-update_call_expr (struct cgraph_node *new_version)
-{
- struct cgraph_edge *e;
-
- gcc_assert (new_version);
-
- /* Update the call expr on the edges to call the new version. */
- for (e = new_version->callers; e; e = e->next_caller)
- {
- struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->symbol.decl);
- gimple_call_set_fndecl (e->call_stmt, new_version->symbol.decl);
- maybe_clean_eh_stmt_fn (inner_function, e->call_stmt);
- }
-}
-
-
-/* Create a new cgraph node which is the new version of
- OLD_VERSION node. REDIRECT_CALLERS holds the callers
- edges which should be redirected to point to
- NEW_VERSION. ALL the callees edges of OLD_VERSION
- are cloned to the new version node. Return the new
- version node.
-
- If non-NULL BLOCK_TO_COPY determine what basic blocks
- was copied to prevent duplications of calls that are dead
- in the clone. */
-
-struct cgraph_node *
-cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
- tree new_decl,
- VEC(cgraph_edge_p,heap) *redirect_callers,
- bitmap bbs_to_copy)
- {
- struct cgraph_node *new_version;
- struct cgraph_edge *e;
- unsigned i;
-
- gcc_assert (old_version);
-
- new_version = cgraph_create_node (new_decl);
-
- new_version->analyzed = old_version->analyzed;
- new_version->local = old_version->local;
- new_version->symbol.externally_visible = false;
- new_version->local.local = old_version->analyzed;
- new_version->global = old_version->global;
- new_version->rtl = old_version->rtl;
- new_version->count = old_version->count;
-
- for (e = old_version->callees; e; e=e->next_callee)
- if (!bbs_to_copy
- || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
- cgraph_clone_edge (e, new_version, e->call_stmt,
- e->lto_stmt_uid, REG_BR_PROB_BASE,
- CGRAPH_FREQ_BASE,
- true);
- for (e = old_version->indirect_calls; e; e=e->next_callee)
- if (!bbs_to_copy
- || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
- cgraph_clone_edge (e, new_version, e->call_stmt,
- e->lto_stmt_uid, REG_BR_PROB_BASE,
- CGRAPH_FREQ_BASE,
- true);
- FOR_EACH_VEC_ELT (cgraph_edge_p, redirect_callers, i, e)
- {
- /* Redirect calls to the old version node to point to its new
- version. */
- cgraph_redirect_edge_callee (e, new_version);
- }
-
- cgraph_call_node_duplication_hooks (old_version, new_version);
-
- return new_version;
- }
-
- /* Perform function versioning.
- Function versioning includes copying of the tree and
- a callgraph update (creating a new cgraph node and updating
- its callees and callers).
-
- REDIRECT_CALLERS varray includes the edges to be redirected
- to the new version.
-
- TREE_MAP is a mapping of tree nodes we want to replace with
- new ones (according to results of prior analysis).
- OLD_VERSION_NODE is the node that is versioned.
-
- If non-NULL ARGS_TO_SKIP determine function parameters to remove
- from new version.
- If SKIP_RETURN is true, the new version will return void.
- If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
- If non_NULL NEW_ENTRY determine new entry BB of the clone.
-
- Return the new version's cgraph node. */
-
-struct cgraph_node *
-cgraph_function_versioning (struct cgraph_node *old_version_node,
- VEC(cgraph_edge_p,heap) *redirect_callers,
- VEC (ipa_replace_map_p,gc)* tree_map,
- bitmap args_to_skip,
- bool skip_return,
- bitmap bbs_to_copy,
- basic_block new_entry_block,
- const char *clone_name)
-{
- tree old_decl = old_version_node->symbol.decl;
- struct cgraph_node *new_version_node = NULL;
- tree new_decl;
-
- if (!tree_versionable_function_p (old_decl))
- return NULL;
-
- gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
-
- /* Make a new FUNCTION_DECL tree node for the new version. */
- if (!args_to_skip && !skip_return)
- new_decl = copy_node (old_decl);
- else
- new_decl
- = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
-
- /* Generate a new name for the new version. */
- DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
- SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
- SET_DECL_RTL (new_decl, NULL);
-
- /* When the old decl was a con-/destructor make sure the clone isn't. */
- DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
- DECL_STATIC_DESTRUCTOR(new_decl) = 0;
-
- /* Create the new version's call-graph node.
- and update the edges of the new node. */
- new_version_node =
- cgraph_copy_node_for_versioning (old_version_node, new_decl,
- redirect_callers, bbs_to_copy);
-
- /* Copy the OLD_VERSION_NODE function tree to the new version. */
- tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
- skip_return, bbs_to_copy, new_entry_block);
-
- /* Update the new version's properties.
- Make The new version visible only within this translation unit. Make sure
- that is not weak also.
- ??? We cannot use COMDAT linkage because there is no
- ABI support for this. */
- symtab_make_decl_local (new_version_node->symbol.decl);
- DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
- new_version_node->symbol.externally_visible = 0;
- new_version_node->local.local = 1;
- new_version_node->lowered = true;
-
- /* Update the call_expr on the edges to call the new version node. */
- update_call_expr (new_version_node);
-
- cgraph_call_function_insertion_hooks (new_version_node);
- return new_version_node;
-}
-
-/* Given virtual clone, turn it into actual clone. */
-static void
-cgraph_materialize_clone (struct cgraph_node *node)
-{
- bitmap_obstack_initialize (NULL);
- node->former_clone_of = node->clone_of->symbol.decl;
- if (node->clone_of->former_clone_of)
- node->former_clone_of = node->clone_of->former_clone_of;
- /* Copy the OLD_VERSION_NODE function tree to the new version. */
- tree_function_versioning (node->clone_of->symbol.decl, node->symbol.decl,
- node->clone.tree_map, true,
- node->clone.args_to_skip, false,
- NULL, NULL);
- if (cgraph_dump_file)
- {
- dump_function_to_file (node->clone_of->symbol.decl, cgraph_dump_file, dump_flags);
- dump_function_to_file (node->symbol.decl, cgraph_dump_file, dump_flags);
- }
-
- /* Function is no longer clone. */
- if (node->next_sibling_clone)
- node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
- if (node->prev_sibling_clone)
- node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
- else
- 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_release_function_body (node->clone_of);
- cgraph_node_remove_callees (node->clone_of);
- ipa_remove_all_references (&node->clone_of->symbol.ref_list);
- }
- node->clone_of = NULL;
- bitmap_obstack_release (NULL);
-}
-
-/* If necessary, change the function declaration in the call statement
- associated with E so that it corresponds to the edge callee. */
-
-gimple
-cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
-{
- tree decl = gimple_call_fndecl (e->call_stmt);
- gimple new_stmt;
- gimple_stmt_iterator gsi;
-#ifdef ENABLE_CHECKING
- struct cgraph_node *node;
-#endif
-
- if (e->indirect_unknown_callee
- || decl == e->callee->symbol.decl)
- return e->call_stmt;
-
-#ifdef ENABLE_CHECKING
- if (decl)
- {
- node = cgraph_get_node (decl);
- gcc_assert (!node || !node->clone.combined_args_to_skip);
- }
-#endif
-
- if (cgraph_dump_file)
- {
- fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ",
- xstrdup (cgraph_node_name (e->caller)), e->caller->uid,
- xstrdup (cgraph_node_name (e->callee)), e->callee->uid);
- print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
- if (e->callee->clone.combined_args_to_skip)
- {
- fprintf (cgraph_dump_file, " combined args to skip: ");
- dump_bitmap (cgraph_dump_file,
- e->callee->clone.combined_args_to_skip);
- }
- }
-
- if (e->callee->clone.combined_args_to_skip)
- {
- int lp_nr;
-
- new_stmt
- = gimple_call_copy_skip_args (e->call_stmt,
- e->callee->clone.combined_args_to_skip);
- gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
-
- if (gimple_vdef (new_stmt)
- && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
-
- gsi = gsi_for_stmt (e->call_stmt);
- gsi_replace (&gsi, new_stmt, false);
- /* We need to defer cleaning EH info on the new statement to
- fixup-cfg. We may not have dominator information at this point
- and thus would end up with unreachable blocks and have no way
- to communicate that we need to run CFG cleanup then. */
- lp_nr = lookup_stmt_eh_lp (e->call_stmt);
- if (lp_nr != 0)
- {
- remove_stmt_from_eh_lp (e->call_stmt);
- add_stmt_to_eh_lp (new_stmt, lp_nr);
- }
- }
- else
- {
- new_stmt = e->call_stmt;
- gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl);
- update_stmt (new_stmt);
- }
-
- cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt);
-
- if (cgraph_dump_file)
- {
- fprintf (cgraph_dump_file, " updated to:");
- print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
- }
- return new_stmt;
-}
-
-/* Once all functions from compilation unit are in memory, produce all clones
- and update all calls. We might also do this on demand if we don't want to
- bring all functions to memory prior compilation, but current WHOPR
- implementation does that and it is is bit easier to keep everything right in
- this order. */
-static void
-cgraph_materialize_all_clones (void)
-{
- struct cgraph_node *node;
- bool stabilized = false;
-
- if (cgraph_dump_file)
- fprintf (cgraph_dump_file, "Materializing clones\n");
-#ifdef ENABLE_CHECKING
- verify_cgraph ();
-#endif
-
- /* We can also do topological order, but number of iterations should be
- bounded by number of IPA passes since single IPA pass is probably not
- going to create clones of clones it created itself. */
- while (!stabilized)
- {
- stabilized = true;
- FOR_EACH_FUNCTION (node)
- {
- if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl
- && !gimple_has_body_p (node->symbol.decl))
- {
- if (gimple_has_body_p (node->clone_of->symbol.decl))
- {
- if (cgraph_dump_file)
- {
- fprintf (cgraph_dump_file, "cloning %s to %s\n",
- xstrdup (cgraph_node_name (node->clone_of)),
- xstrdup (cgraph_node_name (node)));
- if (node->clone.tree_map)
- {
- unsigned int i;
- fprintf (cgraph_dump_file, " replace map: ");
- for (i = 0; i < VEC_length (ipa_replace_map_p,
- node->clone.tree_map);
- i++)
- {
- struct ipa_replace_map *replace_info;
- replace_info = VEC_index (ipa_replace_map_p,
- node->clone.tree_map,
- i);
- print_generic_expr (cgraph_dump_file, replace_info->old_tree, 0);
- fprintf (cgraph_dump_file, " -> ");
- print_generic_expr (cgraph_dump_file, replace_info->new_tree, 0);
- fprintf (cgraph_dump_file, "%s%s;",
- replace_info->replace_p ? "(replace)":"",
- replace_info->ref_p ? "(ref)":"");
- }
- fprintf (cgraph_dump_file, "\n");
- }
- if (node->clone.args_to_skip)
- {
- fprintf (cgraph_dump_file, " args_to_skip: ");
- dump_bitmap (cgraph_dump_file, node->clone.args_to_skip);
- }
- if (node->clone.args_to_skip)
- {
- fprintf (cgraph_dump_file, " combined_args_to_skip:");
- dump_bitmap (cgraph_dump_file, node->clone.combined_args_to_skip);
- }
- }
- cgraph_materialize_clone (node);
- stabilized = false;
- }
- }
- }
- }
- FOR_EACH_FUNCTION (node)
- if (!node->analyzed && node->callees)
- cgraph_node_remove_callees (node);
- if (cgraph_dump_file)
- fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
-#ifdef ENABLE_CHECKING
- verify_cgraph ();
-#endif
- cgraph_remove_unreachable_nodes (false, cgraph_dump_file);
-}
-
/* Perform simple optimizations based on callgraph. */