From af21714c7bac20c348d544a285a2dc95fe271a5d Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Sun, 29 Mar 2015 17:38:52 +0200 Subject: [PATCH] re PR ipa/65478 (crafty performance regression) PR ipa/65478 * params.def (PARAM_IPA_CP_RECURSION_PENALTY) : New. (PARAM_IPA_CP_SINGLE_CALL_PENALTY): Likewise. * ipa-prop.h (ipa_node_params): New flags node_within_scc and node_calling_single_call. * ipa-cp.c (count_callers): New function. (set_single_call_flag): Likewise. (initialize_node_lattices): Count callers and set single_flag_call if necessary. (incorporate_penalties): New function. (good_cloning_opportunity_p): Use it, dump new flags. (propagate_constants_topo): Set node_within_scc flag if appropriate. * doc/invoke.texi (ipa-cp-recursion-penalty, ipa-cp-single-call-pentalty): Document. From-SVN: r221763 --- gcc/ChangeLog | 17 +++++++++ gcc/doc/invoke.texi | 9 +++++ gcc/ipa-cp.c | 89 +++++++++++++++++++++++++++++++++++++++++---- gcc/ipa-prop.h | 4 ++ gcc/params.def | 12 ++++++ 5 files changed, 123 insertions(+), 8 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 554d8c68335..9baf88b1471 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2015-03-27 Martin Jambor + + PR ipa/65478 + * params.def (PARAM_IPA_CP_RECURSION_PENALTY) : New. + (PARAM_IPA_CP_SINGLE_CALL_PENALTY): Likewise. + * ipa-prop.h (ipa_node_params): New flags node_within_scc and + node_calling_single_call. + * ipa-cp.c (count_callers): New function. + (set_single_call_flag): Likewise. + (initialize_node_lattices): Count callers and set single_flag_call if + necessary. + (incorporate_penalties): New function. + (good_cloning_opportunity_p): Use it, dump new flags. + (propagate_constants_topo): Set node_within_scc flag if appropriate. + * doc/invoke.texi (ipa-cp-recursion-penalty, + ipa-cp-single-call-pentalty): Document. + 2015-03-27 Jan Hubicka PR ipa/65588 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 9749727c13f..bf8afadfb94 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10834,6 +10834,15 @@ IPA-CP calculates its own score of cloning profitability heuristics and performs those cloning opportunities with scores that exceed @option{ipa-cp-eval-threshold}. +@item ipa-cp-recursion-penalty +Percentage penalty the recursive functions will receive when they +are evaluated for cloning. + +@item ipa-cp-single-call-penalty +Percentage penalty functions containg a single call to another +function will receive when they are evaluated for cloning. + + @item ipa-max-agg-items IPA-CP is also capable to propagate a number of scalar values passed in an aggregate. @option{ipa-max-agg-items} controls the maximum diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index bfe4d972e73..d9aa92ed5b5 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -811,6 +811,41 @@ set_all_contains_variable (struct ipcp_param_lattices *plats) return ret; } +/* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA + points to by the number of callers to NODE. */ + +static bool +count_callers (cgraph_node *node, void *data) +{ + int *caller_count = (int *) data; + + for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller) + /* Local thunks can be handled transparently, but if the thunk can not + be optimized out, count it as a real use. */ + if (!cs->caller->thunk.thunk_p || !cs->caller->local.local) + ++*caller_count; + return false; +} + +/* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on + the one caller of some other node. Set the caller's corresponding flag. */ + +static bool +set_single_call_flag (cgraph_node *node, void *) +{ + cgraph_edge *cs = node->callers; + /* Local thunks can be handled transparently, skip them. */ + while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local) + cs = cs->next_caller; + if (cs) + { + gcc_assert (!cs->next_caller); + IPA_NODE_REF (cs->caller)->node_calling_single_call = true; + return true; + } + return false; +} + /* Initialize ipcp_lattices. */ static void @@ -822,7 +857,17 @@ initialize_node_lattices (struct cgraph_node *node) int i; gcc_checking_assert (node->has_gimple_body_p ()); - if (!cgraph_local_p (node)) + if (cgraph_local_p (node)) + { + int caller_count = 0; + node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, + true); + gcc_checking_assert (caller_count > 0); + if (caller_count == 1) + node->call_for_symbol_thunks_and_aliases (set_single_call_flag, + NULL, true); + } + else { /* When cloning is allowed, we can assume that externally visible functions are not called. We will compensate this by cloning @@ -2105,6 +2150,24 @@ hint_time_bonus (inline_hints hints) return result; } +/* If there is a reason to penalize the function described by INFO in the + cloning goodness evaluation, do so. */ + +static inline int64_t +incorporate_penalties (ipa_node_params *info, int64_t evaluation) +{ + if (info->node_within_scc) + evaluation = (evaluation + * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100; + + if (info->node_calling_single_call) + evaluation = (evaluation + * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY))) + / 100; + + return evaluation; +} + /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT and SIZE_COST and with the sum of frequencies of incoming edges to the potential new clone in FREQUENCIES. */ @@ -2120,18 +2183,22 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, gcc_assert (size_cost > 0); + struct ipa_node_params *info = IPA_NODE_REF (node); if (max_count) { int factor = (count_sum * 1000) / max_count; int64_t evaluation = (((int64_t) time_benefit * factor) / size_cost); + evaluation = incorporate_penalties (info, evaluation); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC - ") -> evaluation: " "%"PRId64 + "%s%s) -> evaluation: " "%"PRId64 ", threshold: %i\n", time_benefit, size_cost, (HOST_WIDE_INT) count_sum, + info->node_within_scc ? ", scc" : "", + info->node_calling_single_call ? ", single_call" : "", evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); @@ -2140,13 +2207,16 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, { int64_t evaluation = (((int64_t) time_benefit * freq_sum) / size_cost); + evaluation = incorporate_penalties (info, evaluation); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " - "size: %i, freq_sum: %i) -> evaluation: " + "size: %i, freq_sum: %i%s%s) -> evaluation: " "%"PRId64 ", threshold: %i\n", - time_benefit, size_cost, freq_sum, evaluation, - PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); + time_benefit, size_cost, freq_sum, + info->node_within_scc ? ", scc" : "", + info->node_calling_single_call ? ", single_call" : "", + evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); } @@ -2637,9 +2707,12 @@ propagate_constants_topo (struct ipa_topo_info *topo) struct cgraph_edge *cs; for (cs = v->callees; cs; cs = cs->next_callee) - if (ipa_edge_within_scc (cs) - && propagate_constants_accross_call (cs)) - push_node_to_stack (topo, cs->callee->function_symbol ()); + if (ipa_edge_within_scc (cs)) + { + IPA_NODE_REF (v)->node_within_scc = true; + if (propagate_constants_accross_call (cs)) + push_node_to_stack (topo, cs->callee->function_symbol ()); + } v = pop_node_from_stack (topo); } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 1b78ccc3a2b..0488254492a 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -330,6 +330,10 @@ struct ipa_node_params /* Node has been completely replaced by clones and will be removed after ipa-cp is finished. */ unsigned node_dead : 1; + /* Node is involved in a recursion, potentionally indirect. */ + unsigned node_within_scc : 1; + /* Node is calling a private function called only once. */ + unsigned node_calling_single_call : 1; }; /* ipa_node_params access functions. Please use these to access fields that diff --git a/gcc/params.def b/gcc/params.def index f890cb0e176..5e2c7695865 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -999,6 +999,18 @@ DEFPARAM (PARAM_IPA_CP_EVAL_THRESHOLD, "beneficial to clone.", 500, 0, 0) +DEFPARAM (PARAM_IPA_CP_RECURSION_PENALTY, + "ipa-cp-recursion-penalty", + "Percentage penalty the recursive functions will receive when they " + "are evaluated for cloning.", + 40, 0, 100) + +DEFPARAM (PARAM_IPA_CP_SINGLE_CALL_PENALTY, + "ipa-cp-single-call-penalty", + "Percentage penalty functions containg a single call to another " + "function will receive when they are evaluated for cloning.", + 15, 0, 100) + DEFPARAM (PARAM_IPA_MAX_AGG_ITEMS, "ipa-max-agg-items", "Maximum number of aggregate content items for a parameter in " -- 2.30.2