ipa-prop.h (struct ipa_param_flags): Removed.

2008-09-11  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (struct ipa_param_flags): Removed.
	(struct ipa_param_descriptor): New structure.
	(struct ipa_node_params): ipcp_lattices, param_decls and
	param_flags moved to ipa_param_description.
	(ipa_get_ith_param): Renamed to ipa_get_param, changed to access
	descriptors.  Renamed all users.
	(ipa_is_ith_param_modified): Renamed to ipa_is_param_modified,
	changed to access descriptors.  Renamed all users.
	(ipa_is_ith_param_called): Renamed to ipa_is_param_called, changed
	to access descriptors. Renamed all users.
	* ipa-cp.c (ipcp_init_cloned_node): Call
	ipa_initialize_node_params instead of ipa_count_formal_params and
	ipa_create_param_decls_array.
	(ipcp_analyze_node): Likewise.
	(ipcp_get_ith_lattice): Renamed to ipcp_get_lattice, changed to access
	descriptors.  Renamed all users.
	(ipcp_initialize_node_lattices): Remove allocation.
	* ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
	ipa_initialize_node_params instead of ipa_count_formal_params and
	ipa_create_param_decls_array.
	* ipa-prop.c (ipa_create_param_decls_array): Renamed to
	ipa_populate_param_decls, made static, added parameter info,
	renamed mt to node, removed allocation, changed to use
	descriptors.
	(ipa_count_formal_params): Made static, added parameter info,
	renamed mt to node.
	(ipa_initialize_node_params): New function.
	(ipa_check_stmt_modifications): Changed to use descriptors.
	(ipa_detect_param_modifications): Removed allocation, changed to
	use descriptors.
	(ipa_note_param_call): Changed to use descriptors.
	(ipa_analyze_params_uses): Removed allocation.
	(ipa_free_node_params_substructures): Changed to use descriptors.
	(ipa_edge_duplication_hook): Use the unused attribute.
	(ipa_node_duplication_hook): Use the unused attribute, changed to
	use descriptors, changed to duplicate descriptors.

	* ipa-inline.c (cgraph_mark_inline_edge): New parameter new_edges,
	changed all callers.  Call ipa_propagate_indirect_call_infos if doing
	indirect inlining.  Made static.
        (cgraph_decide_inlining): Freeing ipa-prop structures after inlining
	functions called only once.
	(cgraph_decide_recursive_inlining): Don't call
	ipa_propagate_indirect_call_infos, pass new_edges to
	cgraph_mark_inline_edge instead.
	(cgraph_decide_inlining_of_small_functions): Don't call
	ipa_propagate_indirect_call_infos, pass new_edges to
	cgraph_mark_inline_edge instead.
	(cgraph_decide_inlining): Don't call
	ipa_propagate_indirect_call_infos.
	* ipa-prop.c: Check that vectors are allocated.

	* ipa-inline.c (cgraph_mark_inline_edge): Returns boolean, true
	iff a new cgraph edges have been created.
	(cgraph_decide_inlining): New variable redo_always_inline.
	Flattening and always_inlining loop until callgraph stabilizes.
	* ipa-prop.c (update_call_notes_after_inlining): Returns boolean,
	true iff new cgraph edges have been created.
	(propagate_info_to_inlined_callees): Likewise.
	(ipa_propagate_indirect_call_infos): Likewise.

From-SVN: r140293
This commit is contained in:
Martin Jambor 2008-09-11 19:03:23 +02:00 committed by Martin Jambor
parent 420da8caae
commit f8e2a1ed3b
6 changed files with 267 additions and 190 deletions

View File

@ -1,3 +1,66 @@
2008-09-11 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (struct ipa_param_flags): Removed.
(struct ipa_param_descriptor): New structure.
(struct ipa_node_params): ipcp_lattices, param_decls and
param_flags moved to ipa_param_description.
(ipa_get_ith_param): Renamed to ipa_get_param, changed to access
descriptors. Renamed all users.
(ipa_is_ith_param_modified): Renamed to ipa_is_param_modified,
changed to access descriptors. Renamed all users.
(ipa_is_ith_param_called): Renamed to ipa_is_param_called, changed
to access descriptors. Renamed all users.
* ipa-cp.c (ipcp_init_cloned_node): Call
ipa_initialize_node_params instead of ipa_count_formal_params and
ipa_create_param_decls_array.
(ipcp_analyze_node): Likewise.
(ipcp_get_ith_lattice): Renamed to ipcp_get_lattice, changed to access
descriptors. Renamed all users.
(ipcp_initialize_node_lattices): Remove allocation.
* ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
ipa_initialize_node_params instead of ipa_count_formal_params and
ipa_create_param_decls_array.
* ipa-prop.c (ipa_create_param_decls_array): Renamed to
ipa_populate_param_decls, made static, added parameter info,
renamed mt to node, removed allocation, changed to use
descriptors.
(ipa_count_formal_params): Made static, added parameter info,
renamed mt to node.
(ipa_initialize_node_params): New function.
(ipa_check_stmt_modifications): Changed to use descriptors.
(ipa_detect_param_modifications): Removed allocation, changed to
use descriptors.
(ipa_note_param_call): Changed to use descriptors.
(ipa_analyze_params_uses): Removed allocation.
(ipa_free_node_params_substructures): Changed to use descriptors.
(ipa_edge_duplication_hook): Use the unused attribute.
(ipa_node_duplication_hook): Use the unused attribute, changed to
use descriptors, changed to duplicate descriptors.
* ipa-inline.c (cgraph_mark_inline_edge): New parameter new_edges,
changed all callers. Call ipa_propagate_indirect_call_infos if doing
indirect inlining. Made static.
(cgraph_decide_inlining): Freeing ipa-prop structures after inlining
functions called only once.
(cgraph_decide_recursive_inlining): Don't call
ipa_propagate_indirect_call_infos, pass new_edges to
cgraph_mark_inline_edge instead.
(cgraph_decide_inlining_of_small_functions): Don't call
ipa_propagate_indirect_call_infos, pass new_edges to
cgraph_mark_inline_edge instead.
(cgraph_decide_inlining): Don't call
ipa_propagate_indirect_call_infos.
* ipa-prop.c: Check that vectors are allocated.
* ipa-inline.c (cgraph_mark_inline_edge): Returns boolean, true
iff a new cgraph edges have been created.
(cgraph_decide_inlining): New variable redo_always_inline.
Flattening and always_inlining loop until callgraph stabilizes.
* ipa-prop.c (update_call_notes_after_inlining): Returns boolean,
true iff new cgraph edges have been created.
(propagate_info_to_inlined_callees): Likewise.
(ipa_propagate_indirect_call_infos): Likewise.
2008-09-11 Richard Guenther <rguenther@suse.de>
* tree-vectorizer.c (slpeel_add_loop_guard): Fix types.

View File

@ -452,7 +452,6 @@ varpool_next_static_initializer (struct varpool_node *node)
/* In ipa-inline.c */
void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool, bool);
void cgraph_mark_inline_edge (struct cgraph_edge *, bool);
bool cgraph_default_inline_p (struct cgraph_node *, const char **);
unsigned int compute_inline_parameters (struct cgraph_node *);

View File

@ -171,9 +171,8 @@ ipcp_init_cloned_node (struct cgraph_node *orig_node,
struct cgraph_node *new_node)
{
ipa_check_create_node_params ();
ipa_initialize_node_params (new_node);
IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node;
ipa_count_formal_params (new_node);
ipa_create_param_decls_array (new_node);
}
/* Perform intraprocedrual analysis needed for ipcp. */
@ -183,8 +182,7 @@ ipcp_analyze_node (struct cgraph_node *node)
/* Unreachable nodes should have been eliminated before ipcp. */
gcc_assert (node->needed || node->reachable);
ipa_count_formal_params (node);
ipa_create_param_decls_array (node);
ipa_initialize_node_params (node);
ipa_detect_param_modifications (node);
}
@ -300,9 +298,9 @@ ipa_lattice_meet (struct ipcp_lattice *res, struct ipcp_lattice *lat1,
/* Return the lattice corresponding to the Ith formal parameter of the function
described by INFO. */
static inline struct ipcp_lattice *
ipcp_get_ith_lattice (struct ipa_node_params *info, int i)
ipcp_get_lattice (struct ipa_node_params *info, int i)
{
return &(info->ipcp_lattices[i]);
return &(info->params[i].ipcp_lattice);
}
/* Given the jump function JFUNC, compute the lattice LAT that describes the
@ -321,7 +319,7 @@ ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
{
struct ipcp_lattice *caller_lat;
caller_lat = ipcp_get_ith_lattice (info, jfunc->value.formal_id);
caller_lat = ipcp_get_lattice (info, jfunc->value.formal_id);
lat->type = caller_lat->type;
lat->constant = caller_lat->constant;
}
@ -364,7 +362,7 @@ ipcp_print_all_lattices (FILE * f)
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
fprintf (f, " param [%d]: ", i);
if (lat->type == IPA_CONST_VALUE)
@ -485,9 +483,6 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
struct ipa_node_params *info = IPA_NODE_REF (node);
enum ipa_lattice_type type;
info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice,
ipa_get_param_count (info));
if (ipa_is_called_with_var_arguments (info))
type = IPA_BOTTOM;
else if (!node->needed)
@ -500,7 +495,7 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
type = IPA_BOTTOM;
for (i = 0; i < ipa_get_param_count (info) ; i++)
ipcp_get_ith_lattice (info, i)->type = type;
ipcp_get_lattice (info, i)->type = type;
}
/* build INTEGER_CST tree with type TREE_TYPE and value according to LAT.
@ -596,14 +591,14 @@ ipcp_change_tops_to_bottom (void)
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
if (lat->type == IPA_TOP)
{
prop_again = true;
if (dump_file)
{
fprintf (dump_file, "Forcing param ");
print_generic_expr (dump_file, ipa_get_ith_param (info, i), 0);
print_generic_expr (dump_file, ipa_get_param (info, i), 0);
fprintf (dump_file, " of node %s to bottom.\n",
cgraph_node_name (node));
}
@ -651,7 +646,7 @@ ipcp_propagate_stage (void)
{
jump_func = ipa_get_ith_jump_func (args, i);
ipcp_lattice_from_jfunc (info, &inc_lat, jump_func);
dest_lat = ipcp_get_ith_lattice (callee_info, i);
dest_lat = ipcp_get_lattice (callee_info, i);
ipa_lattice_meet (&new_lat, &inc_lat, dest_lat);
if (ipcp_lattice_changed (&new_lat, dest_lat))
{
@ -917,7 +912,7 @@ ipcp_need_redirect_p (struct cgraph_edge *cs)
count = ipa_get_param_count (orig_callee_info);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (orig_callee_info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (orig_callee_info, i);
if (ipcp_lat_is_const (lat))
{
jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
@ -946,8 +941,8 @@ ipcp_update_callgraph (void)
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
tree parm_tree = ipa_get_ith_param (info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
tree parm_tree = ipa_get_param (info, i);
/* We can proactively remove obviously unused arguments. */
if (is_gimple_reg (parm_tree)
@ -1069,8 +1064,8 @@ ipcp_estimate_growth (struct cgraph_node *node)
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
tree parm_tree = ipa_get_ith_param (info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
tree parm_tree = ipa_get_param (info, i);
/* We can proactively remove obviously unused arguments. */
if (is_gimple_reg (parm_tree)
@ -1142,8 +1137,8 @@ ipcp_const_param_count (struct cgraph_node *node)
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
tree parm_tree = ipa_get_ith_param (info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
tree parm_tree = ipa_get_param (info, i);
if (ipcp_lat_is_insertable (lat)
/* Do not count obviously unused arguments. */
&& (!is_gimple_reg (parm_tree)
@ -1242,8 +1237,8 @@ ipcp_insert_stage (void)
args_to_skip = BITMAP_ALLOC (NULL);
for (i = 0; i < count; i++)
{
struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
parm_tree = ipa_get_ith_param (info, i);
struct ipcp_lattice *lat = ipcp_get_lattice (info, i);
parm_tree = ipa_get_param (info, i);
/* We can proactively remove obviously unused arguments. */
if (is_gimple_reg (parm_tree)

View File

@ -243,15 +243,19 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
cgraph_clone_inlined_nodes (e, duplicate, update_original);
}
/* Mark edge E as inlined and update callgraph accordingly.
UPDATE_ORIGINAL specify whether profile of original function should be
updated. */
/* Mark edge E as inlined and update callgraph accordingly. UPDATE_ORIGINAL
specify whether profile of original function should be updated. If any new
indirect edges are discovered in the process, add them to NEW_EDGES, unless
it is NULL. Return true iff any new callgraph edges were discovered as a
result of inlining. */
void
cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original)
static bool
cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
VEC (cgraph_edge_p, heap) **new_edges)
{
int old_insns = 0, new_insns = 0;
struct cgraph_node *to = NULL, *what;
struct cgraph_edge *curr = e;
if (e->callee->inline_decl)
cgraph_redirect_edge_callee (e, cgraph_node (e->callee->inline_decl));
@ -281,6 +285,11 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original)
if (new_insns > old_insns)
overall_insns += new_insns - old_insns;
ncalls_inlined++;
if (flag_indirect_inlining)
return ipa_propagate_indirect_call_infos (curr, new_edges);
else
return false;
}
/* Mark all calls of EDGE->CALLEE inlined into EDGE->CALLER.
@ -302,7 +311,7 @@ cgraph_mark_inline (struct cgraph_edge *edge)
next = e->next_caller;
if (e->caller == to && e->inline_failed)
{
cgraph_mark_inline_edge (e, true);
cgraph_mark_inline_edge (e, true, NULL);
if (e == edge)
edge = next;
}
@ -747,9 +756,7 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node,
fprintf (dump_file, "\n");
}
cgraph_redirect_edge_callee (curr, master_clone);
cgraph_mark_inline_edge (curr, false);
if (flag_indirect_inlining)
ipa_propagate_indirect_call_infos (curr, new_edges);
cgraph_mark_inline_edge (curr, false, new_edges);
lookup_recursive_calls (node, curr->callee, heap);
n++;
}
@ -1002,12 +1009,10 @@ cgraph_decide_inlining_of_small_functions (void)
continue;
}
callee = edge->callee;
cgraph_mark_inline_edge (edge, true);
cgraph_mark_inline_edge (edge, true, &new_indirect_edges);
if (flag_indirect_inlining)
{
ipa_propagate_indirect_call_infos (edge, &new_indirect_edges);
add_new_edges_to_heap (heap, new_indirect_edges);
}
add_new_edges_to_heap (heap, new_indirect_edges);
update_callee_keys (heap, callee, updated_nodes);
}
where = edge->caller;
@ -1070,6 +1075,7 @@ cgraph_decide_inlining (void)
int old_insns = 0;
int i;
int initial_insns = 0;
bool redo_always_inline = true;
cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
@ -1103,69 +1109,70 @@ cgraph_decide_inlining (void)
/* In the first pass mark all always_inline edges. Do this with a priority
so none of our later choices will make this impossible. */
for (i = nnodes - 1; i >= 0; i--)
while (redo_always_inline)
{
struct cgraph_edge *e, *next;
node = order[i];
/* Handle nodes to be flattened, but don't update overall unit size. */
if (lookup_attribute ("flatten", DECL_ATTRIBUTES (node->decl)) != NULL)
{
if (dump_file)
fprintf (dump_file,
"Flattening %s\n", cgraph_node_name (node));
cgraph_decide_inlining_incrementally (node, INLINE_ALL, 0);
}
if (!node->local.disregard_inline_limits)
continue;
if (dump_file)
fprintf (dump_file,
"\nConsidering %s %i insns (always inline)\n",
cgraph_node_name (node), node->global.insns);
old_insns = overall_insns;
for (e = node->callers; e; e = next)
redo_always_inline = false;
for (i = nnodes - 1; i >= 0; i--)
{
next = e->next_caller;
if (!e->inline_failed || gimple_call_cannot_inline_p (e->call_stmt))
continue;
if (cgraph_recursive_inlining_p (e->caller, e->callee,
&e->inline_failed))
continue;
if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
struct cgraph_edge *e, *next;
node = order[i];
/* Handle nodes to be flattened, but don't update overall unit
size. */
if (lookup_attribute ("flatten",
DECL_ATTRIBUTES (node->decl)) != NULL)
{
gimple_call_set_cannot_inline (e->call_stmt, true);
continue;
if (dump_file)
fprintf (dump_file,
"Flattening %s\n", cgraph_node_name (node));
cgraph_decide_inlining_incrementally (node, INLINE_ALL, 0);
}
cgraph_mark_inline_edge (e, true);
if (flag_indirect_inlining)
ipa_propagate_indirect_call_infos (e, NULL);
if (!node->local.disregard_inline_limits)
continue;
if (dump_file)
fprintf (dump_file,
" Inlined into %s which now has %i insns.\n",
cgraph_node_name (e->caller),
e->caller->global.insns);
"\nConsidering %s %i insns (always inline)\n",
cgraph_node_name (node), node->global.insns);
old_insns = overall_insns;
for (e = node->callers; e; e = next)
{
next = e->next_caller;
if (!e->inline_failed
|| gimple_call_cannot_inline_p (e->call_stmt))
continue;
if (cgraph_recursive_inlining_p (e->caller, e->callee,
&e->inline_failed))
continue;
if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
{
gimple_call_set_cannot_inline (e->call_stmt, true);
continue;
}
if (cgraph_mark_inline_edge (e, true, NULL))
redo_always_inline = true;
if (dump_file)
fprintf (dump_file,
" Inlined into %s which now has %i insns.\n",
cgraph_node_name (e->caller),
e->caller->global.insns);
}
/* Inlining self recursive function might introduce new calls to
themselves we didn't see in the loop above. Fill in the proper
reason why inline failed. */
for (e = node->callers; e; e = e->next_caller)
if (e->inline_failed)
e->inline_failed = N_("recursive inlining");
if (dump_file)
fprintf (dump_file,
" Inlined for a net change of %+i insns.\n",
overall_insns - old_insns);
}
/* Inlining self recursive function might introduce new calls to
themselves we didn't see in the loop above. Fill in the proper
reason why inline failed. */
for (e = node->callers; e; e = e->next_caller)
if (e->inline_failed)
e->inline_failed = N_("recursive inlining");
if (dump_file)
fprintf (dump_file,
" Inlined for a net change of %+i insns.\n",
overall_insns - old_insns);
}
cgraph_decide_inlining_of_small_functions ();
/* After this point, any edge discovery performed by indirect inlining is no
good so let's give up. */
if (flag_indirect_inlining)
free_all_ipa_structures_after_iinln ();
if (flag_inline_functions_called_once)
{
if (dump_file)
@ -1220,6 +1227,10 @@ cgraph_decide_inlining (void)
}
}
/* Free ipa-prop structures if they are no longer needed. */
if (flag_indirect_inlining)
free_all_ipa_structures_after_iinln ();
if (dump_file)
fprintf (dump_file,
"\nInlined %i calls, eliminated %i functions, "
@ -1635,8 +1646,7 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
if (!flag_ipa_cp)
{
ipa_count_formal_params (node);
ipa_create_param_decls_array (node);
ipa_initialize_node_params (node);
ipa_detect_param_modifications (node);
}
ipa_analyze_params_uses (node);

View File

@ -102,52 +102,67 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree)
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
if (ipa_get_ith_param(info, i) == ptree)
if (ipa_get_param(info, i) == ptree)
return i;
return -1;
}
/* Insert the formal trees to the param_decls array in function MT. */
void
ipa_create_param_decls_array (struct cgraph_node *mt)
/* Populate the param_decl field in parameter descriptors of INFO that
corresponds to NODE. */
static void
ipa_populate_param_decls (struct cgraph_node *node,
struct ipa_node_params *info)
{
tree fndecl;
tree fnargs;
tree parm;
int param_num;
struct ipa_node_params *info = IPA_NODE_REF (mt);
if (info->param_decls)
return;
info->param_decls = XCNEWVEC (tree, ipa_get_param_count (info));
fndecl = mt->decl;
fndecl = node->decl;
fnargs = DECL_ARGUMENTS (fndecl);
param_num = 0;
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
{
info->param_decls[param_num] = parm;
info->params[param_num].decl = parm;
param_num++;
}
}
/* Count number of formals in MT. Insert the result to the
ipa_node_params. */
void
ipa_count_formal_params (struct cgraph_node *mt)
/* Count number of formal parameters in NOTE. Store the result to the
appropriate field of INFO. */
static void
ipa_count_formal_params (struct cgraph_node *node,
struct ipa_node_params *info)
{
tree fndecl;
tree fnargs;
tree parm;
int param_num;
fndecl = mt->decl;
fndecl = node->decl;
fnargs = DECL_ARGUMENTS (fndecl);
param_num = 0;
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
param_num++;
ipa_set_param_count (IPA_NODE_REF (mt), param_num);
ipa_set_param_count (info, param_num);
}
/* Initialize the ipa_node_params structure associated with NODE by counting
the function parameters, creating the descriptors and populating their
param_decls. */
void
ipa_initialize_node_params (struct cgraph_node *node)
{
struct ipa_node_params *info = IPA_NODE_REF (node);
if (!info->params)
{
ipa_count_formal_params (node, info);
info->params = XCNEWVEC (struct ipa_param_descriptor,
ipa_get_param_count (info));
ipa_populate_param_decls (node, info);
}
}
/* Check STMT to detect whether a formal parameter is directly modified within
@ -173,13 +188,13 @@ ipa_check_stmt_modifications (struct ipa_node_params *info, gimple stmt)
lhs = SSA_NAME_VAR (lhs);
index = ipa_get_param_decl_index (info, lhs);
if (index >= 0)
info->param_flags[index].modified = true;
info->params[index].modified = true;
break;
case GIMPLE_ASM:
/* Asm code could modify any of the parameters. */
for (j = 0; j < ipa_get_param_count (info); j++)
info->param_flags[j].modified = true;
info->params[j].modified = true;
break;
default:
@ -205,10 +220,6 @@ ipa_detect_param_modifications (struct cgraph_node *node)
if (ipa_get_param_count (info) == 0 || info->modification_analysis_done)
return;
if (!info->param_flags)
info->param_flags = XCNEWVEC (struct ipa_param_flags,
ipa_get_param_count (info));
func = DECL_STRUCT_FUNCTION (decl);
FOR_EACH_BB_FN (bb, func)
{
@ -221,8 +232,8 @@ ipa_detect_param_modifications (struct cgraph_node *node)
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
if (TREE_ADDRESSABLE (ipa_get_ith_param (info, i)))
info->param_flags[i].modified = true;
if (TREE_ADDRESSABLE (ipa_get_param (info, i)))
info->params[i].modified = true;
info->modification_analysis_done = 1;
}
@ -402,7 +413,7 @@ compute_pass_through_member_ptrs (struct ipa_node_params *info,
int index = ipa_get_param_decl_index (info, arg);
gcc_assert (index >=0);
if (!ipa_is_ith_param_modified (info, index))
if (!ipa_is_param_modified (info, index))
{
functions[num].type = IPA_PASS_THROUGH;
functions[num].value.formal_id = index;
@ -613,7 +624,7 @@ ipa_note_param_call (struct ipa_node_params *info, int formal_id,
struct ipa_param_call_note *note;
basic_block bb = gimple_bb (stmt);
info->param_flags[formal_id].called = 1;
info->params[formal_id].called = 1;
note = XCNEW (struct ipa_param_call_note);
note->formal_id = formal_id;
@ -788,7 +799,7 @@ ipa_analyze_call_uses (struct ipa_node_params *info, gimple call)
return;
index = ipa_get_param_decl_index (info, rec);
if (index >= 0 && !ipa_is_ith_param_modified (info, index))
if (index >= 0 && !ipa_is_param_modified (info, index))
ipa_note_param_call (info, index, call);
return;
@ -818,9 +829,6 @@ ipa_analyze_params_uses (struct cgraph_node *node)
if (ipa_get_param_count (info) == 0 || info->uses_analysis_done)
return;
if (!info->param_flags)
info->param_flags = XCNEWVEC (struct ipa_param_flags,
ipa_get_param_count (info));
func = DECL_STRUCT_FUNCTION (decl);
FOR_EACH_BB_FN (bb, func)
@ -891,8 +899,8 @@ print_edge_addition_message (FILE *f, struct ipa_param_call_note *nt,
assuming NODE is (potentially indirectly) inlined into CS->callee.
Moreover, if the callee is discovered to be constant, create a new cgraph
edge for it. Newly discovered indirect edges will be added to *NEW_EDGES,
unless NEW_EDGES is NULL. */
static void
unless NEW_EDGES is NULL. Return true iff a new edge(s) were created. */
static bool
update_call_notes_after_inlining (struct cgraph_edge *cs,
struct cgraph_node *node,
VEC (cgraph_edge_p, heap) **new_edges)
@ -900,6 +908,7 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
struct ipa_node_params *info = IPA_NODE_REF (node);
struct ipa_edge_args *top = IPA_EDGE_REF (cs);
struct ipa_param_call_note *nt;
bool res = false;
for (nt = info->param_calls; nt; nt = nt->next)
{
@ -940,6 +949,7 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
if (!callee || !callee->local.inlinable)
continue;
res = true;
if (dump_file)
print_edge_addition_message (dump_file, nt, jfunc, node);
@ -953,6 +963,7 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
top = IPA_EDGE_REF (cs);
}
}
return res;
}
/* Recursively traverse subtree of NODE (including node) made of inlined
@ -960,32 +971,43 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
update_call_notes_after_inlining on all nodes and
update_jump_functions_after_inlining on all non-inlined edges that lead out
of this subtree. Newly discovered indirect edges will be added to
*NEW_EDGES, unless NEW_EDGES is NULL. */
static void
*NEW_EDGES, unless NEW_EDGES is NULL. Return true iff a new edge(s) were
created. */
static bool
propagate_info_to_inlined_callees (struct cgraph_edge *cs,
struct cgraph_node *node,
VEC (cgraph_edge_p, heap) **new_edges)
{
struct cgraph_edge *e;
bool res;
update_call_notes_after_inlining (cs, node, new_edges);
res = update_call_notes_after_inlining (cs, node, new_edges);
for (e = node->callees; e; e = e->next_callee)
if (!e->inline_failed)
propagate_info_to_inlined_callees (cs, e->callee, new_edges);
res |= propagate_info_to_inlined_callees (cs, e->callee, new_edges);
else
update_jump_functions_after_inlining (cs, e);
return res;
}
/* Update jump functions and call note functions on inlining the call site CS.
CS is expected to lead to a node already cloned by
cgraph_clone_inline_nodes. Newly discovered indirect edges will be added to
*NEW_EDGES, unless NEW_EDGES is NULL. */
void
*NEW_EDGES, unless NEW_EDGES is NULL. Return true iff a new edge(s) were +
created. */
bool
ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
VEC (cgraph_edge_p, heap) **new_edges)
{
propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
/* Do nothing if the preparation phase has not been carried out yet
(i.e. during early inlining). */
if (!ipa_node_params_vector)
return false;
gcc_assert (ipa_edge_args_vector);
return propagate_info_to_inlined_callees (cs, cs->callee, new_edges);
}
/* Frees all dynamically allocated structures that the argument info points
@ -1020,12 +1042,8 @@ ipa_free_all_edge_args (void)
void
ipa_free_node_params_substructures (struct ipa_node_params *info)
{
if (info->ipcp_lattices)
free (info->ipcp_lattices);
if (info->param_decls)
free (info->param_decls);
if (info->param_flags)
free (info->param_flags);
if (info->params)
free (info->params);
while (info->param_calls)
{
@ -1091,7 +1109,7 @@ duplicate_array (void *src, size_t n)
/* Hook that is called by cgraph.c when a node is duplicated. */
static void
ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
void *data)
__attribute__((unused)) void *data)
{
struct ipa_edge_args *old_args, *new_args;
int arg_count;
@ -1106,13 +1124,12 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
new_args->jump_functions = (struct ipa_jump_func *)
duplicate_array (old_args->jump_functions,
sizeof (struct ipa_jump_func) * arg_count);
data = data; /* Suppressing compiler warning. */
}
/* Hook that is called by cgraph.c when a node is duplicated. */
static void
ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
void *data)
__attribute__((unused)) void *data)
{
struct ipa_node_params *old_info, *new_info;
struct ipa_param_call_note *note;
@ -1124,15 +1141,9 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
param_count = ipa_get_param_count (old_info);
ipa_set_param_count (new_info, param_count);
new_info->ipcp_lattices = (struct ipcp_lattice *)
duplicate_array (old_info->ipcp_lattices,
sizeof (struct ipcp_lattice) * param_count);
new_info->param_decls = (tree *)
duplicate_array (old_info->param_decls, sizeof (tree) * param_count);
new_info->param_flags = (struct ipa_param_flags *)
duplicate_array (old_info->param_flags,
sizeof (struct ipa_param_flags) * param_count);
new_info->params = (struct ipa_param_descriptor *)
duplicate_array (old_info->params,
sizeof (struct ipa_param_descriptor) * param_count);
new_info->ipcp_orig_node = old_info->ipcp_orig_node;
new_info->count_scale = old_info->count_scale;
@ -1146,8 +1157,6 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
nn->next = new_info->param_calls;
new_info->param_calls = nn;
}
data = data; /* Suppressing compiler warning. */
}
/* Register our cgraph hooks if they are not already there. */
@ -1221,13 +1230,13 @@ ipa_print_node_params (FILE * f, struct cgraph_node *node)
count = ipa_get_param_count (info);
for (i = 0; i < count; i++)
{
temp = ipa_get_ith_param (info, i);
temp = ipa_get_param (info, i);
if (TREE_CODE (temp) == PARM_DECL)
fprintf (f, " param %d : %s", i,
(*lang_hooks.decl_printable_name) (temp, 2));
if (ipa_is_ith_param_modified (info, i))
if (ipa_is_param_modified (info, i))
fprintf (f, " modified");
if (ipa_is_ith_param_called (info, i))
if (ipa_is_param_called (info, i))
fprintf (f, " called");
fprintf (f, "\n");
}

View File

@ -110,16 +110,6 @@ struct ipa_replace_map
bool ref_p;
};
/* ipa_param_flags contains various flags that describe how the associated
parameter is treated within a function. */
struct ipa_param_flags
{
/* Whether the value parameter has been modified within the function. */
unsigned modified : 1;
/* Whether the parameter has been used as a call destination. */
unsigned called : 1;
};
/* Each instance of the following structure describes a statement that calls a
function parameter. Those referring to statements within the same function
are linked in a list. */
@ -144,6 +134,19 @@ struct ipa_param_call_note
bool processed;
};
/* Structure describing a single formal parameter. */
struct ipa_param_descriptor
{
/* IPA-CP lattice. */
struct ipcp_lattice ipcp_lattice;
/* PARAM_DECL of this parameter. */
tree decl;
/* Whether the value parameter has been modified within the function. */
unsigned modified : 1;
/* Whether the parameter has been used as a call destination. */
unsigned called : 1;
};
/* ipa_node_params stores information related to formal parameters of functions
and some other information for interprocedural passes that operate on
parameters (such as ipa-cp). */
@ -153,12 +156,9 @@ struct ipa_node_params
this function's parameters would not be analyzed by the different
stages of IPA CP. */
int param_count;
/* Array of lattices. */
struct ipcp_lattice *ipcp_lattices;
/* Mapping each parameter to its PARM_DECL tree. */
tree *param_decls;
/* Various flags describing individual parameters. */
struct ipa_param_flags *param_flags;
/* Pointer to an array of structures describing individual formal
parameters. */
struct ipa_param_descriptor *params;
/* List of structures enumerating calls to a formal parameter. */
struct ipa_param_call_note *param_calls;
/* Only for versioned nodes this field would not be NULL,
@ -197,31 +197,33 @@ ipa_get_param_count (struct ipa_node_params *info)
return info->param_count;
}
/* Returns the declaration of ith param of the corresponding node. Note there
is no setter function as this array is built just once using
ipa_create_param_decls_array. */
/* Return the declaration of Ith formal parameter of the function corresponding
to INFO. Note there is no setter function as this array is built just once
using ipa_initialize_node_params. */
static inline tree
ipa_get_ith_param (struct ipa_node_params *info, int i)
ipa_get_param (struct ipa_node_params *info, int i)
{
return info->param_decls[i];
return info->params[i].decl;
}
/* Returns the modification flag corresponding to the ith parameter. Note
there is no setter method as the goal is to set all flags when building the
array in ipa_detect_param_modifications. */
/* Return the modification flag corresponding to the Ith formal parameter of
the function associated with INFO. Note that there is no setter method as
the goal is to set all flags when building the array in
ipa_detect_param_modifications. */
static inline bool
ipa_is_ith_param_modified (struct ipa_node_params *info, int i)
ipa_is_param_modified (struct ipa_node_params *info, int i)
{
return info->param_flags[i].modified;
return info->params[i].modified;
}
/* Returns the called flag corresponding o the ith paramterer. Note there is
no setter method as the goal is to set all flags when building the array in
/* Return the called flag corresponding to the Ith formal parameter of the
function associated with INFO. Note that there is no setter method as the
goal is to set all flags when building the array in
ipa_detect_called_params. */
static inline bool
ipa_is_ith_param_called (struct ipa_node_params *info, int i)
ipa_is_param_called (struct ipa_node_params *info, int i)
{
return info->param_flags[i].called;
return info->params[i].called;
}
/* Flag this node as having callers with variable number of arguments. */
@ -372,12 +374,11 @@ struct cgraph_node *ipa_pop_func_from_list (struct ipa_func_list **);
void ipa_compute_jump_functions (struct cgraph_edge *);
void ipa_count_arguments (struct cgraph_edge *);
/* Function parameters related computations. */
void ipa_count_formal_params (struct cgraph_node *);
void ipa_create_param_decls_array (struct cgraph_node *);
/* Function formal parameters related computations. */
void ipa_initialize_node_params (struct cgraph_node *node);
void ipa_detect_param_modifications (struct cgraph_node *);
void ipa_analyze_params_uses (struct cgraph_node *);
void ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
VEC (cgraph_edge_p, heap) **new_edges);
/* Debugging interface. */