aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2006-01-11 14:13:37 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2006-01-11 13:13:37 +0000
commitea99e0becf7057b7112a267b55e39e9b8c24db13 (patch)
tree7528e0c14251773ead6e3aa9eaaf90a59556ee1d /gcc/tree-inline.c
parentabcb0cdc2005f2cfb5ac9f1dedd5269b5f51c89f (diff)
downloadgcc-ea99e0becf7057b7112a267b55e39e9b8c24db13.zip
gcc-ea99e0becf7057b7112a267b55e39e9b8c24db13.tar.gz
gcc-ea99e0becf7057b7112a267b55e39e9b8c24db13.tar.bz2
cgraph.c (cgraph_insert_node_to_hashtable): New function.
* cgraph.c (cgraph_insert_node_to_hashtable): New function. * cgraph.h (cgraph_node): Add inline_decl. (cgraph_insert_node_to_hashtable): Declare. (save_inline_function_body): Declare. * cgraphunit.c (verify_cgraph_node): Inline edges might point to inline clones. (cgraph_preserve_function_body_p): Do not presrve when dump is enabled. (cgraph_function_versioning): Update call of tree_function_versioning. (save_inline_function_body): New function. * function.h (struct function): Kill saved_eh, saved_cfg, saved_args, saved_static_chain_decl, saved_blocks and saved-unexpanded_var_list. * ipa-inline.c (cgraph_mark_inline_edge): Look for inline clones. (cgraph_default_inline_p): Likewise. (cgraph_decide_inlining_incrementally): Likewise. * tree-inline.c (inline_data): Kill saving_p add update_clones_p. (copy_bb): Kill saving; do updating of clones. (copy_cfg_body): Kill saving. (initialize_inlined-parameters): Likewise. (expand_call_inline): Likewise. (save_body): Kill. (tree_function_versioning): New parameter "update_clones". (inlining_p): Kill saving. * tree-inline.h (tree_function_versioning): Update prototype. * tree-optimize.c (tree_rest_of_compilation): Use clonning instead of saving. From-SVN: r109580
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c178
1 files changed, 36 insertions, 142 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 0dafbc2..be38fc9 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -111,9 +111,7 @@ typedef struct inline_data
tree callee;
/* FUNCTION_DECL for function being inlined into. */
tree caller;
- /* struct function for function being inlined. Usually this is the same
- as DECL_STRUCT_FUNCTION (callee), but can be different if saved_cfg
- and saved_eh are in use. */
+ /* struct function for function being inlined. */
struct function *callee_cfun;
/* The VAR_DECL for the return value. */
tree retvar;
@@ -125,10 +123,11 @@ typedef struct inline_data
distinguish between those two situations. This flag is true if
we are cloning, rather than inlining. */
bool cloning_p;
- /* Similarly for saving function body. */
- bool saving_p;
/* Versioning function is slightly different from inlining. */
bool versioning_p;
+ /* If set, the call_stmt of edges in clones of caller functions will
+ be updated. */
+ bool update_clones_p;
/* Callgraph node of function we are inlining into. */
struct cgraph_node *node;
/* Callgraph node of currently inlined function. */
@@ -750,46 +749,33 @@ copy_bb (inline_data *id, basic_block bb, int frequency_scale, int count_scale)
callgraph edges and update or duplicate them. */
if (call && (decl = get_callee_fndecl (call)))
{
- if (id->saving_p)
- {
- struct cgraph_node *node;
- struct cgraph_edge *edge;
-
- /* We're saving a copy of the body, so we'll update the
- callgraph nodes in place. Note that we avoid
- altering the original callgraph node; we begin with
- the first clone. */
- for (node = id->node->next_clone;
- node;
- node = node->next_clone)
- {
- edge = cgraph_edge (node, orig_stmt);
- gcc_assert (edge);
- edge->call_stmt = stmt;
- }
- }
- else
+ if (!id->versioning_p)
{
struct cgraph_edge *edge;
/* We're cloning or inlining this body; duplicate the
associate callgraph nodes. */
- if (!id->versioning_p)
- {
- edge = cgraph_edge (id->current_node, orig_stmt);
- if (edge)
- cgraph_clone_edge (edge, id->node, stmt,
- REG_BR_PROB_BASE, 1, true);
- }
+ edge = cgraph_edge (id->current_node, orig_stmt);
+ if (edge)
+ cgraph_clone_edge (edge, id->node, stmt,
+ REG_BR_PROB_BASE, 1, true);
}
- if (id->versioning_p)
+ else
{
/* Update the call_expr on the edges from the new version
to its callees. */
struct cgraph_edge *edge;
edge = cgraph_edge (id->node, orig_stmt);
if (edge)
- edge->call_stmt = stmt;
+ {
+ edge->call_stmt = stmt;
+ if (id->update_clones_p)
+ {
+ struct cgraph_node *n;
+ for (n = id->node->next_clone; n; n = n->next_clone)
+ cgraph_edge (n, orig_stmt)->call_stmt = stmt;
+ }
+ }
}
}
/* If you think we can abort here, you are wrong.
@@ -917,7 +903,7 @@ copy_cfg_body (inline_data * id, gcov_type count, int frequency,
(struct function *) ggc_alloc_cleared (sizeof (struct function));
basic_block bb;
tree new_fndecl = NULL;
- bool saving_or_cloning;
+ bool versioning_or_cloning;
int count_scale, frequency_scale;
if (ENTRY_BLOCK_PTR_FOR_FUNCTION (callee_cfun)->count)
@@ -942,24 +928,14 @@ copy_cfg_body (inline_data * id, gcov_type count, int frequency,
*cfun_to_copy = *DECL_STRUCT_FUNCTION (callee_fndecl);
- /* If there is a saved_cfg+saved_args lurking in the
- struct function, a copy of the callee body was saved there, and
- the 'struct cgraph edge' nodes have been fudged to point into the
- saved body. Accordingly, we want to copy that saved body so the
- callgraph edges will be recognized and cloned properly. */
- if (cfun_to_copy->saved_cfg)
- {
- cfun_to_copy->cfg = cfun_to_copy->saved_cfg;
- cfun_to_copy->eh = cfun_to_copy->saved_eh;
- }
id->callee_cfun = cfun_to_copy;
/* If saving or cloning a function body, create new basic_block_info
and label_to_block_maps. Otherwise, we're duplicating a function
body for inlining; insert our new blocks and labels into the
existing varrays. */
- saving_or_cloning = (id->saving_p || id->cloning_p || id->versioning_p);
- if (saving_or_cloning)
+ versioning_or_cloning = (id->cloning_p || id->versioning_p);
+ if (versioning_or_cloning)
{
new_cfun =
(struct function *) ggc_alloc_cleared (sizeof (struct function));
@@ -995,7 +971,7 @@ copy_cfg_body (inline_data * id, gcov_type count, int frequency,
/* Duplicate any exception-handling regions. */
if (cfun->eh)
{
- if (saving_or_cloning)
+ if (versioning_or_cloning)
init_eh_for_function ();
id->eh_region_offset = duplicate_eh_regions (cfun_to_copy,
remap_decl_1,
@@ -1011,7 +987,7 @@ copy_cfg_body (inline_data * id, gcov_type count, int frequency,
FOR_ALL_BB_FN (bb, cfun_to_copy)
bb->aux = NULL;
- if (saving_or_cloning)
+ if (versioning_or_cloning)
pop_cfun ();
return new_fndecl;
@@ -1183,8 +1159,6 @@ initialize_inlined_parameters (inline_data *id, tree args, tree static_chain,
/* Figure out what the parameters are. */
parms = DECL_ARGUMENTS (fn);
- if (fn == current_function_decl)
- parms = cfun->saved_args;
/* Loop through the parameter declarations, replacing each with an
equivalent VAR_DECL, appropriately initialized. */
@@ -1204,8 +1178,7 @@ initialize_inlined_parameters (inline_data *id, tree args, tree static_chain,
/* Initialize the static chain. */
p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
- if (fn == current_function_decl)
- p = DECL_STRUCT_FUNCTION (fn)->saved_static_chain_decl;
+ gcc_assert (fn != current_function_decl);
if (p)
{
/* No static chain? Seems like a bug in tree-nested.c. */
@@ -2039,6 +2012,7 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
}
goto egress;
}
+ fn = cg_edge->callee->decl;
#ifdef ENABLE_CHECKING
if (cg_edge->callee->decl != id->node->decl)
@@ -2095,9 +2069,7 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
/* Record the function we are about to inline. */
id->callee = fn;
- if (DECL_STRUCT_FUNCTION (fn)->saved_blocks)
- add_lexical_block (id->block, remap_blocks (DECL_STRUCT_FUNCTION (fn)->saved_blocks, id));
- else if (DECL_INITIAL (fn))
+ if (DECL_INITIAL (fn))
add_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
/* Return statements in the function body will be replaced by jumps
@@ -2155,8 +2127,6 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
/* Add local vars in this inlined callee to caller. */
t_step = id->callee_cfun->unexpanded_var_list;
- if (id->callee_cfun->saved_unexpanded_var_list)
- t_step = id->callee_cfun->saved_unexpanded_var_list;
for (; t_step; t_step = TREE_CHAIN (t_step))
{
var = TREE_VALUE (t_step);
@@ -2331,86 +2301,6 @@ clone_body (tree clone, tree fn, void *arg_map)
append_to_statement_list_force (copy_generic_body (&id), &DECL_SAVED_TREE (clone));
}
-/* Save duplicate body in FN. MAP is used to pass around splay tree
- used to update arguments in restore_body. */
-
-/* Make and return duplicate of body in FN. Put copies of DECL_ARGUMENTS
- in *arg_copy and of the static chain, if any, in *sc_copy. */
-
-void
-save_body (tree fn, tree *arg_copy, tree *sc_copy)
-{
- inline_data id;
- tree newdecl, *parg;
- basic_block fn_entry_block;
- tree t_step;
-
- memset (&id, 0, sizeof (id));
- id.callee = fn;
- id.callee_cfun = DECL_STRUCT_FUNCTION (fn);
- id.caller = fn;
- id.node = cgraph_node (fn);
- id.saving_p = true;
- id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
- *arg_copy = DECL_ARGUMENTS (fn);
-
- for (parg = arg_copy; *parg; parg = &TREE_CHAIN (*parg))
- {
- tree new = copy_node (*parg);
-
- lang_hooks.dup_lang_specific_decl (new);
- DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*parg);
- insert_decl_map (&id, *parg, new);
- TREE_CHAIN (new) = TREE_CHAIN (*parg);
- *parg = new;
- }
-
- *sc_copy = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
- if (*sc_copy)
- {
- tree new = copy_node (*sc_copy);
-
- lang_hooks.dup_lang_specific_decl (new);
- DECL_ABSTRACT_ORIGIN (new) = DECL_ORIGIN (*sc_copy);
- insert_decl_map (&id, *sc_copy, new);
- TREE_CHAIN (new) = TREE_CHAIN (*sc_copy);
- *sc_copy = new;
- }
-
- /* We're not inside any EH region. */
- id.eh_region = -1;
-
- insert_decl_map (&id, DECL_RESULT (fn), DECL_RESULT (fn));
-
- DECL_STRUCT_FUNCTION (fn)->saved_blocks
- = remap_blocks (DECL_INITIAL (fn), &id);
- for (t_step = id.callee_cfun->unexpanded_var_list;
- t_step;
- t_step = TREE_CHAIN (t_step))
- {
- tree var = TREE_VALUE (t_step);
- if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var))
- cfun->saved_unexpanded_var_list
- = tree_cons (NULL_TREE, var, cfun->saved_unexpanded_var_list);
- else
- cfun->saved_unexpanded_var_list
- = tree_cons (NULL_TREE, remap_decl (var, &id),
- cfun->saved_unexpanded_var_list);
- }
-
- /* Actually copy the body, including a new (struct function *) and CFG.
- EH info is also duplicated so its labels point into the copied
- CFG, not the original. */
- fn_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fn));
- newdecl = copy_body (&id, fn_entry_block->count, fn_entry_block->frequency,
- NULL, NULL);
- DECL_STRUCT_FUNCTION (fn)->saved_cfg = DECL_STRUCT_FUNCTION (newdecl)->cfg;
- DECL_STRUCT_FUNCTION (fn)->saved_eh = DECL_STRUCT_FUNCTION (newdecl)->eh;
-
- /* Clean up. */
- splay_tree_delete (id.decl_map);
-}
-
/* Passed to walk_tree. Copies the node pointed to, if appropriate. */
tree
@@ -2807,9 +2697,11 @@ tree_versionable_function_p (tree fndecl)
respectively. In case we want to replace a DECL
tree with another tree while duplicating the function's
body, TREE_MAP represents the mapping between these
- trees. */
+ trees. If UPDATE_CLONES is set, the call_stmt fields
+ of edges of clones of the function will be updated. */
void
-tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map)
+tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map,
+ bool update_clones)
{
struct cgraph_node *old_version_node;
struct cgraph_node *new_version_node;
@@ -2835,8 +2727,9 @@ tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map)
DECL_ABSTRACT_ORIGIN (new_decl) = DECL_ORIGIN (old_decl);
/* Generate a new name for the new version. */
- DECL_NAME (new_decl) =
- create_tmp_var_name (NULL);
+ if (!update_clones)
+ DECL_NAME (new_decl) =
+ create_tmp_var_name (NULL);
/* Create a new SYMBOL_REF rtx for the new name. */
if (DECL_RTL (old_decl) != NULL)
{
@@ -2856,6 +2749,7 @@ tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map)
id.current_node = cgraph_node (old_decl);
id.versioning_p = true;
+ id.update_clones_p = update_clones;
id.decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
id.caller = new_decl;
id.callee = old_decl;
@@ -2982,7 +2876,7 @@ replace_ref_tree (inline_data * id, tree * tp)
static inline bool
inlining_p (inline_data * id)
{
- return (!id->saving_p && !id->cloning_p && !id->versioning_p);
+ return (!id->cloning_p && !id->versioning_p);
}
/* Duplicate a type, fields and all. */