function.h (struct function): Add saved blocks/unexpanded var list.
* function.h (struct function): Add saved blocks/unexpanded var list. * gimple-low.c (record_vars): Insert only VAR_DECLs. * tree-inline.c (add_lexical_block): Declare; do not clear sublocks. (remap_decl): Do not declare vars. (remap_block): Do not care inserting blocks. (remap_blocks): New function. (copy_body_r): Update debug info. (expand_call_inline): Duplicate callee block tree into caller; copy all the unexpanded_var_list. (save_body): Save unexpanded_var_list and blocks. * tree-optimize.c (tree_rest_of_optimization): Restore blocks/unexpanded_var_list. From-SVN: r101449
This commit is contained in:
parent
0abb14c013
commit
acb8f2123d
@ -1,3 +1,18 @@
|
||||
2005-06-30 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* function.h (struct function): Add saved blocks/unexpanded var list.
|
||||
* gimple-low.c (record_vars): Insert only VAR_DECLs.
|
||||
* tree-inline.c (add_lexical_block): Declare; do not clear sublocks.
|
||||
(remap_decl): Do not declare vars.
|
||||
(remap_block): Do not care inserting blocks.
|
||||
(remap_blocks): New function.
|
||||
(copy_body_r): Update debug info.
|
||||
(expand_call_inline): Duplicate callee block tree into caller;
|
||||
copy all the unexpanded_var_list.
|
||||
(save_body): Save unexpanded_var_list and blocks.
|
||||
* tree-optimize.c (tree_rest_of_optimization): Restore
|
||||
blocks/unexpanded_var_list.
|
||||
|
||||
2005-06-29 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/ia64/ia64.c (ia64_expand_vecint_minmax): Use us_minus and
|
||||
|
@ -178,6 +178,8 @@ struct function GTY(())
|
||||
inlining */
|
||||
tree saved_args;
|
||||
tree saved_static_chain_decl;
|
||||
tree saved_blocks;
|
||||
tree saved_unexpanded_var_list;
|
||||
|
||||
/* For function.c. */
|
||||
|
||||
|
@ -516,11 +516,13 @@ record_vars (tree vars)
|
||||
{
|
||||
tree var = vars;
|
||||
|
||||
/* BIND_EXPRs contains also function/type/constant declarations
|
||||
we don't need to care about. */
|
||||
if (TREE_CODE (var) != VAR_DECL)
|
||||
continue;
|
||||
/* Nothing to do in this case. */
|
||||
if (DECL_EXTERNAL (var))
|
||||
continue;
|
||||
if (TREE_CODE (var) == FUNCTION_DECL)
|
||||
continue;
|
||||
|
||||
/* Record the variable. */
|
||||
cfun->unexpanded_var_list = tree_cons (NULL_TREE, var,
|
||||
|
@ -159,6 +159,7 @@ static void declare_inline_vars (tree, tree);
|
||||
static void remap_save_expr (tree *, void *, int *);
|
||||
|
||||
static inline bool inlining_p (inline_data *id);
|
||||
static void add_lexical_block (tree current_block, tree new_block);
|
||||
|
||||
/* Insert a tree->tree mapping for ID. Despite the name suggests
|
||||
that the trees should be variables, it is used for more than that. */
|
||||
@ -246,13 +247,6 @@ remap_decl (tree decl, inline_data *id)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we are inlining and this is a variable (not a label), declare the
|
||||
remapped variable in the callers' body. */
|
||||
if (inlining_p (id)
|
||||
&& (TREE_CODE (t) == VAR_DECL
|
||||
|| TREE_CODE (t) == PARM_DECL))
|
||||
declare_inline_vars (id->block, t);
|
||||
|
||||
/* Remember it, so that if we encounter this local entity
|
||||
again we can reuse this copy. */
|
||||
insert_decl_map (id, decl, t);
|
||||
@ -436,32 +430,32 @@ remap_block (tree *block, inline_data *id)
|
||||
BLOCK_VARS (new_block) = remap_decls (BLOCK_VARS (old_block), id);
|
||||
|
||||
fn = id->caller;
|
||||
#if 1
|
||||
/* FIXME! It shouldn't be so hard to manage blocks. Rebuilding them in
|
||||
rest_of_compilation is a good start. */
|
||||
if (id->cloning_p)
|
||||
/* We're building a clone; DECL_INITIAL is still
|
||||
error_mark_node, and current_binding_level is the parm
|
||||
binding level. */
|
||||
lang_hooks.decls.insert_block (new_block);
|
||||
else
|
||||
{
|
||||
/* Attach this new block after the DECL_INITIAL block for the
|
||||
function into which this block is being inlined. In
|
||||
rest_of_compilation we will straighten out the BLOCK tree. */
|
||||
tree *first_block;
|
||||
if (DECL_INITIAL (fn))
|
||||
first_block = &BLOCK_CHAIN (DECL_INITIAL (fn));
|
||||
else
|
||||
first_block = &DECL_INITIAL (fn);
|
||||
BLOCK_CHAIN (new_block) = *first_block;
|
||||
*first_block = new_block;
|
||||
}
|
||||
#endif
|
||||
/* Remember the remapped block. */
|
||||
insert_decl_map (id, old_block, new_block);
|
||||
}
|
||||
|
||||
/* Copy the whole block tree and root it in id->block. */
|
||||
static tree
|
||||
remap_blocks (tree block, inline_data *id)
|
||||
{
|
||||
tree t;
|
||||
tree new = block;
|
||||
|
||||
if (!block)
|
||||
return NULL;
|
||||
|
||||
remap_block (&new, id);
|
||||
gcc_assert (new != block);
|
||||
for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
|
||||
add_lexical_block (new, remap_blocks (t, id));
|
||||
return new;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_statement_list (tree *tp)
|
||||
{
|
||||
@ -503,6 +497,7 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
|
||||
{
|
||||
inline_data *id = (inline_data *) data;
|
||||
tree fn = id->callee;
|
||||
tree new_block;
|
||||
|
||||
/* Begin by recognizing trees that we'll completely rewrite for the
|
||||
inlining context. Our output for these trees is completely
|
||||
@ -647,9 +642,23 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data)
|
||||
/* Here is the "usual case". Copy this tree node, and then
|
||||
tweak some special cases. */
|
||||
copy_tree_r (tp, walk_subtrees, NULL);
|
||||
if (id->block
|
||||
&& IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (*tp))))
|
||||
TREE_BLOCK (*tp) = id->block;
|
||||
|
||||
/* If EXPR has block defined, map it to newly constructed block.
|
||||
When inlining we want EXPRs without block appear in the block
|
||||
of function call. */
|
||||
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (*tp))))
|
||||
{
|
||||
new_block = id->block;
|
||||
if (TREE_BLOCK (*tp))
|
||||
{
|
||||
splay_tree_node n;
|
||||
n = splay_tree_lookup (id->decl_map,
|
||||
(splay_tree_key) TREE_BLOCK (*tp));
|
||||
gcc_assert (n);
|
||||
new_block = (tree) n->value;
|
||||
}
|
||||
TREE_BLOCK (*tp) = new_block;
|
||||
}
|
||||
|
||||
if (TREE_CODE (*tp) == RESX_EXPR && id->eh_region_offset)
|
||||
TREE_OPERAND (*tp, 0) =
|
||||
@ -1870,7 +1879,6 @@ add_lexical_block (tree current_block, tree new_block)
|
||||
;
|
||||
*blk_p = new_block;
|
||||
BLOCK_SUPERCONTEXT (new_block) = current_block;
|
||||
BLOCK_SUBBLOCKS (new_block) = NULL_TREE;
|
||||
}
|
||||
|
||||
/* If *TP is a CALL_EXPR, replace it with its inline expansion. */
|
||||
@ -2035,6 +2043,11 @@ 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))
|
||||
add_lexical_block (id->block, remap_blocks (DECL_INITIAL (fn), id));
|
||||
|
||||
/* Return statements in the function body will be replaced by jumps
|
||||
to the RET_LABEL. */
|
||||
|
||||
@ -2088,6 +2101,21 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
|
||||
copy_body (id, bb->count, bb->frequency, bb, return_block);
|
||||
id->current_node = old_node;
|
||||
|
||||
/* 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);
|
||||
if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var))
|
||||
cfun->unexpanded_var_list = tree_cons (NULL_TREE, var,
|
||||
cfun->unexpanded_var_list);
|
||||
else
|
||||
cfun->unexpanded_var_list = tree_cons (NULL_TREE, remap_decl (var, id),
|
||||
cfun->unexpanded_var_list);
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
splay_tree_delete (id->decl_map);
|
||||
id->decl_map = st;
|
||||
@ -2125,16 +2153,6 @@ expand_call_inline (basic_block bb, tree stmt, tree *tp, void *data)
|
||||
/* Declare the 'auto' variables added with this inlined body. */
|
||||
record_vars (BLOCK_VARS (id->block));
|
||||
id->block = NULL_TREE;
|
||||
|
||||
/* Add local static vars in this inlined callee to caller. */
|
||||
for (t_step = id->callee_cfun->unexpanded_var_list;
|
||||
t_step;
|
||||
t_step = TREE_CHAIN (t_step))
|
||||
{
|
||||
var = TREE_VALUE (t_step);
|
||||
if (TREE_STATIC (var) && !TREE_ASM_WRITTEN (var))
|
||||
record_vars (var);
|
||||
}
|
||||
successfully_inlined = TRUE;
|
||||
|
||||
egress:
|
||||
@ -2273,6 +2291,7 @@ 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;
|
||||
@ -2311,11 +2330,28 @@ save_body (tree fn, tree *arg_copy, tree *sc_copy)
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -924,9 +924,13 @@ tree_rest_of_compilation (tree fndecl)
|
||||
DECL_ARGUMENTS (fndecl) = cfun->saved_args;
|
||||
cfun->cfg = cfun->saved_cfg;
|
||||
cfun->eh = cfun->saved_eh;
|
||||
DECL_INITIAL (fndecl) = cfun->saved_blocks;
|
||||
cfun->unexpanded_var_list = cfun->saved_unexpanded_var_list;
|
||||
cfun->saved_cfg = NULL;
|
||||
cfun->saved_eh = NULL;
|
||||
cfun->saved_args = NULL_TREE;
|
||||
cfun->saved_blocks = NULL_TREE;
|
||||
cfun->saved_unexpanded_var_list = NULL_TREE;
|
||||
cfun->static_chain_decl = cfun->saved_static_chain_decl;
|
||||
cfun->saved_static_chain_decl = NULL;
|
||||
/* When not in unit-at-a-time mode, we must preserve out of line copy
|
||||
|
Loading…
Reference in New Issue
Block a user