diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-29 11:31:40 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-29 11:31:40 +0000 |
commit | 5afe38fe4c359548ac69898c28c2511a6f341d96 (patch) | |
tree | d057c22936747f4672fd349b48d59df2628ab832 /gcc/ipa-cp.c | |
parent | 0bfd8d5c472a9e897b1f5636d4bc1a69a0fe6251 (diff) | |
download | gcc-5afe38fe4c359548ac69898c28c2511a6f341d96.tar.gz |
* tree.c (build_function_type_skip_args, build_function_decl_skip_args):
New functions.
* tree.h (build_function_type_skip_args, build_function_decl_skip_args):
Declare.
* gimple.c (giple_copy_call_skip_args): New function.
(giple_copy_call_skip_args): Declare.
* cgraph.h (cgraph_function_versioning): Add skip_args arugmnet
* ipa-cp.c (ipcp_node_not_modifiable_p): Rename to ...
(ipcp_node_modifiable_p): ... this one; use tree_versionable_function_p.
(ipcp_create_replace_map): Improve debug output.
(ipcp_need_redirect_p): Return false when not clonning.
(ipcp_update_callgraph): Skip args.
(ipcp_insert_stage): UPdate call of !ipcp_node_modifiable_p;
skip args.
* cgraphunit.c (cgraph_function_versioning): Add skip_args argument.
(save_inline_function_body): Update call of tree_function_versioning.
* ipa-prop.c (ipa_edge_removal_hook): Do not ICE on unanalyzed nodes.
* tree-inline.c (copy_arguments_for_versioning): Add skip_args argument.
(tree_function_versioning): Likewise.
* tree-inline.h (tree_function_versioning): Update prototype.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139761 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-cp.c')
-rw-r--r-- | gcc/ipa-cp.c | 107 |
1 files changed, 79 insertions, 28 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index ca7e231904b..4b0a5f2c2db 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -560,12 +560,11 @@ ipcp_iterate_stage (void) /* Check conditions to forbid constant insertion to function described by NODE. */ static inline bool -ipcp_node_not_modifiable_p (struct cgraph_node *node) +ipcp_node_modifiable_p (struct cgraph_node *node) { - /* ??? Handle pending sizes case. */ - if (DECL_UNINLINABLE (node->decl)) - return true; - return false; + /* Once we will be able to do in-place replacement, we can be more + lax here. */ + return tree_versionable_function_p (node->decl); } /* Print count scale data structures. */ @@ -745,9 +744,15 @@ ipcp_create_replace_map (tree parm_tree, struct ipcp_lattice *lat) tree const_val; replace_map = XCNEW (struct ipa_replace_map); - if (dump_file) - fprintf (dump_file, "replacing param with const\n"); const_val = build_const_val (lat, TREE_TYPE (parm_tree)); + if (dump_file) + { + fprintf (dump_file, " replacing param "); + print_generic_expr (dump_file, parm_tree, 0); + fprintf (dump_file, " with const "); + print_generic_expr (dump_file, const_val, 0); + fprintf (dump_file, "\n"); + } replace_map->old_tree = parm_tree; replace_map->new_tree = const_val; replace_map->replace_p = true; @@ -766,6 +771,9 @@ ipcp_need_redirect_p (struct cgraph_edge *cs) struct ipa_jump_func *jump_func; struct cgraph_node *node = cs->callee, *orig; + if (!flag_ipa_cp_clone) + return false; + if ((orig = ipcp_get_orig_node (node)) != NULL) node = orig; if (ipcp_get_orig_node (cs->caller)) @@ -791,26 +799,59 @@ ipcp_need_redirect_p (struct cgraph_edge *cs) static void ipcp_update_callgraph (void) { - struct cgraph_node *node, *orig_callee; - struct cgraph_edge *cs; + struct cgraph_node *node; for (node = cgraph_nodes; node; node = node->next) - { - /* want to fix only original nodes */ - if (!node->analyzed || ipcp_node_is_clone (node)) - continue; - for (cs = node->callees; cs; cs = cs->next_callee) - if (ipcp_node_is_clone (cs->callee)) + if (node->analyzed && ipcp_node_is_clone (node)) + { + bitmap args_to_skip = BITMAP_ALLOC (NULL); + struct cgraph_node *orig_node = ipcp_get_orig_node (node); + struct ipa_node_params *info = IPA_NODE_REF (orig_node); + int i, count = ipa_get_param_count (info); + struct cgraph_edge *cs, *next; + + for (i = 0; i < count; i++) { - /* Callee is a cloned node */ - orig_callee = ipcp_get_orig_node (cs->callee); - if (ipcp_need_redirect_p (cs)) + struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i); + tree parm_tree = ipa_get_ith_param (info, i); + + /* We can proactively remove obviously unused arguments. */ + if (is_gimple_reg (parm_tree) + && !gimple_default_def (DECL_STRUCT_FUNCTION (orig_node->decl), + parm_tree)) { - cgraph_redirect_edge_callee (cs, orig_callee); - gimple_call_set_fndecl (cs->call_stmt, orig_callee->decl); + bitmap_set_bit (args_to_skip, i); + continue; } + + if (lat->type == IPA_CONST_VALUE) + bitmap_set_bit (args_to_skip, i); } - } + for (cs = node->callers; cs; cs = next) + { + next = cs->next_caller; + if (ipcp_node_is_clone (cs->caller) || !ipcp_need_redirect_p (cs)) + { + gimple new_stmt; + gimple_stmt_iterator gsi; + + current_function_decl = cs->caller->decl; + push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl)); + + new_stmt = giple_copy_call_skip_args (cs->call_stmt, args_to_skip); + gsi = gsi_for_stmt (cs->call_stmt); + gsi_replace (&gsi, new_stmt, true); + cgraph_set_call_stmt (cs, new_stmt); + pop_cfun (); + current_function_decl = NULL; + } + else + { + cgraph_redirect_edge_callee (cs, orig_node); + gimple_call_set_fndecl (cs->call_stmt, orig_node->decl); + } + } + } } /* Update all cfg basic blocks in NODE according to SCALE. */ @@ -989,7 +1030,7 @@ ipcp_insert_stage (void) { struct ipa_node_params *info; /* Propagation of the constant is forbidden in certain conditions. */ - if (!node->analyzed || ipcp_node_not_modifiable_p (node)) + if (!node->analyzed || !ipcp_node_modifiable_p (node)) continue; info = IPA_NODE_REF (node); if (ipa_is_called_with_var_arguments (info)) @@ -1004,6 +1045,7 @@ ipcp_insert_stage (void) { struct ipa_node_params *info; int growth = 0; + bitmap args_to_skip; node = (struct cgraph_node *)fibheap_extract_min (heap); node->aux = NULL; @@ -1033,20 +1075,27 @@ ipcp_insert_stage (void) VARRAY_GENERIC_PTR_INIT (replace_trees, ipcp_const_param_count (node), "replace_trees"); + args_to_skip = BITMAP_ALLOC (NULL); for (i = 0; i < count; i++) { struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i); parm_tree = ipa_get_ith_param (info, i); - if (lat->type == IPA_CONST_VALUE - /* Do not count obviously unused arguments. */ - && (!is_gimple_reg (parm_tree) - || gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), - parm_tree))) + /* We can proactively remove obviously unused arguments. */ + if (is_gimple_reg (parm_tree) + && !gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), + parm_tree)) + { + bitmap_set_bit (args_to_skip, i); + continue; + } + + if (lat->type == IPA_CONST_VALUE) { replace_param = ipcp_create_replace_map (parm_tree, lat); VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param); + bitmap_set_bit (args_to_skip, i); } } @@ -1061,7 +1110,9 @@ ipcp_insert_stage (void) /* Redirecting all the callers of the node to the new versioned node. */ node1 = - cgraph_function_versioning (node, redirect_callers, replace_trees); + cgraph_function_versioning (node, redirect_callers, replace_trees, + args_to_skip); + BITMAP_FREE (args_to_skip); VEC_free (cgraph_edge_p, heap, redirect_callers); VARRAY_CLEAR (replace_trees); if (node1 == NULL) |