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:
parent
420da8caae
commit
f8e2a1ed3b
@ -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.
|
||||
|
@ -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 *);
|
||||
|
||||
|
43
gcc/ipa-cp.c
43
gcc/ipa-cp.c
@ -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)
|
||||
|
146
gcc/ipa-inline.c
146
gcc/ipa-inline.c
@ -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);
|
||||
|
135
gcc/ipa-prop.c
135
gcc/ipa-prop.c
@ -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");
|
||||
}
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user