cgraph.c (first_cgraph_function_insertion_hook): New variable.

* cgraph.c (first_cgraph_function_insertion_hook): New variable.
	(cgraph_add_function_insertion_hook, cgraph_remove_function_insertion_hook,
	cgraph_call_function_insertion_hooks): New functions.
	* cgraph.h (cgraph_add_function_insertion_hook, cgraph_remove_function_insertion_hook,
	cgraph_call_function_insertion_hooks): Declare.
	* ipa-reference.c (function_insertion_hook_holder): New variable.
	(check_operand, look_for_address_of): When checking late, do not care
	about module bitmaps.
	(add_new_function): New function.
	(generate_summary): Register hooks; zero module bitmaps.
	(propagate): Unregister hooks.
	* ipa-pure-const.c (function_insertion_hook_holder): New variable.
	(add_new_function): New function.
	(generate_summary): Register hook.
	(propagate): Remove hook.

	* ipa-cp.c (ipcp_need_redirect_p): Fix to not be constant 0.

	* tree-pass.h (pass_ipa_cp): Make ipa_opt_pass.
	* ipa-cp.c (ipcp_update_cloned_node): New function.
	(build_const_val): Handle functions correctly; bring type logic
	into sync with tree-inline.c
	(ipcp_init_stage):  Take care of computing stuff needed by
	indirect inlining; update clones.
	(ipcp_generate_summary): Break out of ipcp_driver.
	(ipcp_driver): Do only execution and transformation.
	(pass_ipa_cp): Make IPA_PASS.
	* tree-ssa-ccp.c (fold_stmt_r): Check type before trying to fold
	offset to address.
	* ipa-inline.c (inline_indirect_intraprocedural_analysis): When doing
	ipcp, some info is already available.
	* ipa-prop.c (ipa_count_arguments): Grow edge lists as needed.
	* tree-inline.c (remap_ssa_name): Unshare expression.

From-SVN: r139389
This commit is contained in:
Jan Hubicka 2008-08-21 17:26:59 +02:00 committed by Jan Hubicka
parent 1e52075c54
commit 129a37fc31
12 changed files with 232 additions and 32 deletions

View File

@ -1,3 +1,39 @@
2008-08-21 Jan Hubicka <jh@suse.cz>
* cgraph.c (first_cgraph_function_insertion_hook): New variable.
(cgraph_add_function_insertion_hook, cgraph_remove_function_insertion_hook,
cgraph_call_function_insertion_hooks): New functions.
* cgraph.h (cgraph_add_function_insertion_hook, cgraph_remove_function_insertion_hook,
cgraph_call_function_insertion_hooks): Declare.
* ipa-reference.c (function_insertion_hook_holder): New variable.
(check_operand, look_for_address_of): When checking late, do not care
about module bitmaps.
(add_new_function): New function.
(generate_summary): Register hooks; zero module bitmaps.
(propagate): Unregister hooks.
* ipa-pure-const.c (function_insertion_hook_holder): New variable.
(add_new_function): New function.
(generate_summary): Register hook.
(propagate): Remove hook.
* ipa-cp.c (ipcp_need_redirect_p): Fix to not be constant 0.
* tree-pass.h (pass_ipa_cp): Make ipa_opt_pass.
* ipa-cp.c (ipcp_update_cloned_node): New function.
(build_const_val): Handle functions correctly; bring type logic
into sync with tree-inline.c
(ipcp_init_stage): Take care of computing stuff needed by
indirect inlining; update clones.
(ipcp_generate_summary): Break out of ipcp_driver.
(ipcp_driver): Do only execution and transformation.
(pass_ipa_cp): Make IPA_PASS.
* tree-ssa-ccp.c (fold_stmt_r): Check type before trying to fold
offset to address.
* ipa-inline.c (inline_indirect_intraprocedural_analysis): When doing
ipcp, some info is already available.
* ipa-prop.c (ipa_count_arguments): Grow edge lists as needed.
* tree-inline.c (remap_ssa_name): Unshare expression.
2008-08-21 Richard Guenther <rguenther@suse.de>
* tree-ssa-pre.c (insert_into_preds_of_block): Before inserting

View File

@ -173,6 +173,8 @@ struct cgraph_node_hook_list *first_cgraph_node_removal_hook;
struct cgraph_2edge_hook_list *first_cgraph_edge_duplicated_hook;
/* List of hooks triggered when a node is duplicated. */
struct cgraph_2node_hook_list *first_cgraph_node_duplicated_hook;
/* List of hooks triggered when an function is inserted. */
struct cgraph_node_hook_list *first_cgraph_function_insertion_hook;
/* Register HOOK to be called with DATA on each removed edge. */
@ -255,6 +257,46 @@ cgraph_call_node_removal_hooks (struct cgraph_node *node)
}
}
/* Register HOOK to be called with DATA on each removed node. */
struct cgraph_node_hook_list *
cgraph_add_function_insertion_hook (cgraph_node_hook hook, void *data)
{
struct cgraph_node_hook_list *entry;
struct cgraph_node_hook_list **ptr = &first_cgraph_function_insertion_hook;
entry = (struct cgraph_node_hook_list *) xmalloc (sizeof (*entry));
entry->hook = hook;
entry->data = data;
entry->next = NULL;
while (*ptr)
ptr = &(*ptr)->next;
*ptr = entry;
return entry;
}
/* Remove ENTRY from the list of hooks called on removing nodes. */
void
cgraph_remove_function_insertion_hook (struct cgraph_node_hook_list *entry)
{
struct cgraph_node_hook_list **ptr = &first_cgraph_function_insertion_hook;
while (*ptr != entry)
ptr = &(*ptr)->next;
*ptr = entry->next;
}
/* Call all node removal hooks. */
void
cgraph_call_function_insertion_hooks (struct cgraph_node *node)
{
struct cgraph_node_hook_list *entry = first_cgraph_function_insertion_hook;
while (entry)
{
entry->hook (node, entry->data);
entry = entry->next;
}
}
/* Register HOOK to be called with DATA on each duplicated edge. */
struct cgraph_2edge_hook_list *
cgraph_add_edge_duplication_hook (cgraph_2edge_hook hook, void *data)

View File

@ -372,6 +372,10 @@ void cgraph_remove_edge_removal_hook (struct cgraph_edge_hook_list *);
struct cgraph_node_hook_list *cgraph_add_node_removal_hook (cgraph_node_hook,
void *);
void cgraph_remove_node_removal_hook (struct cgraph_node_hook_list *);
struct cgraph_node_hook_list *cgraph_add_function_insertion_hook (cgraph_node_hook,
void *);
void cgraph_remove_function_insertion_hook (struct cgraph_node_hook_list *);
void cgraph_call_function_insertion_hooks (struct cgraph_node *node);
struct cgraph_2edge_hook_list *cgraph_add_edge_duplication_hook (cgraph_2edge_hook, void *);
void cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *);
struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_hook, void *);

View File

@ -434,6 +434,7 @@ cgraph_process_new_functions (void)
gcc_unreachable ();
break;
}
cgraph_call_function_insertion_hooks (node);
}
return output;
}
@ -1535,6 +1536,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
new_version_node->local.externally_visible = 0;
new_version_node->local.local = 1;
new_version_node->lowered = true;
cgraph_call_function_insertion_hooks (new_version_node);
return new_version_node;
}

View File

@ -159,6 +159,36 @@ ipcp_init_cloned_node (struct cgraph_node *orig_node,
ipa_create_param_decls_array (new_node);
}
/* Recompute all local information since node might've got new
direct calls after clonning. */
static void
ipcp_update_cloned_node (struct cgraph_node *new_node)
{
/* We might've introduced new direct calls. */
push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
current_function_decl = new_node->decl;
rebuild_cgraph_edges ();
if (flag_indirect_inlining)
{
struct cgraph_edge *cs;
ipa_check_create_node_params ();
ipa_count_formal_params (new_node);
ipa_create_param_decls_array (new_node);
ipa_detect_param_modifications (new_node);
ipa_analyze_params_uses (new_node);
for (cs = new_node->callees; cs; cs = cs->next_callee)
{
ipa_count_arguments (cs);
ipa_compute_jump_functions (cs);
}
}
pop_cfun ();
current_function_decl = NULL;
}
/* Return scale for NODE. */
static inline gcov_type
ipcp_get_node_scale (struct cgraph_node *node)
@ -377,11 +407,27 @@ constant_val_insert (tree parm1 ATTRIBUTE_UNUSED, tree val ATTRIBUTE_UNUSED)
static tree
build_const_val (struct ipcp_lattice *lat, tree tree_type)
{
tree const_val = NULL;
tree val;
gcc_assert (ipcp_lat_is_const (lat));
const_val = fold_convert (tree_type, lat->constant);
return const_val;
val = lat->constant;
/* compute_jump_functions inserts FUNCTION_DECL as value of parameter
when address of function is taken. It would make more sense to pass
whole ADDR_EXPR, but for now compensate here. */
if ((lat->type == IPA_CONST_VALUE
&& TREE_CODE (val) == FUNCTION_DECL)
|| lat->type == IPA_CONST_VALUE_REF)
return build_fold_addr_expr_with_type (val, tree_type);
if (!useless_type_conversion_p (tree_type, TREE_TYPE (val)))
{
if (fold_convertible_p (tree_type, val))
return fold_build1 (NOP_EXPR, tree_type, val);
else
return fold_build1 (VIEW_CONVERT_EXPR, tree_type, val);
}
return val;
}
/* Build the tree representing the constant and call constant_val_insert(). */
@ -456,6 +502,8 @@ ipcp_init_stage (void)
/* Handle cases of functions with
a variable number of parameters. */
ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
if (flag_indirect_inlining)
ipa_compute_jump_functions (cs);
}
else
ipa_compute_jump_functions (cs);
@ -781,7 +829,8 @@ ipcp_need_redirect_p (struct cgraph_edge *cs)
if (ipcp_lat_is_const (lat))
{
jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
if (!ipcp_lat_is_const (lat))
if (jump_func->type != IPA_CONST && jump_func->type != IPA_CONST_REF
&& jump_func->type != IPA_CONST_MEMBER_PTR)
return true;
}
}
@ -966,7 +1015,10 @@ ipcp_insert_stage (void)
free_dominance_info (CDI_POST_DOMINATORS);
pop_cfun ();
current_function_decl = NULL;
/* We've possibly introduced direct calls. */
ipcp_update_cloned_node (node1);
}
if (dump_file)
dump_function_to_file (node1->decl, dump_file, dump_flags);
}
@ -978,19 +1030,6 @@ ipcp_insert_stage (void)
static unsigned int
ipcp_driver (void)
{
if (dump_file)
fprintf (dump_file, "\nIPA constant propagation start:\n");
ipa_check_create_node_params ();
ipa_check_create_edge_args ();
ipa_register_cgraph_hooks ();
/* 1. Call the init stage to initialize
the ipa_node_params and ipa_edge_args structures. */
ipcp_init_stage ();
if (dump_file)
{
fprintf (dump_file, "\nIPA structures before propagation:\n");
ipcp_print_all_structures (dump_file);
}
/* 2. Do the interprocedural propagation. */
ipcp_iterate_stage ();
if (dump_file)
@ -1015,6 +1054,25 @@ ipcp_driver (void)
return 0;
}
/* Note function body size. */
static void
ipcp_generate_summary (void)
{
if (dump_file)
fprintf (dump_file, "\nIPA constant propagation start:\n");
ipa_check_create_node_params ();
ipa_check_create_edge_args ();
ipa_register_cgraph_hooks ();
/* 1. Call the init stage to initialize
the ipa_node_params and ipa_edge_args structures. */
ipcp_init_stage ();
if (dump_file)
{
fprintf (dump_file, "\nIPA structures before propagation:\n");
ipcp_print_all_structures (dump_file);
}
}
/* Gate for IPCP optimization. */
static bool
cgraph_gate_cp (void)
@ -1022,10 +1080,10 @@ cgraph_gate_cp (void)
return flag_ipa_cp;
}
struct simple_ipa_opt_pass pass_ipa_cp =
struct ipa_opt_pass pass_ipa_cp =
{
{
SIMPLE_IPA_PASS,
IPA_PASS,
"cp", /* name */
cgraph_gate_cp, /* gate */
ipcp_driver, /* execute */
@ -1038,5 +1096,12 @@ struct simple_ipa_opt_pass pass_ipa_cp =
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_cgraph | TODO_dump_func /* todo_flags_finish */
}
},
ipcp_generate_summary, /* generate_summary */
NULL, /* write_summary */
NULL, /* read_summary */
NULL, /* function_read_summary */
0, /* TODOs */
NULL, /* function_transform */
NULL, /* variable_transform */
};

View File

@ -1633,19 +1633,23 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
{
struct cgraph_edge *cs;
ipa_count_formal_params (node);
ipa_create_param_decls_array (node);
ipa_detect_param_modifications (node);
if (!flag_ipa_cp)
{
ipa_count_formal_params (node);
ipa_create_param_decls_array (node);
ipa_detect_param_modifications (node);
}
ipa_analyze_params_uses (node);
if (dump_file)
ipa_print_node_param_flags (dump_file, node);
for (cs = node->callees; cs; cs = cs->next_callee)
{
ipa_count_arguments (cs);
ipa_compute_jump_functions (cs);
}
if (!flag_ipa_cp)
for (cs = node->callees; cs; cs = cs->next_callee)
{
ipa_count_arguments (cs);
ipa_compute_jump_functions (cs);
}
if (dump_file)
ipa_print_node_jump_functions (dump_file, node);

View File

@ -238,6 +238,10 @@ ipa_count_arguments (struct cgraph_edge *cs)
stmt = cs->call_stmt;
gcc_assert (is_gimple_call (stmt));
arg_num = gimple_call_num_args (stmt);
if (VEC_length (ipa_edge_args_t, ipa_edge_args_vector)
<= (unsigned) cgraph_edge_max_uid)
VEC_safe_grow_cleared (ipa_edge_args_t, heap,
ipa_edge_args_vector, cgraph_edge_max_uid + 1);
ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num);
}

View File

@ -96,6 +96,8 @@ typedef struct funct_state_d * funct_state;
static funct_state *funct_state_vec;
/* Holders of ipa cgraph hooks: */
static struct cgraph_node_hook_list *function_insertion_hook_holder;
/* Init the function state. */
@ -677,6 +679,21 @@ end:
}
}
/* Called when new function is inserted to callgraph late. */
static void
add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
funct_state_vec = XRESIZEVEC (funct_state, funct_state_vec, cgraph_max_uid);
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
since all we would be interested in are the addressof
operations. */
visited_nodes = pointer_set_create ();
analyze_function (node);
pointer_set_destroy (visited_nodes);
visited_nodes = NULL;
}
/* Analyze each function in the cgraph to see if it is locally PURE or
CONST. */
@ -686,6 +703,8 @@ generate_summary (void)
{
struct cgraph_node *node;
function_insertion_hook_holder =
cgraph_add_function_insertion_hook (&add_new_function, NULL);
init_state ();
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
@ -725,6 +744,7 @@ propagate (void)
int i;
struct ipa_dfs_info * w_info;
cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
order_pos = ipa_utils_reduced_inorder (order, true, false);
if (dump_file)
{

View File

@ -95,6 +95,9 @@ static struct pointer_set_t *visited_nodes;
static bitmap_obstack ipa_obstack;
/* Holders of ipa cgraph hooks: */
static struct cgraph_node_hook_list *function_insertion_hook_holder;
enum initialization_status_t
{
UNINITIALIZED,
@ -296,7 +299,8 @@ check_operand (ipa_reference_local_vars_info_t local,
bitmap_set_bit (local->statics_written, DECL_UID (t));
/* Mark the write so we can tell which statics are
readonly. */
bitmap_set_bit (module_statics_written, DECL_UID (t));
if (module_statics_written)
bitmap_set_bit (module_statics_written, DECL_UID (t));
}
else if (local)
bitmap_set_bit (local->statics_read, DECL_UID (t));
@ -345,7 +349,7 @@ look_for_address_of (tree t)
{
tree x = get_base_var (t);
if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL)
if (has_proper_scope_for_analysis (x))
if (has_proper_scope_for_analysis (x) && module_statics_escape)
bitmap_set_bit (module_statics_escape, DECL_UID (x));
}
}
@ -935,6 +939,19 @@ clean_function (struct cgraph_node *fn)
get_function_ann (fn->decl)->reference_vars_info = NULL;
}
/* Called when new function is inserted to callgraph late. */
static void
add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
since all we would be interested in are the addressof
operations. */
visited_nodes = pointer_set_create ();
analyze_function (node);
pointer_set_destroy (visited_nodes);
visited_nodes = NULL;
}
/* Analyze each function in the cgraph to see which global or statics
are read or written. */
@ -949,6 +966,8 @@ generate_summary (void)
bitmap module_statics_readonly;
bitmap bm_temp;
function_insertion_hook_holder =
cgraph_add_function_insertion_hook (&add_new_function, NULL);
ipa_init ();
module_statics_readonly = BITMAP_ALLOC (&ipa_obstack);
bm_temp = BITMAP_ALLOC (&ipa_obstack);
@ -1031,6 +1050,8 @@ generate_summary (void)
BITMAP_FREE(module_statics_escape);
BITMAP_FREE(module_statics_written);
module_statics_escape = NULL;
module_statics_written = NULL;
if (dump_file)
EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
@ -1107,6 +1128,7 @@ propagate (void)
int order_pos = ipa_utils_reduced_inorder (order, false, true);
int i;
cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
if (dump_file)
dump_cgraph (dump_file);

View File

@ -161,7 +161,7 @@ remap_ssa_name (tree name, copy_body_data *id)
n = (tree *) pointer_map_contains (id->decl_map, name);
if (n)
return *n;
return unshare_expr (*n);
/* Do not set DEF_STMT yet as statement is not copied yet. We do that
in copy_bb. */

View File

@ -390,11 +390,11 @@ extern struct gimple_opt_pass pass_reset_cc_flags;
/* IPA Passes */
extern struct ipa_opt_pass pass_ipa_inline;
extern struct ipa_opt_pass pass_ipa_cp;
extern struct ipa_opt_pass pass_ipa_reference;
extern struct ipa_opt_pass pass_ipa_pure_const;
extern struct simple_ipa_opt_pass pass_ipa_matrix_reorg;
extern struct simple_ipa_opt_pass pass_ipa_cp;
extern struct simple_ipa_opt_pass pass_ipa_early_inline;
extern struct simple_ipa_opt_pass pass_ipa_type_escape;
extern struct simple_ipa_opt_pass pass_ipa_pta;

View File

@ -2304,6 +2304,7 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
*walk_subtrees = 0;
if (POINTER_TYPE_P (TREE_TYPE (expr))
&& POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (expr)))
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
&& (t = maybe_fold_offset_to_address (TREE_OPERAND (expr, 0),
integer_zero_node,