aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2005-06-30 02:47:49 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2005-06-30 00:47:49 +0000
commitacb8f2123d5a627e6c5dad2e78fd57d2bd6c6fb1 (patch)
tree61f3a41e0903263a69773a750d50202e1e71289e
parent0abb14c01353a5f52ee2a5fee73ed0862d306af0 (diff)
downloadgcc-acb8f2123d5a627e6c5dad2e78fd57d2bd6c6fb1.zip
gcc-acb8f2123d5a627e6c5dad2e78fd57d2bd6c6fb1.tar.gz
gcc-acb8f2123d5a627e6c5dad2e78fd57d2bd6c6fb1.tar.bz2
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
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/function.h2
-rw-r--r--gcc/gimple-low.c6
-rw-r--r--gcc/tree-inline.c114
-rw-r--r--gcc/tree-optimize.c4
5 files changed, 100 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ea8a5ae..9a91b2a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/function.h b/gcc/function.h
index 2d59d23..11b97c1 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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. */
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 7acb4a4..3bece1a 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.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,
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 16f6164..94f9371 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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;
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index 7374478..4add52b 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -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