Message ID | 3e71f4974dee623dfa99fa6722b9d0fc5eae3c99.1601403165.git.mjambor@suse.cz |
---|---|
State | New |
Headers | show |
Series | IPA cleanups and IPA-CP improvements for 548.exchange2_r | expand |
> A subsequent patch adds another two estimates that the code in > ipa_call_context::estimate_size_and_time computes, and the fact that > the function has a special output parameter for each thing it computes > would make it have just too many. Therefore, this patch collapses all > those ouptut parameters into one output structure. > > gcc/ChangeLog: > > 2020-09-02 Martin Jambor <mjambor@suse.cz> > > * ipa-inline-analysis.c (do_estimate_edge_time): Adjusted to use > ipa_call_estimates. > (do_estimate_edge_size): Likewise. > (do_estimate_edge_hints): Likewise. > * ipa-fnsummary.h (struct ipa_call_estimates): New type. > (ipa_call_context::estimate_size_and_time): Adjusted declaration. > (estimate_ipcp_clone_size_and_time): Likewise. > * ipa-cp.c (hint_time_bonus): Changed the type of the second argument > to ipa_call_estimates. > (perform_estimation_of_a_value): Adjusted to use ipa_call_estimates. > (estimate_local_effects): Likewise. > * ipa-fnsummary.c (ipa_call_context::estimate_size_and_time): Adjusted > to return estimates in a single ipa_call_estimates parameter. > (estimate_ipcp_clone_size_and_time): Likewise. OK, Honza > --- > gcc/ipa-cp.c | 45 ++++++++++++++--------------- > gcc/ipa-fnsummary.c | 60 +++++++++++++++++++-------------------- > gcc/ipa-fnsummary.h | 36 +++++++++++++++++------ > gcc/ipa-inline-analysis.c | 47 +++++++++++++++++------------- > 4 files changed, 105 insertions(+), 83 deletions(-) > > diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c > index 292dd7e5bdf..77c84a6ed5d 100644 > --- a/gcc/ipa-cp.c > +++ b/gcc/ipa-cp.c > @@ -3196,12 +3196,13 @@ devirtualization_time_bonus (struct cgraph_node *node, > return res; > } > > -/* Return time bonus incurred because of HINTS. */ > +/* Return time bonus incurred because of hints stored in ESTIMATES. */ > > static int > -hint_time_bonus (cgraph_node *node, ipa_hints hints) > +hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates) > { > int result = 0; > + ipa_hints hints = estimates.hints; > if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) > result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus); > return result; > @@ -3397,15 +3398,13 @@ perform_estimation_of_a_value (cgraph_node *node, > int removable_params_cost, int est_move_cost, > ipcp_value_base *val) > { > - int size, time_benefit; > - sreal time, base_time; > - ipa_hints hints; > + int time_benefit; > + ipa_call_estimates estimates; > > - estimate_ipcp_clone_size_and_time (node, avals, &size, &time, > - &base_time, &hints); > - base_time -= time; > - if (base_time > 65535) > - base_time = 65535; > + estimate_ipcp_clone_size_and_time (node, avals, &estimates); > + sreal time_delta = estimates.nonspecialized_time - estimates.time; > + if (time_delta > 65535) > + time_delta = 65535; > > /* Extern inline functions have no cloning local time benefits because they > will be inlined anyway. The only reason to clone them is if it enables > @@ -3413,11 +3412,12 @@ perform_estimation_of_a_value (cgraph_node *node, > if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl)) > time_benefit = 0; > else > - time_benefit = base_time.to_int () > + time_benefit = time_delta.to_int () > + devirtualization_time_bonus (node, avals) > - + hint_time_bonus (node, hints) > + + hint_time_bonus (node, estimates) > + removable_params_cost + est_move_cost; > > + int size = estimates.size; > gcc_checking_assert (size >=0); > /* The inliner-heuristics based estimates may think that in certain > contexts some functions do not have any size at all but we want > @@ -3472,23 +3472,21 @@ estimate_local_effects (struct cgraph_node *node) > || (removable_params_cost && node->can_change_signature)) > { > struct caller_statistics stats; > - ipa_hints hints; > - sreal time, base_time; > - int size; > + ipa_call_estimates estimates; > > init_caller_stats (&stats); > node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, > false); > - estimate_ipcp_clone_size_and_time (node, &avals, &size, &time, > - &base_time, &hints); > - time -= devirt_bonus; > - time -= hint_time_bonus (node, hints); > - time -= removable_params_cost; > - size -= stats.n_calls * removable_params_cost; > + estimate_ipcp_clone_size_and_time (node, &avals, &estimates); > + sreal time = estimates.nonspecialized_time - estimates.time; > + time += devirt_bonus; > + time += hint_time_bonus (node, estimates); > + time += removable_params_cost; > + int size = estimates.size - stats.n_calls * removable_params_cost; > > if (dump_file) > fprintf (dump_file, " - context independent values, size: %i, " > - "time_benefit: %f\n", size, (base_time - time).to_double ()); > + "time_benefit: %f\n", size, (time).to_double ()); > > if (size <= 0 || node->local) > { > @@ -3499,8 +3497,7 @@ estimate_local_effects (struct cgraph_node *node) > "known contexts, code not going to grow.\n"); > } > else if (good_cloning_opportunity_p (node, > - MIN ((base_time - time).to_int (), > - 65536), > + MIN ((time).to_int (), 65536), > stats.freq_sum, stats.count_sum, > size)) > { > diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c > index 4ef7d2570e9..6082f34d63f 100644 > --- a/gcc/ipa-fnsummary.c > +++ b/gcc/ipa-fnsummary.c > @@ -3536,18 +3536,14 @@ ipa_call_context::equal_to (const ipa_call_context &ctx) > return true; > } > > -/* Estimate size and time needed to execute call in the given context. > - Additionally determine hints determined by the context. Finally compute > - minimal size needed for the call that is independent on the call context and > - can be used for fast estimates. Return the values in RET_SIZE, > - RET_MIN_SIZE, RET_TIME and RET_HINTS. */ > +/* Fill in the selected fields in ESTIMATES with value estimated for call in > + this context. Always compute size and min_size. Only compute time and > + nonspecialized_time if EST_TIMES is true. Only compute hints if EST_HINTS > + is true. */ > > void > -ipa_call_context::estimate_size_and_time (int *ret_size, > - int *ret_min_size, > - sreal *ret_time, > - sreal *ret_nonspecialized_time, > - ipa_hints *ret_hints) > +ipa_call_context::estimate_size_and_time (ipa_call_estimates *estimates, > + bool est_times, bool est_hints) > { > class ipa_fn_summary *info = ipa_fn_summaries->get (m_node); > size_time_entry *e; > @@ -3577,8 +3573,8 @@ ipa_call_context::estimate_size_and_time (int *ret_size, > > if (m_node->callees || m_node->indirect_calls) > estimate_calls_size_and_time (m_node, &size, &min_size, > - ret_time ? &time : NULL, > - ret_hints ? &hints : NULL, m_possible_truths, > + est_times ? &time : NULL, > + est_hints ? &hints : NULL, m_possible_truths, > &m_avals); > > sreal nonspecialized_time = time; > @@ -3605,7 +3601,7 @@ ipa_call_context::estimate_size_and_time (int *ret_size, > known to be constant in a specialized setting. */ > if (nonconst) > size += e->size; > - if (!ret_time) > + if (!est_times) > continue; > nonspecialized_time += e->time; > if (!nonconst) > @@ -3645,7 +3641,7 @@ ipa_call_context::estimate_size_and_time (int *ret_size, > if (time > nonspecialized_time) > time = nonspecialized_time; > > - if (ret_hints) > + if (est_hints) > { > if (info->loop_iterations > && !info->loop_iterations->evaluate (m_possible_truths)) > @@ -3663,18 +3659,23 @@ ipa_call_context::estimate_size_and_time (int *ret_size, > min_size = RDIV (min_size, ipa_fn_summary::size_scale); > > if (dump_file && (dump_flags & TDF_DETAILS)) > - fprintf (dump_file, "\n size:%i time:%f nonspec time:%f\n", (int) size, > - time.to_double (), nonspecialized_time.to_double ()); > - if (ret_time) > - *ret_time = time; > - if (ret_nonspecialized_time) > - *ret_nonspecialized_time = nonspecialized_time; > - if (ret_size) > - *ret_size = size; > - if (ret_min_size) > - *ret_min_size = min_size; > - if (ret_hints) > - *ret_hints = hints; > + { > + if (est_times) > + fprintf (dump_file, "\n size:%i time:%f nonspec time:%f\n", > + (int) size, time.to_double (), > + nonspecialized_time.to_double ()); > + else > + fprintf (dump_file, "\n size:%i (time not estimated)\n", (int) size); > + } > + if (est_times) > + { > + estimates->time = time; > + estimates->nonspecialized_time = nonspecialized_time; > + } > + estimates->size = size; > + estimates->min_size = min_size; > + if (est_hints) > + estimates->hints = hints; > return; > } > > @@ -3687,17 +3688,14 @@ ipa_call_context::estimate_size_and_time (int *ret_size, > void > estimate_ipcp_clone_size_and_time (struct cgraph_node *node, > ipa_auto_call_arg_values *avals, > - int *ret_size, sreal *ret_time, > - sreal *ret_nonspec_time, > - ipa_hints *hints) > + ipa_call_estimates *estimates) > { > clause_t clause, nonspec_clause; > > evaluate_conditions_for_known_args (node, false, avals, &clause, > &nonspec_clause); > ipa_call_context ctx (node, clause, nonspec_clause, vNULL, avals); > - ctx.estimate_size_and_time (ret_size, NULL, ret_time, > - ret_nonspec_time, hints); > + ctx.estimate_size_and_time (estimates); > } > > /* Return stack frame offset where frame of NODE is supposed to start inside > diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h > index 020a6f0425d..ccb6b432f0b 100644 > --- a/gcc/ipa-fnsummary.h > +++ b/gcc/ipa-fnsummary.h > @@ -287,6 +287,29 @@ public: > ipa_call_summary *dst_data); > }; > > +/* Estimated execution times, code sizes and other information about the > + code executing a call described by ipa_call_context. */ > + > +struct ipa_call_estimates > +{ > + /* Estimated size needed to execute call in the given context. */ > + int size; > + > + /* Minimal size needed for the call that is + independent on the call context > + and can be used for fast estimates. */ > + int min_size; > + > + /* Estimated time needed to execute call in the given context. */ > + sreal time; > + > + /* Estimated time needed to execute the function when not ignoring > + computations known to be constant in this context. */ > + sreal nonspecialized_time; > + > + /* Further discovered reasons why to inline or specialize the give calls. */ > + ipa_hints hints; > +}; > + > class ipa_cached_call_context; > > /* This object describe a context of call. That is a summary of known > @@ -305,10 +328,8 @@ public: > : m_node(NULL) > { > } > - void estimate_size_and_time (int *ret_size, int *ret_min_size, > - sreal *ret_time, > - sreal *ret_nonspecialized_time, > - ipa_hints *ret_hints); > + void estimate_size_and_time (ipa_call_estimates *estimates, > + bool est_times = true, bool est_hints = true); > bool equal_to (const ipa_call_context &); > bool exists_p () > { > @@ -353,10 +374,9 @@ void ipa_dump_hints (FILE *f, ipa_hints); > void ipa_free_fn_summary (void); > void ipa_free_size_summary (void); > void inline_analyze_function (struct cgraph_node *node); > -void estimate_ipcp_clone_size_and_time (struct cgraph_node *, > - ipa_auto_call_arg_values *, > - int *, sreal *, sreal *, > - ipa_hints *); > +void estimate_ipcp_clone_size_and_time (struct cgraph_node *node, > + ipa_auto_call_arg_values *avals, > + ipa_call_estimates *estimates); > void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge); > void ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset = true); > void compute_fn_summary (struct cgraph_node *, bool); > diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c > index b7af77f7b9b..acbf82e84d9 100644 > --- a/gcc/ipa-inline-analysis.c > +++ b/gcc/ipa-inline-analysis.c > @@ -208,16 +208,12 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) > && !opt_for_fn (callee->decl, flag_profile_partial_training) > && !callee->count.ipa_p ()) > { > - sreal chk_time, chk_nonspec_time; > - int chk_size, chk_min_size; > - > - ipa_hints chk_hints; > - ctx.estimate_size_and_time (&chk_size, &chk_min_size, > - &chk_time, &chk_nonspec_time, > - &chk_hints); > - gcc_assert (chk_size == size && chk_time == time > - && chk_nonspec_time == nonspec_time > - && chk_hints == hints); > + ipa_call_estimates chk_estimates; > + ctx.estimate_size_and_time (&chk_estimates); > + gcc_assert (chk_estimates.size == size > + && chk_estimates.time == time > + && chk_estimates.nonspecialized_time == nonspec_time > + && chk_estimates.hints == hints); > } > } > else > @@ -227,18 +223,28 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) > else > node_context_cache_clear++; > e->entry.ctx.release (); > - ctx.estimate_size_and_time (&size, &min_size, > - &time, &nonspec_time, &hints); > + ipa_call_estimates estimates; > + ctx.estimate_size_and_time (&estimates); > + size = estimates.size; > e->entry.size = size; > + time = estimates.time; > e->entry.time = time; > + nonspec_time = estimates.nonspecialized_time; > e->entry.nonspec_time = nonspec_time; > + hints = estimates.hints; > e->entry.hints = hints; > e->entry.ctx.duplicate_from (ctx); > } > } > else > - ctx.estimate_size_and_time (&size, &min_size, > - &time, &nonspec_time, &hints); > + { > + ipa_call_estimates estimates; > + ctx.estimate_size_and_time (&estimates); > + size = estimates.size; > + time = estimates.time; > + nonspec_time = estimates.nonspecialized_time; > + hints = estimates.hints; > + } > > /* When we have profile feedback, we can quite safely identify hot > edges and for those we disable size limits. Don't do that when > @@ -321,8 +327,9 @@ do_estimate_edge_size (struct cgraph_edge *edge) > evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause, > &avals, true); > ipa_call_context ctx (callee, clause, nonspec_clause, vNULL, &avals); > - ctx.estimate_size_and_time (&size, NULL, NULL, NULL, NULL); > - return size; > + ipa_call_estimates estimates; > + ctx.estimate_size_and_time (&estimates, false, false); > + return estimates.size; > } > > > @@ -332,7 +339,6 @@ do_estimate_edge_size (struct cgraph_edge *edge) > ipa_hints > do_estimate_edge_hints (struct cgraph_edge *edge) > { > - ipa_hints hints; > struct cgraph_node *callee; > clause_t clause, nonspec_clause; > > @@ -341,7 +347,7 @@ do_estimate_edge_hints (struct cgraph_edge *edge) > if (edge_growth_cache != NULL) > { > do_estimate_edge_time (edge); > - hints = edge_growth_cache->get (edge)->hints; > + ipa_hints hints = edge_growth_cache->get (edge)->hints; > gcc_checking_assert (hints); > return hints - 1; > } > @@ -354,8 +360,9 @@ do_estimate_edge_hints (struct cgraph_edge *edge) > evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause, > &avals, true); > ipa_call_context ctx (callee, clause, nonspec_clause, vNULL, &avals); > - ctx.estimate_size_and_time (NULL, NULL, NULL, NULL, &hints); > - hints |= simple_edge_hints (edge); > + ipa_call_estimates estimates; > + ctx.estimate_size_and_time (&estimates, false, true); > + ipa_hints hints = estimates.hints | simple_edge_hints (edge); > return hints; > } > > -- > 2.28.0 >
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 292dd7e5bdf..77c84a6ed5d 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -3196,12 +3196,13 @@ devirtualization_time_bonus (struct cgraph_node *node, return res; } -/* Return time bonus incurred because of HINTS. */ +/* Return time bonus incurred because of hints stored in ESTIMATES. */ static int -hint_time_bonus (cgraph_node *node, ipa_hints hints) +hint_time_bonus (cgraph_node *node, const ipa_call_estimates &estimates) { int result = 0; + ipa_hints hints = estimates.hints; if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) result += opt_for_fn (node->decl, param_ipa_cp_loop_hint_bonus); return result; @@ -3397,15 +3398,13 @@ perform_estimation_of_a_value (cgraph_node *node, int removable_params_cost, int est_move_cost, ipcp_value_base *val) { - int size, time_benefit; - sreal time, base_time; - ipa_hints hints; + int time_benefit; + ipa_call_estimates estimates; - estimate_ipcp_clone_size_and_time (node, avals, &size, &time, - &base_time, &hints); - base_time -= time; - if (base_time > 65535) - base_time = 65535; + estimate_ipcp_clone_size_and_time (node, avals, &estimates); + sreal time_delta = estimates.nonspecialized_time - estimates.time; + if (time_delta > 65535) + time_delta = 65535; /* Extern inline functions have no cloning local time benefits because they will be inlined anyway. The only reason to clone them is if it enables @@ -3413,11 +3412,12 @@ perform_estimation_of_a_value (cgraph_node *node, if (DECL_EXTERNAL (node->decl) && DECL_DECLARED_INLINE_P (node->decl)) time_benefit = 0; else - time_benefit = base_time.to_int () + time_benefit = time_delta.to_int () + devirtualization_time_bonus (node, avals) - + hint_time_bonus (node, hints) + + hint_time_bonus (node, estimates) + removable_params_cost + est_move_cost; + int size = estimates.size; gcc_checking_assert (size >=0); /* The inliner-heuristics based estimates may think that in certain contexts some functions do not have any size at all but we want @@ -3472,23 +3472,21 @@ estimate_local_effects (struct cgraph_node *node) || (removable_params_cost && node->can_change_signature)) { struct caller_statistics stats; - ipa_hints hints; - sreal time, base_time; - int size; + ipa_call_estimates estimates; init_caller_stats (&stats); node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false); - estimate_ipcp_clone_size_and_time (node, &avals, &size, &time, - &base_time, &hints); - time -= devirt_bonus; - time -= hint_time_bonus (node, hints); - time -= removable_params_cost; - size -= stats.n_calls * removable_params_cost; + estimate_ipcp_clone_size_and_time (node, &avals, &estimates); + sreal time = estimates.nonspecialized_time - estimates.time; + time += devirt_bonus; + time += hint_time_bonus (node, estimates); + time += removable_params_cost; + int size = estimates.size - stats.n_calls * removable_params_cost; if (dump_file) fprintf (dump_file, " - context independent values, size: %i, " - "time_benefit: %f\n", size, (base_time - time).to_double ()); + "time_benefit: %f\n", size, (time).to_double ()); if (size <= 0 || node->local) { @@ -3499,8 +3497,7 @@ estimate_local_effects (struct cgraph_node *node) "known contexts, code not going to grow.\n"); } else if (good_cloning_opportunity_p (node, - MIN ((base_time - time).to_int (), - 65536), + MIN ((time).to_int (), 65536), stats.freq_sum, stats.count_sum, size)) { diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 4ef7d2570e9..6082f34d63f 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -3536,18 +3536,14 @@ ipa_call_context::equal_to (const ipa_call_context &ctx) return true; } -/* Estimate size and time needed to execute call in the given context. - Additionally determine hints determined by the context. Finally compute - minimal size needed for the call that is independent on the call context and - can be used for fast estimates. Return the values in RET_SIZE, - RET_MIN_SIZE, RET_TIME and RET_HINTS. */ +/* Fill in the selected fields in ESTIMATES with value estimated for call in + this context. Always compute size and min_size. Only compute time and + nonspecialized_time if EST_TIMES is true. Only compute hints if EST_HINTS + is true. */ void -ipa_call_context::estimate_size_and_time (int *ret_size, - int *ret_min_size, - sreal *ret_time, - sreal *ret_nonspecialized_time, - ipa_hints *ret_hints) +ipa_call_context::estimate_size_and_time (ipa_call_estimates *estimates, + bool est_times, bool est_hints) { class ipa_fn_summary *info = ipa_fn_summaries->get (m_node); size_time_entry *e; @@ -3577,8 +3573,8 @@ ipa_call_context::estimate_size_and_time (int *ret_size, if (m_node->callees || m_node->indirect_calls) estimate_calls_size_and_time (m_node, &size, &min_size, - ret_time ? &time : NULL, - ret_hints ? &hints : NULL, m_possible_truths, + est_times ? &time : NULL, + est_hints ? &hints : NULL, m_possible_truths, &m_avals); sreal nonspecialized_time = time; @@ -3605,7 +3601,7 @@ ipa_call_context::estimate_size_and_time (int *ret_size, known to be constant in a specialized setting. */ if (nonconst) size += e->size; - if (!ret_time) + if (!est_times) continue; nonspecialized_time += e->time; if (!nonconst) @@ -3645,7 +3641,7 @@ ipa_call_context::estimate_size_and_time (int *ret_size, if (time > nonspecialized_time) time = nonspecialized_time; - if (ret_hints) + if (est_hints) { if (info->loop_iterations && !info->loop_iterations->evaluate (m_possible_truths)) @@ -3663,18 +3659,23 @@ ipa_call_context::estimate_size_and_time (int *ret_size, min_size = RDIV (min_size, ipa_fn_summary::size_scale); if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\n size:%i time:%f nonspec time:%f\n", (int) size, - time.to_double (), nonspecialized_time.to_double ()); - if (ret_time) - *ret_time = time; - if (ret_nonspecialized_time) - *ret_nonspecialized_time = nonspecialized_time; - if (ret_size) - *ret_size = size; - if (ret_min_size) - *ret_min_size = min_size; - if (ret_hints) - *ret_hints = hints; + { + if (est_times) + fprintf (dump_file, "\n size:%i time:%f nonspec time:%f\n", + (int) size, time.to_double (), + nonspecialized_time.to_double ()); + else + fprintf (dump_file, "\n size:%i (time not estimated)\n", (int) size); + } + if (est_times) + { + estimates->time = time; + estimates->nonspecialized_time = nonspecialized_time; + } + estimates->size = size; + estimates->min_size = min_size; + if (est_hints) + estimates->hints = hints; return; } @@ -3687,17 +3688,14 @@ ipa_call_context::estimate_size_and_time (int *ret_size, void estimate_ipcp_clone_size_and_time (struct cgraph_node *node, ipa_auto_call_arg_values *avals, - int *ret_size, sreal *ret_time, - sreal *ret_nonspec_time, - ipa_hints *hints) + ipa_call_estimates *estimates) { clause_t clause, nonspec_clause; evaluate_conditions_for_known_args (node, false, avals, &clause, &nonspec_clause); ipa_call_context ctx (node, clause, nonspec_clause, vNULL, avals); - ctx.estimate_size_and_time (ret_size, NULL, ret_time, - ret_nonspec_time, hints); + ctx.estimate_size_and_time (estimates); } /* Return stack frame offset where frame of NODE is supposed to start inside diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h index 020a6f0425d..ccb6b432f0b 100644 --- a/gcc/ipa-fnsummary.h +++ b/gcc/ipa-fnsummary.h @@ -287,6 +287,29 @@ public: ipa_call_summary *dst_data); }; +/* Estimated execution times, code sizes and other information about the + code executing a call described by ipa_call_context. */ + +struct ipa_call_estimates +{ + /* Estimated size needed to execute call in the given context. */ + int size; + + /* Minimal size needed for the call that is + independent on the call context + and can be used for fast estimates. */ + int min_size; + + /* Estimated time needed to execute call in the given context. */ + sreal time; + + /* Estimated time needed to execute the function when not ignoring + computations known to be constant in this context. */ + sreal nonspecialized_time; + + /* Further discovered reasons why to inline or specialize the give calls. */ + ipa_hints hints; +}; + class ipa_cached_call_context; /* This object describe a context of call. That is a summary of known @@ -305,10 +328,8 @@ public: : m_node(NULL) { } - void estimate_size_and_time (int *ret_size, int *ret_min_size, - sreal *ret_time, - sreal *ret_nonspecialized_time, - ipa_hints *ret_hints); + void estimate_size_and_time (ipa_call_estimates *estimates, + bool est_times = true, bool est_hints = true); bool equal_to (const ipa_call_context &); bool exists_p () { @@ -353,10 +374,9 @@ void ipa_dump_hints (FILE *f, ipa_hints); void ipa_free_fn_summary (void); void ipa_free_size_summary (void); void inline_analyze_function (struct cgraph_node *node); -void estimate_ipcp_clone_size_and_time (struct cgraph_node *, - ipa_auto_call_arg_values *, - int *, sreal *, sreal *, - ipa_hints *); +void estimate_ipcp_clone_size_and_time (struct cgraph_node *node, + ipa_auto_call_arg_values *avals, + ipa_call_estimates *estimates); void ipa_merge_fn_summary_after_inlining (struct cgraph_edge *edge); void ipa_update_overall_fn_summary (struct cgraph_node *node, bool reset = true); void compute_fn_summary (struct cgraph_node *, bool); diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index b7af77f7b9b..acbf82e84d9 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -208,16 +208,12 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) && !opt_for_fn (callee->decl, flag_profile_partial_training) && !callee->count.ipa_p ()) { - sreal chk_time, chk_nonspec_time; - int chk_size, chk_min_size; - - ipa_hints chk_hints; - ctx.estimate_size_and_time (&chk_size, &chk_min_size, - &chk_time, &chk_nonspec_time, - &chk_hints); - gcc_assert (chk_size == size && chk_time == time - && chk_nonspec_time == nonspec_time - && chk_hints == hints); + ipa_call_estimates chk_estimates; + ctx.estimate_size_and_time (&chk_estimates); + gcc_assert (chk_estimates.size == size + && chk_estimates.time == time + && chk_estimates.nonspecialized_time == nonspec_time + && chk_estimates.hints == hints); } } else @@ -227,18 +223,28 @@ do_estimate_edge_time (struct cgraph_edge *edge, sreal *ret_nonspec_time) else node_context_cache_clear++; e->entry.ctx.release (); - ctx.estimate_size_and_time (&size, &min_size, - &time, &nonspec_time, &hints); + ipa_call_estimates estimates; + ctx.estimate_size_and_time (&estimates); + size = estimates.size; e->entry.size = size; + time = estimates.time; e->entry.time = time; + nonspec_time = estimates.nonspecialized_time; e->entry.nonspec_time = nonspec_time; + hints = estimates.hints; e->entry.hints = hints; e->entry.ctx.duplicate_from (ctx); } } else - ctx.estimate_size_and_time (&size, &min_size, - &time, &nonspec_time, &hints); + { + ipa_call_estimates estimates; + ctx.estimate_size_and_time (&estimates); + size = estimates.size; + time = estimates.time; + nonspec_time = estimates.nonspecialized_time; + hints = estimates.hints; + } /* When we have profile feedback, we can quite safely identify hot edges and for those we disable size limits. Don't do that when @@ -321,8 +327,9 @@ do_estimate_edge_size (struct cgraph_edge *edge) evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause, &avals, true); ipa_call_context ctx (callee, clause, nonspec_clause, vNULL, &avals); - ctx.estimate_size_and_time (&size, NULL, NULL, NULL, NULL); - return size; + ipa_call_estimates estimates; + ctx.estimate_size_and_time (&estimates, false, false); + return estimates.size; } @@ -332,7 +339,6 @@ do_estimate_edge_size (struct cgraph_edge *edge) ipa_hints do_estimate_edge_hints (struct cgraph_edge *edge) { - ipa_hints hints; struct cgraph_node *callee; clause_t clause, nonspec_clause; @@ -341,7 +347,7 @@ do_estimate_edge_hints (struct cgraph_edge *edge) if (edge_growth_cache != NULL) { do_estimate_edge_time (edge); - hints = edge_growth_cache->get (edge)->hints; + ipa_hints hints = edge_growth_cache->get (edge)->hints; gcc_checking_assert (hints); return hints - 1; } @@ -354,8 +360,9 @@ do_estimate_edge_hints (struct cgraph_edge *edge) evaluate_properties_for_edge (edge, true, &clause, &nonspec_clause, &avals, true); ipa_call_context ctx (callee, clause, nonspec_clause, vNULL, &avals); - ctx.estimate_size_and_time (NULL, NULL, NULL, NULL, &hints); - hints |= simple_edge_hints (edge); + ipa_call_estimates estimates; + ctx.estimate_size_and_time (&estimates, false, true); + ipa_hints hints = estimates.hints | simple_edge_hints (edge); return hints; }