diff options
author | Razya Ladelsky <razya@il.ibm.com> | 2005-08-01 07:42:09 +0000 |
---|---|---|
committer | Razya Ladelsky <razya@il.ibm.com> | 2005-08-01 07:42:09 +0000 |
commit | 4a90571c1b5899eb0f4a907b924f1520c558d75a (patch) | |
tree | 85e0f4769a0ce6965e726bad05916930c2abcd04 /gcc/cgraphunit.c | |
parent | 9dec17f3d4d6c106d40d2fb193df6b76ae5c95fa (diff) |
* Makefile.in: Add ipcp.c, ipa-prop.h, ipa-prop.c. Remove integrate.h
dependency from tree-inline.o.
Add ipa-prop.h dependency to tree-inline.o and cgraphunit.o.
* common.opt: Add ipa-cp flag.
* timevar.def: Add IPCP optimization.
* tree-optimize.c (init_tree_optimization_passes): Schedule
pass_ipa_cp.
* tree-pass.h (pass_ipa_cp): Declare.
* cgraph.h (update_call_expr, cgraph_copy_node_for_versioning,
cgraph_function_versioning): New declarations.
* cgraphunit.c: Add include to ipa-prop.h.
(update_call_expr, cgraph_copy_node_for_versioning,
cgraph_function_versioning): New functions.
* integrate.c (copy_decl_for_inlining): Remove.
* tree-inline.c: Remove include to integrate.h, Add include ipa-prop.h.
(struct inline_data): Add versioning_p, ipa_info, new fields.
(remap_decl, mark_local_for_remap_r, setup_one_parameter,
declare_return_variable): Replace calls to copy_decl_for_inlining with
copy_decl_for_dup.
(copy_body_r, copy_bb, copy_cfg_body, copy_tree_r, inlining_p): Add
versioning support.
(copy_decl_for_dup): Rename from copy_decl_for_inlining.
Add argument VERSIONING.
(copy_arguments_for_versioning, copy_static_chain,
function_versionable_p, tree_versionable_function_p,
tree_function_versioning, replace_ref_tree): New functions.
* tree-inline.h: Include varray.h.
(tree_versionable_function_p, tree_function_versioning,
tree copy_decl_for_dup): New declarations.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@102625 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r-- | gcc/cgraphunit.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index f8f864c11f8..a10859dd0bc 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -162,6 +162,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "c-common.h" #include "intl.h" #include "function.h" +#include "ipa-prop.h" #include "tree-gimple.h" #include "tree-pass.h" #include "output.h" @@ -1368,3 +1369,134 @@ 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); + for (e = new_version->callers; e; e = e->next_caller) + /* Update the call expr on the edges + to call the new version. */ + TREE_OPERAND (TREE_OPERAND (get_call_expr_in (e->call_stmt), 0), 0) = new_version->decl; +} + + +/* 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. */ + +static struct cgraph_node * +cgraph_copy_node_for_versioning (struct cgraph_node *old_version, + tree new_decl, varray_type redirect_callers) + { + struct cgraph_node *new_version; + struct cgraph_edge *e, *new_e; + struct cgraph_edge *next_callee; + unsigned i; + + gcc_assert (old_version); + + new_version = cgraph_node (new_decl); + + new_version->analyzed = true; + new_version->local = old_version->local; + new_version->global = old_version->global; + new_version->rtl = new_version->rtl; + new_version->reachable = true; + new_version->count = old_version->count; + + /* Clone the old node callees. Recursive calls are + also cloned. */ + for (e = old_version->callees;e; e=e->next_callee) + { + new_e = cgraph_clone_edge (e, new_version, e->call_stmt, 0, e->loop_nest, true); + new_e->count = e->count; + } + /* Fix recursive calls. + If OLD_VERSION has a recursive call after the + previous edge cloning, the new version will have an edge + pointing to the old version, which is wrong; + Redirect it to point to the new version. */ + for (e = new_version->callees ; e; e = next_callee) + { + next_callee = e->next_callee; + if (e->callee == old_version) + cgraph_redirect_edge_callee (e, new_version); + + if (!next_callee) + break; + } + if (redirect_callers) + for (i = 0; i < VARRAY_ACTIVE_SIZE (redirect_callers); i++) + { + e = VARRAY_GENERIC_PTR (redirect_callers, i); + /* Redirect calls to the old version node + to point to it's new version. */ + cgraph_redirect_edge_callee (e, 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. + It returns the new version's cgraph node. */ + +struct cgraph_node * +cgraph_function_versioning (struct cgraph_node *old_version_node, + varray_type redirect_callers, + varray_type tree_map) +{ + tree old_decl = old_version_node->decl; + struct cgraph_node *new_version_node = NULL; + tree new_decl; + + if (!tree_versionable_function_p (old_decl)) + return NULL; + + /* Make a new FUNCTION_DECL tree node for the + new version. */ + new_decl = copy_node (old_decl); + + /* 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); + + /* Copy the OLD_VERSION_NODE function tree to the new version. */ + tree_function_versioning (old_decl, new_decl, tree_map); + /* Update the call_expr on the edges to call the new version node. */ + update_call_expr (new_version_node); + + /* Update the new version's properties. + Make The new version visible only within this translation unit. + ??? We cannot use COMDAT linkage because there is no + ABI support for this. */ + DECL_EXTERNAL (new_version_node->decl) = 0; + DECL_ONE_ONLY (new_version_node->decl) = 0; + TREE_PUBLIC (new_version_node->decl) = 0; + DECL_COMDAT (new_version_node->decl) = 0; + new_version_node->local.externally_visible = 0; + new_version_node->local.local = 1; + new_version_node->lowered = true; + return new_version_node; +} |