From f8e2a1ed3b746951a5d07e03f91d1f8209ebe775 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Thu, 11 Sep 2008 19:03:23 +0200 Subject: [PATCH] ipa-prop.h (struct ipa_param_flags): Removed. 2008-09-11 Martin Jambor * 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 --- gcc/ChangeLog | 63 ++++++++++++++++++++ gcc/cgraph.h | 1 - gcc/ipa-cp.c | 43 ++++++-------- gcc/ipa-inline.c | 146 +++++++++++++++++++++++++---------------------- gcc/ipa-prop.c | 135 +++++++++++++++++++++++-------------------- gcc/ipa-prop.h | 69 +++++++++++----------- 6 files changed, 267 insertions(+), 190 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 + + * 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 * 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; - - 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, + "\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 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. */