summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog63
-rw-r--r--gcc/cgraph.h1
-rw-r--r--gcc/ipa-cp.c43
-rw-r--r--gcc/ipa-inline.c140
-rw-r--r--gcc/ipa-prop.c135
-rw-r--r--gcc/ipa-prop.h69
6 files changed, 264 insertions, 187 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 33de0138db0..aaec4d73a8b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index eec56a53903..a6018dc8910 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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 *);
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 8f1c1614cd8..8dbc9f87f99 100644
--- a/gcc/ipa-cp.c
+++ b/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)
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 88566fed007..662cff60b50 100644
--- a/gcc/ipa-inline.c
+++ b/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;
+ redo_always_inline = false;
+ for (i = nnodes - 1; i >= 0; i--)
+ {
+ struct cgraph_edge *e, *next;
- node = order[i];
+ 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);
- }
+ /* 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)
- {
- next = e->next_caller;
- if (!e->inline_failed || gimple_call_cannot_inline_p (e->call_stmt))
+ if (!node->local.disregard_inline_limits)
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))
+ 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)
{
- gimple_call_set_cannot_inline (e->call_stmt, true);
- continue;
+ 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);
}
- cgraph_mark_inline_edge (e, true);
- if (flag_indirect_inlining)
- ipa_propagate_indirect_call_infos (e, NULL);
+ /* 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 into %s which now has %i insns.\n",
- cgraph_node_name (e->caller),
- e->caller->global.insns);
+ " 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);
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index f8b73439ed9..90b0333e783 100644
--- a/gcc/ipa-prop.c
+++ b/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");
}
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index c1bc1a2003a..47010e1ab59 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -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. */