diff options
author | Jan Hubicka <jh@suse.cz> | 2012-05-08 23:03:18 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2012-05-08 21:03:18 +0000 |
commit | 66a20fc2a7de31a268cfe5f87ffe42255d815c32 (patch) | |
tree | d628a84cad48249917d726d624c73733baf7b169 /gcc/cgraphunit.c | |
parent | aedfe0a8068e1ae6c0fcce1e3175f065b491a5c4 (diff) | |
download | gcc-66a20fc2a7de31a268cfe5f87ffe42255d815c32.zip gcc-66a20fc2a7de31a268cfe5f87ffe42255d815c32.tar.gz gcc-66a20fc2a7de31a268cfe5f87ffe42255d815c32.tar.bz2 |
cgraph.c (cgraph_call_edge_duplication_hooks): Export.
* 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.
From-SVN: r187295
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r-- | gcc/cgraphunit.c | 367 |
1 files changed, 0 insertions, 367 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index cfb9414..4c44d91 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. */ |