summaryrefslogtreecommitdiff
path: root/gcc/ipa-inline.c
diff options
context:
space:
mode:
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-23 19:45:45 +0000
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2008-07-23 19:45:45 +0000
commitf8daee9bad3067f34c8061fc0fcb2f9dc9525a1b (patch)
tree425c693ef81efc3a4ab38d1ddfbc42bc63047cc2 /gcc/ipa-inline.c
parent5cd72fe59d2227a76053c6e4f80ca59dce966a20 (diff)
downloadgcc-f8daee9bad3067f34c8061fc0fcb2f9dc9525a1b.tar.gz
2008-07-23 Martin Jambor <mjambor@suse.cz>
* ipa-cp.c (ipcp_print_edge_profiles): Test for node->analyzed rather than for DECL_SAVED_TREE. * ipa-prop.c: Include diagnostic.h. (ipa_check_stmt_modifications): Check LHS of GIMPLE_MODIFY_EXPRs thoroughly. (ipa_detect_param_modifications): Function rewritten from scratch. (ipa_compute_jump_functions): Changed accesses to modification flags. (ipa_free_node_params_substructures): Update flags destruction. (ipa_node_duplication_hook): Update flags duplication. (ipa_print_all_params_modified): Updated flag access. * ipa-prop.h (struct ipa_param_flags): New structure. (struct ipa_node_params): New field modification_analysis_done, modified_flags changed into param_flags. (ipa_is_ith_param_modified): Changed to use new flags. * Makefile.in (ipa-prop.o): Add $(DIAGNOSTIC_H) to dependencies. * ipa-prop.c (ipa_print_all_jump_functions): Moved here from ipa-cp.c and split into two functions. (ipa_print_node_jump_functions): New function. (compute_scalar_jump_functions): New function. (type_like_member_ptr_p): New function. (compute_pass_through_member_ptrs): New function. (fill_member_ptr_cst_jump_function): New function. (determine_cst_member_ptr): New function. (compute_cst_member_ptr_arguments): New function. (ipa_compute_jump_functions): Complete rewrite. * ipa-prop.h (enum jump_func_type): Make explicit that we depend on IPA_UNKNOWN being zero. Added value IPA_CONST_MEMBER_PTR. (struct ipa_member_ptr_cst): New structure. (union jump_func_value): New field member_cst. * ipa-cp.c (ipcp_lat_is_insertable): New function. (ipcp_lattice_from_jfunc): Produces bottom lattices for unhandled jump function types. (ipcp_print_all_lattices): Slight fprintf rearrangement. (ipcp_print_all_structures): Call ipa_print_all_jump_functions instead of ipcp_print_all_jump_functions. (ipcp_insert_stage): Use ipcp_lat_is_insertable, create replace maps only for replacable scalars. * doc/invoke.texi (Optimize options): Add description of -findirect-inlining. * common.opt (flag_indirect_inlining): New flag. * opts.c (decode_options): Set flag_indirect_inlining when optimize >= 3. * ipa-inline.c: Include ipa-prop.h. (inline_indirect_intraprocedural_analysis): New function. (inline_generate_summary): Allocate parameter and argument info structures, call inline_indirect_intraprocedural_analysis on each node when doing indirect inlining and deallocate indirect inlining data structures in the end. * ipa-prop.c (ipa_create_param_decls_array): Return if already done. (free_all_ipa_structures_after_iinln): New function. (free_all_ipa_structures_after_ipa_cp): Checks whether iinln will be done. * Makefile.in (ipa-inline.o): Added $(IPA_PROP_H) to dependencies. * cgraphbuild.c (compute_call_stmt_bb_frequency): New function. (build_cgraph_edges): Call compute_call_stmt_bb_frequency instead of computing the frequency separately. (rebuild_cgraph_edges): Call compute_call_stmt_bb_frequency instead of computing the frequency separately. * ipa-cp.c (ipcp_print_all_structures): Replace a call to ipa_print_all_param_modified with a call to ipa_print_all_param_flags. * ipa-prop.c (ipa_get_member_ptr_load_param): New function. (ipa_get_stmt_member_ptr_load_param): New function. (ipa_is_ssa_with_stmt_def): New function. (ipa_note_param_call): New function. (ipa_analyze_call_uses): New function. (ipa_analyze_stmt_uses): New function. (ipa_analyze_params_uses): New function. (ipa_free_node_params_substructures): Also free the param_calls linked list. (ipa_node_duplication_hook): Also duplicate the param_calls linked list. (ipa_print_node_param_flags): New function. (ipa_print_all_params_modified): Renamed to ipa_print_all_param_flags. (ipa_print_all_param_flags): Calls ipa_print_node_param_flags. * ipa-prop.h (struct ipa_param_flags): New field called. (struct ipa_param_call_note): New structure. (struct ipa_node_params): New fields param_calls and uses_analysis_done. (ipa_is_ith_param_called): New function. * ipa-inline.c (inline_indirect_intraprocedural_analysis): Call ipa_analyze_params_uses and dump parameter flags. * ipa-inline.c (cgraph_decide_recursive_inlining): Call ipa_propagate_indirect_call_infos if performing indirect inlining, pass a new parameter new_edges to it. (add_new_edges_to_heap): New fucntion. (cgraph_decide_inlining_of_small_functions): New vector new_indirect_edges for newly found indirect edges , call ipa_propagate_indirect_call_infos after inlining. (cgraph_decide_inlining): Call ipa_propagate_indirect_call_infos after inlining if performing indirect inlining. Call free_all_ipa_structures_after_iinln when doing so too. (inline_generate_summary): Do not call free_all_ipa_structures_after_iinln here. * ipa-prop.c (update_jump_functions_after_inlining): New function. (print_edge_addition_message): New function. (update_call_notes_after_inlining): New function. (propagate_info_to_inlined_callees): New function. (ipa_propagate_indirect_call_infos): New function. * ipa-prop.h: Include cgraph.h (struct ipa_param_call_note): Fields reordered, new field processed. * cgraph.h (cgraph_edge): Shrink loop_nest field to 31 bits, add a new flag indirect_call. * cgraphunit.c (verify_cgraph_node): Allow indirect edges not to have rediscovered call statements. * cgraph.c (cgraph_create_edge): Initialize indirect_call to zero. (dump_cgraph_node): Dump also the indirect_call flag. (cgraph_clone_edge): Copy also the indirect_call flag. * tree-inline.c (copy_bb): Do not check for fndecls from call expressions, check for edge availability when moving clones. (get_indirect_callee_fndecl): New function. (expand_call_inline): If callee declaration is not apprent from the statement, try calling get_indirect_callee_fndecl. Do not issue warnings or call sorry when not inlinings an indirect edge. * Makefile.in (IPA_PROP_H): Added $(CGRAPH_H) to dependencies. * ipa-prop.c (ipa_print_node_param_flags): Make the dump format a bit more frandly to matching. * testsuite/g++.dg/ipa/iinline-1.C: New testcase. * testsuite/gcc.dg/ipa/iinline-1.c: New testcase. * testsuite/gcc.dg/ipa/modif-1.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138092 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-inline.c')
-rw-r--r--gcc/ipa-inline.c82
1 files changed, 79 insertions, 3 deletions
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index b7f1597691a..3683ec772ac 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -139,6 +139,7 @@ along with GCC; see the file COPYING3. If not see
#include "ggc.h"
#include "tree-flow.h"
#include "rtl.h"
+#include "ipa-prop.h"
/* Mode incremental inliner operate on:
@@ -660,10 +661,12 @@ lookup_recursive_calls (struct cgraph_node *node, struct cgraph_node *where,
}
/* Decide on recursive inlining: in the case function has recursive calls,
- inline until body size reaches given argument. */
+ inline until body size reaches given argument. If any new indirect edges
+ are discovered in the process, add them to NEW_EDGES, unless it is NULL. */
static bool
-cgraph_decide_recursive_inlining (struct cgraph_node *node)
+cgraph_decide_recursive_inlining (struct cgraph_node *node,
+ VEC (cgraph_edge_p, heap) *new_edges)
{
int limit = PARAM_VALUE (PARAM_MAX_INLINE_INSNS_RECURSIVE_AUTO);
int max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH_AUTO);
@@ -760,6 +763,8 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node)
}
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);
lookup_recursive_calls (node, curr->callee, heap);
n++;
}
@@ -817,6 +822,20 @@ compute_max_insns (int insns)
* (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH)) / 100);
}
+/* Compute badness of all edges in NEW_EDGES and add them to the HEAP. */
+static void
+add_new_edges_to_heap (fibheap_t heap, VEC (cgraph_edge_p, heap) *new_edges)
+{
+ while (VEC_length (cgraph_edge_p, new_edges) > 0)
+ {
+ struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges);
+
+ gcc_assert (!edge->aux);
+ edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge), edge);
+ }
+}
+
+
/* We use greedy algorithm for inlining of small functions:
All inline candidates are put into prioritized heap based on estimated
growth of the overall number of instructions and then update the estimates.
@@ -833,6 +852,10 @@ cgraph_decide_inlining_of_small_functions (void)
fibheap_t heap = fibheap_new ();
bitmap updated_nodes = BITMAP_ALLOC (NULL);
int min_insns, max_insns;
+ VEC (cgraph_edge_p, heap) *new_indirect_edges = NULL;
+
+ if (flag_indirect_inlining)
+ new_indirect_edges = VEC_alloc (cgraph_edge_p, heap, 8);
if (dump_file)
fprintf (dump_file, "\nDeciding on smaller functions:\n");
@@ -968,8 +991,10 @@ cgraph_decide_inlining_of_small_functions (void)
where = edge->caller;
if (where->global.inlined_to)
where = where->global.inlined_to;
- if (!cgraph_decide_recursive_inlining (where))
+ if (!cgraph_decide_recursive_inlining (where, new_indirect_edges))
continue;
+ if (flag_indirect_inlining)
+ add_new_edges_to_heap (heap, new_indirect_edges);
update_callee_keys (heap, where, updated_nodes);
}
else
@@ -986,6 +1011,11 @@ cgraph_decide_inlining_of_small_functions (void)
}
callee = edge->callee;
cgraph_mark_inline_edge (edge, true);
+ if (flag_indirect_inlining)
+ {
+ ipa_propagate_indirect_call_infos (edge, new_indirect_edges);
+ add_new_edges_to_heap (heap, new_indirect_edges);
+ }
update_callee_keys (heap, callee, updated_nodes);
}
where = edge->caller;
@@ -1028,6 +1058,9 @@ cgraph_decide_inlining_of_small_functions (void)
&edge->inline_failed))
edge->inline_failed = N_("--param inline-unit-growth limit reached");
}
+
+ if (new_indirect_edges)
+ VEC_free (cgraph_edge_p, heap, new_indirect_edges);
fibheap_delete (heap);
BITMAP_FREE (updated_nodes);
}
@@ -1112,6 +1145,8 @@ cgraph_decide_inlining (void)
continue;
}
cgraph_mark_inline_edge (e, true);
+ if (flag_indirect_inlining)
+ ipa_propagate_indirect_call_infos (e, NULL);
if (dump_file)
fprintf (dump_file,
" Inlined into %s which now has %i insns.\n",
@@ -1133,6 +1168,11 @@ cgraph_decide_inlining (void)
if (!flag_really_no_inline)
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_really_no_inline
&& flag_inline_functions_called_once)
{
@@ -1612,6 +1652,31 @@ struct gimple_opt_pass pass_inline_parameters =
}
};
+/* This function performs intraprocedural analyzis in NODE that is required to
+ inline indirect calls. */
+static void
+inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
+{
+ struct cgraph_edge *cs;
+
+ ipa_count_formal_params (node);
+ ipa_create_param_decls_array (node);
+ ipa_detect_param_modifications (node);
+ ipa_analyze_params_uses (node);
+
+ if (dump_file)
+ ipa_print_node_param_flags (dump_file, node);
+
+ for (cs = node->callees; cs; cs = cs->next_callee)
+ {
+ ipa_count_arguments (cs);
+ ipa_compute_jump_functions (cs);
+ }
+
+ if (dump_file)
+ ipa_print_node_jump_functions (dump_file, node);
+}
+
/* Note function body size. */
static void
inline_generate_summary (void)
@@ -1621,6 +1686,13 @@ inline_generate_summary (void)
int nnodes = cgraph_postorder (order);
int i;
+ if (flag_indirect_inlining)
+ {
+ ipa_register_cgraph_hooks ();
+ ipa_check_create_node_params ();
+ ipa_check_create_edge_args ();
+ }
+
for (i = nnodes - 1; i >= 0; i--)
{
struct cgraph_node *node = order[i];
@@ -1632,6 +1704,10 @@ inline_generate_summary (void)
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
current_function_decl = node->decl;
compute_inline_parameters (node);
+
+ if (flag_indirect_inlining)
+ inline_indirect_intraprocedural_analysis (node);
+
pop_cfun ();
}
}