diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-04-18 20:30:45 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-04-18 18:30:45 +0000 |
commit | e86a910ff5b8ecfeeeb1e57bffcb85887b771f9a (patch) | |
tree | f13c9287e9f4b5d2d24d112f7c85d5f4ecf6d4ce /gcc/ipa-inline.c | |
parent | fc45aeeeeccfe9e81f7e9619188c5450b1550634 (diff) | |
download | gcc-e86a910ff5b8ecfeeeb1e57bffcb85887b771f9a.tar.gz |
ipa-inline.c (spec_rem): New static variable.
* ipa-inline.c (spec_rem): New static variable.
(dump_overall_stats): New function.
(dump_inline_stats): New function.
From-SVN: r209522
Diffstat (limited to 'gcc/ipa-inline.c')
-rw-r--r-- | gcc/ipa-inline.c | 138 |
1 files changed, 135 insertions, 3 deletions
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index e8f03be397b..1b7a74e0745 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -127,6 +127,7 @@ along with GCC; see the file COPYING3. If not see static int overall_size; static gcov_type max_count; static sreal max_count_real, max_relbenefit_real, half_int_min_real; +static gcov_type spec_rem; /* Return false when inlining edge E would lead to violating limits on function unit growth or stack usage growth. @@ -1533,6 +1534,7 @@ resolve_noninline_speculation (fibheap_t edge_heap, struct cgraph_edge *edge) ? node->global.inlined_to : node; bitmap updated_nodes = BITMAP_ALLOC (NULL); + spec_rem += edge->count; cgraph_resolve_speculation (edge, NULL); reset_edge_caches (where); inline_update_overall_summary (where); @@ -1996,6 +1998,130 @@ inline_to_all_callers (struct cgraph_node *node, void *data) return false; } +/* Output overall time estimate. */ +static void +dump_overall_stats (void) +{ + HOST_WIDEST_INT sum_weighted = 0, sum = 0; + struct cgraph_node *node; + + FOR_EACH_DEFINED_FUNCTION (node) + if (!node->global.inlined_to + && !node->alias) + { + int time = inline_summary (node)->time; + sum += time; + sum_weighted += time * node->count; + } + fprintf (dump_file, "Overall time estimate: " + HOST_WIDEST_INT_PRINT_DEC" weighted by profile: " + HOST_WIDEST_INT_PRINT_DEC"\n", sum, sum_weighted); +} + +/* Output some useful stats about inlining. */ + +static void +dump_inline_stats (void) +{ + HOST_WIDEST_INT inlined_cnt = 0, inlined_indir_cnt = 0; + HOST_WIDEST_INT inlined_virt_cnt = 0, inlined_virt_indir_cnt = 0; + HOST_WIDEST_INT noninlined_cnt = 0, noninlined_indir_cnt = 0; + HOST_WIDEST_INT noninlined_virt_cnt = 0, noninlined_virt_indir_cnt = 0; + HOST_WIDEST_INT inlined_speculative = 0, inlined_speculative_ply = 0; + HOST_WIDEST_INT indirect_poly_cnt = 0, indirect_cnt = 0; + HOST_WIDEST_INT reason[CIF_N_REASONS][3]; + int i; + struct cgraph_node *node; + + memset (reason, 0, sizeof (reason)); + FOR_EACH_DEFINED_FUNCTION (node) + { + struct cgraph_edge *e; + for (e = node->callees; e; e = e->next_callee) + { + if (e->inline_failed) + { + reason[(int) e->inline_failed][0] += e->count; + reason[(int) e->inline_failed][1] += e->frequency; + reason[(int) e->inline_failed][2] ++; + if (DECL_VIRTUAL_P (e->callee->decl)) + { + if (e->indirect_inlining_edge) + noninlined_virt_indir_cnt += e->count; + else + noninlined_virt_cnt += e->count; + } + else + { + if (e->indirect_inlining_edge) + noninlined_indir_cnt += e->count; + else + noninlined_cnt += e->count; + } + } + else + { + if (e->speculative) + { + if (DECL_VIRTUAL_P (e->callee->decl)) + inlined_speculative_ply += e->count; + else + inlined_speculative += e->count; + } + else if (DECL_VIRTUAL_P (e->callee->decl)) + { + if (e->indirect_inlining_edge) + inlined_virt_indir_cnt += e->count; + else + inlined_virt_cnt += e->count; + } + else + { + if (e->indirect_inlining_edge) + inlined_indir_cnt += e->count; + else + inlined_cnt += e->count; + } + } + } + for (e = node->indirect_calls; e; e = e->next_callee) + if (e->indirect_info->polymorphic) + indirect_poly_cnt += e->count; + else + indirect_cnt += e->count; + } + if (max_count) + { + fprintf (dump_file, + "Inlined " HOST_WIDEST_INT_PRINT_DEC " + speculative " + HOST_WIDEST_INT_PRINT_DEC " + speculative polymorphic " + HOST_WIDEST_INT_PRINT_DEC " + previously indirect " + HOST_WIDEST_INT_PRINT_DEC " + virtual " + HOST_WIDEST_INT_PRINT_DEC " + virtual and previously indirect " + HOST_WIDEST_INT_PRINT_DEC "\n" "Not inlined " + HOST_WIDEST_INT_PRINT_DEC " + previously indirect " + HOST_WIDEST_INT_PRINT_DEC " + virtual " + HOST_WIDEST_INT_PRINT_DEC " + virtual and previously indirect " + HOST_WIDEST_INT_PRINT_DEC " + stil indirect " + HOST_WIDEST_INT_PRINT_DEC " + still indirect polymorphic " + HOST_WIDEST_INT_PRINT_DEC "\n", inlined_cnt, + inlined_speculative, inlined_speculative_ply, + inlined_indir_cnt, inlined_virt_cnt, inlined_virt_indir_cnt, + noninlined_cnt, noninlined_indir_cnt, noninlined_virt_cnt, + noninlined_virt_indir_cnt, indirect_cnt, indirect_poly_cnt); + fprintf (dump_file, + "Removed speculations " HOST_WIDEST_INT_PRINT_DEC "\n", + spec_rem); + } + dump_overall_stats (); + fprintf (dump_file, "\nWhy inlining failed?\n"); + for (i = 0; i < CIF_N_REASONS; i++) + if (reason[i][2]) + fprintf (dump_file, "%-50s: %8i calls, %8i freq, "HOST_WIDEST_INT_PRINT_DEC" count\n", + cgraph_inline_failed_string ((cgraph_inline_failed_t) i), + (int) reason[i][2], (int) reason[i][1], reason[i][0]); +} + /* Decide on the inlining. We do so in the topological order to avoid expenses on updating data structures. */ @@ -2048,6 +2174,8 @@ ipa_inline (void) flatten_function (node, false); } } + if (dump_file) + dump_overall_stats (); inline_small_functions (); @@ -2092,6 +2220,7 @@ ipa_inline (void) if (edge->speculative && !speculation_useful_p (edge, false)) { cgraph_resolve_speculation (edge, NULL); + spec_rem += edge->count; update = true; remove_functions = true; } @@ -2122,9 +2251,12 @@ ipa_inline (void) ipa_free_all_structures_after_iinln (); if (dump_file) - fprintf (dump_file, - "\nInlined %i calls, eliminated %i functions\n\n", - ncalls_inlined, nfunctions_inlined); + { + fprintf (dump_file, + "\nInlined %i calls, eliminated %i functions\n\n", + ncalls_inlined, nfunctions_inlined); + dump_inline_stats (); + } if (dump_file) dump_inline_summaries (dump_file); |