Commit ea99e0be by Jan Hubicka Committed by Jan Hubicka

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
parent abcb0cdc
2006-01-11 Jan Hubicka <jh@suse.cz>
* 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.
2006-01-11 Ian Lance Taylor <ian@airs.com>
* combine.c (struct undo): Remove is_int. Enumify types of undos.
......
......@@ -214,6 +214,19 @@ cgraph_node (tree decl)
return node;
}
/* Insert already constructed node into hashtable. */
void
cgraph_insert_node_to_hashtable (struct cgraph_node *node)
{
struct cgraph_node **slot;
slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT);
gcc_assert (!*slot);
*slot = node;
}
/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
static bool
......
......@@ -161,6 +161,11 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
bool externally_visible;
/* Set for aliases once they got through assemble_alias. */
bool alias;
/* In non-unit-at-a-time mode the function body of inline candidates is saved
into clone before compiling so the function in original form can be
inlined later. This pointer points to the clone. */
tree inline_decl;
};
struct cgraph_edge GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller")))
......@@ -225,6 +230,7 @@ extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
/* In cgraph.c */
void dump_cgraph (FILE *);
void dump_cgraph_node (FILE *, struct cgraph_node *);
void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
void dump_varpool (FILE *);
void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
void cgraph_remove_edge (struct cgraph_edge *);
......@@ -281,6 +287,7 @@ void cgraph_reset_static_var_maps (void);
void init_cgraph (void);
struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
varray_type, varray_type);
struct cgraph_node *save_inline_function_body (struct cgraph_node *);
/* In ipa.c */
bool cgraph_remove_unreachable_nodes (bool, FILE *);
......
......@@ -748,7 +748,8 @@ verify_cgraph_node (struct cgraph_node *node)
debug_generic_stmt (stmt);
error_found = true;
}
if (e->callee->decl != cgraph_node (decl)->decl)
if (e->callee->decl != cgraph_node (decl)->decl
&& e->inline_failed)
{
error ("edge points to wrong declaration:");
debug_tree (e->callee->decl);
......@@ -1202,9 +1203,6 @@ bool
cgraph_preserve_function_body_p (tree decl)
{
struct cgraph_node *node;
/* Keep the body; we're going to dump it. */
if (dump_enabled_p (TDI_tree_all))
return true;
if (!cgraph_global_info_ready)
return (DECL_INLINE (decl) && !flag_really_no_inline);
/* Look if there is any clone around. */
......@@ -1504,7 +1502,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
redirect_callers);
/* Copy the OLD_VERSION_NODE function tree to the new version. */
tree_function_versioning (old_decl, new_decl, tree_map);
tree_function_versioning (old_decl, new_decl, tree_map, false);
/* Update the call_expr on the edges to call the new version node. */
update_call_expr (new_version_node);
......@@ -1521,3 +1519,57 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
new_version_node->lowered = true;
return new_version_node;
}
/* Produce separate function body for inline clones so the offline copy can be
modified without affecting them. */
struct cgraph_node *
save_inline_function_body (struct cgraph_node *node)
{
struct cgraph_node *first_clone;
gcc_assert (node == cgraph_node (node->decl));
cgraph_lower_function (node);
/* In non-unit-at-a-time we construct full fledged clone we never output to
assembly file. This clone is pointed out by inline_decl of orginal function
and inlining infrastructure knows how to deal with this. */
if (!flag_unit_at_a_time)
{
struct cgraph_edge *e;
first_clone = cgraph_clone_node (node, node->count, 0, false);
first_clone->needed = 0;
first_clone->reachable = 1;
/* Recursively clone all bodies. */
for (e = first_clone->callees; e; e = e->next_callee)
if (!e->inline_failed)
cgraph_clone_inlined_nodes (e, true, false);
}
else
first_clone = node->next_clone;
first_clone->decl = copy_node (node->decl);
node->next_clone = NULL;
if (!flag_unit_at_a_time)
node->inline_decl = first_clone->decl;
first_clone->prev_clone = NULL;
cgraph_insert_node_to_hashtable (first_clone);
gcc_assert (first_clone == cgraph_node (first_clone->decl));
/* Copy the OLD_VERSION_NODE function tree to the new version. */
tree_function_versioning (node->decl, first_clone->decl, NULL, true);
DECL_EXTERNAL (first_clone->decl) = 0;
DECL_ONE_ONLY (first_clone->decl) = 0;
TREE_PUBLIC (first_clone->decl) = 0;
DECL_COMDAT (first_clone->decl) = 0;
for (node = first_clone->next_clone; node; node = node->next_clone)
node->decl = first_clone->decl;
#ifdef ENABLE_CHECKING
verify_cgraph_node (first_clone);
#endif
return first_clone;
}
......@@ -162,25 +162,14 @@ struct expr_status GTY(())
struct function GTY(())
{
struct eh_status *eh;
struct eh_status *saved_eh;
struct expr_status *expr;
struct emit_status *emit;
struct varasm_status *varasm;
/* The control flow graph for this function. */
struct control_flow_graph *cfg;
struct control_flow_graph *saved_cfg;
bool after_inlining;
/* For tree-optimize.c. */
/* Saved tree and arguments during tree optimization. Used later for
inlining */
tree saved_args;
tree saved_static_chain_decl;
tree saved_blocks;
tree saved_unexpanded_var_list;
/* For function.c. */
/* Points to the FUNCTION_DECL of this function. */
......
......@@ -158,6 +158,9 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original)
int old_insns = 0, new_insns = 0;
struct cgraph_node *to = NULL, *what;
if (e->callee->inline_decl)
cgraph_redirect_edge_callee (e, cgraph_node (e->callee->inline_decl));
gcc_assert (e->inline_failed);
e->inline_failed = NULL;
......@@ -283,21 +286,25 @@ cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
bool
cgraph_default_inline_p (struct cgraph_node *n, const char **reason)
{
if (!DECL_INLINE (n->decl))
tree decl = n->decl;
if (n->inline_decl)
decl = n->inline_decl;
if (!DECL_INLINE (decl))
{
if (reason)
*reason = N_("function not inlinable");
return false;
}
if (!DECL_SAVED_TREE (n->decl))
if (!DECL_STRUCT_FUNCTION (decl)->cfg)
{
if (reason)
*reason = N_("function body not available");
return false;
}
if (DECL_DECLARED_INLINE_P (n->decl))
if (DECL_DECLARED_INLINE_P (decl))
{
if (n->global.insns >= MAX_INLINE_INSNS_SINGLE)
{
......@@ -1046,7 +1053,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, bool early)
&& !cgraph_recursive_inlining_p (node, e->callee, &e->inline_failed)
/* ??? It is possible that renaming variable removed the function body
in duplicate_decls. See gcc.c-torture/compile/20011119-2.c */
&& DECL_SAVED_TREE (e->callee->decl))
&& (DECL_SAVED_TREE (e->callee->decl) || e->callee->inline_decl))
{
if (dump_file && early)
{
......@@ -1069,7 +1076,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node, bool early)
|| (cgraph_estimate_size_after_inlining (1, e->caller, node)
<= e->caller->global.insns))
&& cgraph_check_inline_limits (node, e->callee, &e->inline_failed)
&& DECL_SAVED_TREE (e->callee->decl))
&& (DECL_SAVED_TREE (e->callee->decl) || e->callee->inline_decl))
{
if (cgraph_default_inline_p (e->callee, &failed_reason))
{
......
......@@ -35,7 +35,7 @@ void push_cfun (struct function *new_cfun);
void pop_cfun (void);
int estimate_num_insns (tree expr);
bool tree_versionable_function_p (tree);
void tree_function_versioning (tree, tree, varray_type);
void tree_function_versioning (tree, tree, varray_type, bool);
/* Copy a declaration when one function is substituted inline into
another. It is used also for versioning. */
......
......@@ -348,12 +348,19 @@ void
tree_rest_of_compilation (tree fndecl)
{
location_t saved_loc;
struct cgraph_node *saved_node = NULL, *node;
struct cgraph_node *node;
timevar_push (TV_EXPAND);
gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
node = cgraph_node (fndecl);
/* We might need the body of this function so that we can expand
it inline somewhere else. */
if (cgraph_preserve_function_body_p (fndecl))
save_inline_function_body (node);
/* Initialize the RTL code for the function. */
current_function_decl = fndecl;
saved_loc = input_location;
......@@ -367,26 +374,6 @@ tree_rest_of_compilation (tree fndecl)
cfun->x_dont_save_pending_sizes_p = 1;
cfun->after_inlining = true;
node = cgraph_node (fndecl);
/* We might need the body of this function so that we can expand
it inline somewhere else. This means not lowering some constructs
such as exception handling. */
if (cgraph_preserve_function_body_p (fndecl))
{
if (!flag_unit_at_a_time)
{
struct cgraph_edge *e;
saved_node = cgraph_clone_node (node, node->count, 1, false);
for (e = saved_node->callees; e; e = e->next_callee)
if (!e->inline_failed)
cgraph_clone_inlined_nodes (e, true, false);
}
cfun->saved_static_chain_decl = cfun->static_chain_decl;
save_body (fndecl, &cfun->saved_args, &cfun->saved_static_chain_decl);
}
if (flag_inline_trees)
{
struct cgraph_edge *e;
......@@ -429,40 +416,7 @@ tree_rest_of_compilation (tree fndecl)
/* Release the default bitmap obstack. */
bitmap_obstack_release (NULL);
/* Restore original body if still needed. */
if (cfun->saved_cfg)
{
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
representing node before inlining. Restore original outgoing edges
using clone we created earlier. */
if (!flag_unit_at_a_time)
{
struct cgraph_edge *e;
node = cgraph_node (current_function_decl);
cgraph_node_remove_callees (node);
node->callees = saved_node->callees;
saved_node->callees = NULL;
update_inlined_to_pointers (node, node);
for (e = node->callees; e; e = e->next_callee)
e->caller = node;
cgraph_remove_node (saved_node);
}
}
else
DECL_SAVED_TREE (fndecl) = NULL;
DECL_SAVED_TREE (fndecl) = NULL;
cfun = 0;
/* If requested, warn about function definitions where the function will
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment