Hi Thanks,
On 2019/11/14 17:04, Jan Hubicka wrote:
>> PR ipa/69678
>> * cgraph.c (symbol_table::create_edge): Init speculative_id.
>> (cgraph_edge::make_speculative): Add param for setting speculative_id.
>> (cgraph_edge::speculative_call_info): Find reference by
>> speculative_id for multiple indirect targets.
>> (cgraph_edge::resolve_speculation): Decrease the speculations
>> for indirect edge, drop it's speculative if not direct target
>> left.
>> (cgraph_edge::redirect_call_stmt_to_callee): Likewise.
>> (cgraph_node::verify_node): Don't report error if speculative
>> edge not include statement.
>> (cgraph_edge::has_multiple_indirect_call_p): New function.
>> (cgraph_edge::has_indirect_call_p): New function.
>> * cgraph.h (struct indirect_target_info): New struct.
>> (indirect_call_targets): New vector variable.
>> (make_speculative): Add param for setting speculative_id.
>> (cgraph_edge::has_multiple_indirect_call_p): New declare.
>> (cgraph_edge::has_indirect_call_p): New declare.
>> (speculative_id): New variable.
>> * cgraphclones.c (cgraph_node::create_clone): Clone speculative_id.
>> * cgraphunit.c: Fix comments typo.
>> * ipa-comdats.c: Fix comments typo.
>> * ipa-inline.c (inline_small_functions): Fix iterator update.
>> * ipa-profile.c (ipa_profile_generate_summary): Add indirect
>> multiple targets logic.
>> (ipa_profile): Likewise.
>> * ipa-ref.h (speculative_id): New variable.
>> * ipa.c (process_references): Fix typo.
>> * lto-cgraph.c (lto_output_edge): Add indirect multiple targets
>> logic. Stream out speculative_id.
>> (input_edge): Likewise.
>> * predict.c (dump_prediction): Revome edges count assert to be
>> precise.
>> * symtab.c (symtab_node::create_reference): Init speculative_id.
>> (symtab_node::clone_references): Clone speculative_id.
>> (symtab_node::clone_referring): Clone speculative_id.
>> (symtab_node::clone_reference): Clone speculative_id.
>> (symtab_node::clear_stmts_in_references): Clear speculative_id.
>> * tree-inline.c (copy_bb): Duplicate all the speculative edges
>> if indirect call contains multiple speculative targets.
>> * tree-profile.c (gimple_gen_ic_profiler): Use the new variable
>> __gcov_indirect_call.counters and __gcov_indirect_call.callee.
>> (gimple_gen_ic_func_profiler): Likewise.
>> (pass_ipa_tree_profile::gate): Fix comment typos.
>> * value-prof.h (check_ic_target): Remove.
>> * value-prof.c (gimple_value_profile_transformations):
>> Use void function gimple_ic_transform.
>> * value-prof.c (gimple_ic_transform): Handle topn case.
>> Fix comment typos. Change it to a void function.
>>
>> gcc/testsuite/ChangeLog
>>
>> 2019-11-14 Xiong Hu Luo <[email protected]>
>>
>> PR ipa/69678
>> * gcc.dg/tree-prof/indir-call-prof-topn.c: New testcase.
>> * gcc.dg/tree-prof/crossmodule-indir-call-topn-1.c: New testcase.
>> * gcc.dg/tree-prof/crossmodule-indir-call-topn-1a.c: New testcase.
>> * gcc.dg/tree-prof/crossmodule-indir-call-topn-2.c: New testcase.
>> * lib/scandump.exp: Dump executable file name.
>> * lib/scanwpaipa.exp: New scan-pgo-wap-ipa-dump.
>> @@ -1089,6 +1093,38 @@ cgraph_edge::make_speculative (cgraph_node *n2,
>> profile_count direct_count)
>> call) and if one of them exists, all of them must exist.
>>
>> Given speculative call edge, return all three components.
>> +
>> + For some indirect edge, it may maps to multiple direct edges, i.e. 1:N.
>> + check the speculative_id to return all the three components for specified
>> + direct edge or indirect edge.
>> + If input is indirect, caller of this function will get the direct edge
>> one by
>> + one, get_edge will just return one of the direct edge mapped to the
>> indirect
>> + edge, the returned direct edge will be resolved or redirected by the
>> caller,
>> + then number of indirect calls (speculations) is deceased in each access.
>> + If input is direct, this function will get the indirect edge and
>> reference
>> + with matched speculative_id, the returned edge will also be resolved or
>> + redirected, decrease the speculations accordingly.
>> + Speculations of indirect edge will be dropped only if all direct edges
>> + be handled.
>> +
>> + e.g. for indirect edge E statement "call call_dest":
>> +
>> + Redirect N3 after redirected N2:
>> +
>> + if (call_dest == N2)
>> + n2 ();
>> + else if (call_dest == N3)
>> + n3 ();
>> + else
>> + call call_dest
>> +
>> + Resolve N3 and only redirect N2:
>> +
>> + if (call_dest == N2)
>> + n2 ();
>> + else
>> + call call_dest
>> +
>
> I find this comment hard to read. Reader probably does not know what
> speculative edges are and we only want to describe speculative_call_info
> function not also the way we resolve calls. So what about something
> like this:
>
> Speculative calls represent a transformation of indirect calls
> which may be later inserted into gimple in the following form:
>
> if (call_dest == target1)
> target1 ();
> else if (call_dest == target2)
> target ();
> else
> call_dest ();
>
> This is a win in case target1 and target2 are common values for
> call_dest as determined by ipa-devirt or indirect call profiling.
> In particular this may enable inlining and other optimizations.
>
> Speculative call consists of the following main components:
>
> 1) One or more direct call
> 2) One or more IPA_REF_ADDR references (representing the fact that
> code above takes address of target1 and target2)
> 3) The fallback indirect call
>
> Direct calls and corresponidng references are linked by
> speculative_id.
>
> speculative_call_info returns tripple
> (direct_call, IPA_REF_ADDR reference, indirect call)
> when called on one edge participating in the speculative call.
>
> If called on direct call its corresponding IPA_REF_ADDR is returned.
>
> If caled on indirect call it will return one of direct edges and its
> matching IPA_REF_ADDR.
>
> All direct calls corresponding to a given speculative call can be
> enumerated by indirect_edge->indirect_info->indirect_call_targets
Will update.
>> */
>>
>> void
>> @@ -1128,7 +1164,7 @@ cgraph_edge::speculative_call_info (cgraph_edge
>> *&direct,
>>
>> reference = NULL;
>> for (i = 0; e->caller->iterate_reference (i, ref); i++)
>> - if (ref->speculative
>> + if (ref->speculative && ref->speculative_id == e->speculative_id
>> && ((ref->stmt && ref->stmt == e->call_stmt)
>> || (!ref->stmt && ref->lto_stmt_uid == e->lto_stmt_uid)))
>> {
>> @@ -1189,7 +1225,21 @@ cgraph_edge::resolve_speculation (tree callee_decl)
>
> Rewrite comment here to make clear what resolve_speculation does for
> multiple targets.
OK and please be patient with my English :)
>> in the functions inlined through it. */
>> }
>> edge->count += e2->count;
>> - edge->speculative = false;
>> + /* edge is indirect, e2 is direct. If edge contains multiple
>> speculations,
>> + remove one of speculations for this indirect edge, then if edge still
>> + contains direct target, keep the speculation, next direct target
>> + will continue use it. Give up speculation completely if no direct
>> + target is left for this indirect edge. */
>> + if (edge->has_indirect_call_p ())
>> + {
>> + /* As the direct targets are sorted by decrease, delete the first
>> target
>> + when it is resolved. */
>> + edge->indirect_info->indirect_call_targets->ordered_remove (0);
>> + if (edge->indirect_info->indirect_call_targets->is_empty ())
>> + edge->speculative = false;
>> + }
>> + else
>> + edge->speculative = false;
>> e2->speculative = false;
>> ref->remove_reference ();
>> if (e2->indirect_unknown_callee || e2->inline_failed)
>> @@ -1297,7 +1347,21 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
>> e->caller->set_call_stmt_including_clones (e->call_stmt, new_stmt,
>> false);
>> e->count = gimple_bb (e->call_stmt)->count;
>> - e2->speculative = false;
>> + /* edge is direct, e2 is indirect here. If e2 contains multiple
>> + speculations, remove one of speculations for this indirect edge,
>> + then if e2 still contains direct target, keep the speculation,
>> + next direct target will continue use it. Give up speculation
>> + completely if no direct target is left for this indirect e2. */
>> + if (e2->has_indirect_call_p ())
>> + {
>> + /* As the direct targets are sorted by decrease, delete the first
>> + target when it is redirected. */
>> + e2->indirect_info->indirect_call_targets->ordered_remove (0);
>> + if (e2->indirect_info->indirect_call_targets->is_empty ())
>> + e2->speculative = false;
>> + }
>> + else
>> + e2->speculative = false;
>
> I think this also needs better explanation (and especially in the
> comment in the front of function)
>> @@ -3696,6 +3760,22 @@ cgraph_edge::possibly_call_in_translation_unit_p
>> (void)
>> return node->get_availability () >= AVAIL_INTERPOSABLE;
>> }
>>
>> +/* Return true if this edge has multiple indirect call targets. */
>> +bool
>> +cgraph_edge::has_multiple_indirect_call_p (void)
> Probaby better as
> multiple_speculative_call_targets_p
>
> It seems to me that here you use indirect_call_targets array which does
> not make much sense once the indirect edge is turned into speculative
> call. This vector should be freed after that and as I write late
> it should not be in the callgraph itself but rather in a ipa-profile
> summary.
>
> (I know that common_target_probability and common_target_id is there
> right now but it is code predating summaries and it does not belong there
> anymore)
>
> I would simply add "num_speculative_call_targets" into
> cgraph_indirect_call_info datastructure.
OK. I used num_of_ics(i.e. num_speculative_call_targets) in early version.
Will try restore it.
>> +{
>> + return (indirect_info && indirect_info->indirect_call_targets
>> + && indirect_info->indirect_call_targets->length () > 1);
>
> Maybe it would make sense to call this speculative_call_targets?
> Since they are after all direct calls...
>> +}
>> +
>> +/* Return true if this edge has at least one indirect call target. */
>> +bool
>> +cgraph_edge::has_indirect_call_p (void)
>> +{
>> + return (indirect_info && indirect_info->indirect_call_targets
>> + && !indirect_info->indirect_call_targets->is_empty ());
>
> How this is different from speculative flag on an indirect call?
>> +}
>> +
>> /* A stashed copy of "symtab" for use by selftest::symbol_table_test.
>> This needs to be a global so that it can be a GC root, and thus
>> prevent the stashed copy from being garbage-collected if the GC runs
>> diff --git a/gcc/cgraph.h b/gcc/cgraph.h
>> index a4f14743f00..1299702788d 100644
>> --- a/gcc/cgraph.h
>> +++ b/gcc/cgraph.h
>> @@ -1636,6 +1636,21 @@ private:
>> void make_speculative (tree otr_type = NULL);
>> };
>>
>> +/* Structure containing indirect target information from profile. */
>> +
>> +struct GTY (()) indirect_target_info
> Probably better as speculative_call_target?
>> +{
>> + indirect_target_info (unsigned int id, int prob)
>> + : common_target_id (id), common_target_probability (prob)
>> + {
>> + }
>> +
>> + /* Profile_id of common target obtained from profile. */
>> + unsigned int common_target_id;
>> + /* Probability that call will land in function with COMMON_TARGET_ID. */
>> + int common_target_probability;
>
> I think this would be more like frequent then common, but perhaps
> target_id and target_probablity is better.
>> +};
>> +
>> /* Structure containing additional information about an indirect call. */
>>
>> class GTY(()) cgraph_indirect_call_info
>> @@ -1654,10 +1669,9 @@ public:
>> int param_index;
>> /* ECF flags determined from the caller. */
>> int ecf_flags;
>> - /* Profile_id of common target obtained from profile. */
>> - int common_target_id;
>> - /* Probability that call will land in function with COMMON_TARGET_ID. */
>> - int common_target_probability;
>> +
>> + /* An indirect call may contain one or multiple call targets. */
>> + vec<indirect_target_info, va_gc> *indirect_call_targets;
>
> And speculative_call_targets?
> Please put these into cgraph_edge_summary template.
>
> This is a short lived annotation which is private to ipa-profile and
> does not need to be in the core datastructures. So you can then also
> delcare it within ipa-profile.c as no one lese cares about it.
> Also stream in ipa_profile_write_summary rather than lto-cgraph.
Sorry that I don't quite understand your meanning here. I didn't grep the
word "cgraph_edge_summary" in source code, do you mean add new structure
and related functions like "static ipa_sra_call_summaries *call_sums;"
in ipa-sra.c and stream in/out in
ipa_profile_write_summary/ipa_profile_read_summary?
BTW, there is already an ipa_call_summaries in ipa-profile.c:355, feel
apologetic as
not familiar with many summaries in it, will take time to go through it:
ipa_call_summary *s = ipa_call_summaries->get (edge);
>
>> + /* speculative id is used by multiple indirect targets when the function
>> is
> ... is used to link direct calls with their corresponding IPA_REF_ADDR
> references when representing speculative cals. */
>
> Even if there is only one speculation the values must match, right? :)
>> + speculated. */
>> + unsigned int speculative_id;
>
> The bitfields will pack well with the speculative_id if we make it
> 16bit rather than 32bit. I do not think we will ever want to support
> more than 64K speculative targets.
OK.
>> diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c
>> index b496497ff66..0672d6d6575 100644
>> --- a/gcc/ipa-comdats.c
>> +++ b/gcc/ipa-comdats.c
>> @@ -18,7 +18,7 @@ along with GCC; see the file COPYING3. If not see
>> <http://www.gnu.org/licenses/>. */
>>
>> /* This is very simple pass that looks for static symbols that are used
>> - exlusively by symbol within one comdat group. In this case it makes
>> + exclusively by symbol within one comdat group. In this case it makes
> This can go in separately as obovius.
>> sense to bring the symbol itself into the group to avoid dead code
>> that would arrise when the comdat group from current unit is replaced
>> by a different copy. Consider for example:
>> diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
>> index 78ec0ec685f..8fc67ef88a5 100644
>> --- a/gcc/ipa-inline.c
>> +++ b/gcc/ipa-inline.c
>> @@ -1945,12 +1945,15 @@ inline_small_functions (void)
>> }
>> if (has_speculative)
>> for (edge = node->callees; edge; edge = next)
>> - if (edge->speculative && !speculation_useful_p (edge,
>> - edge->aux != NULL))
>> - {
>> - edge->resolve_speculation ();
>> - update = true;
>> - }
>> + {
>> + next = edge->next_callee;
>> + if (edge->speculative
>> + && !speculation_useful_p (edge, edge->aux != NULL))
>> + {
>> + edge->resolve_speculation ();
>> + update = true;
>> + }
>> + }
>
> This looks like pasto. So next is initialized only in the loop before
> and it happens that it never has speculative flag on it?>
> If so, this is also independent fix, so please send it as separate
> patch.
>> @@ -563,7 +573,7 @@ ipa_profile (void)
>> histogram.release ();
>> histogram_pool.release ();
>>
>> - /* Produce speculative calls: we saved common traget from porfiling into
>> + /* Produce speculative calls: we saved common target from profiling into
>
> Also just commit this as obvious.
Done.
>> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
>> index bdc332dcc23..6c8ebffa11d 100644
>> --- a/gcc/tree-inline.c
>> +++ b/gcc/tree-inline.c
>> @@ -2194,6 +2194,25 @@ copy_bb (copy_body_data *id, basic_block bb,
>>
>> gcc_assert (!edge->indirect_unknown_callee);
>> old_edge->speculative_call_info (direct, indirect,
>> ref);
>> + while (old_edge->next_callee
>> + && old_edge->next_callee->speculative
>> + && indirect->has_multiple_indirect_call_p ())
>> + {
>> + /* Some speculative calls may contain more than
>> + one direct target, loop iterate it to clone all
> I gues better as "Iterate through all direct calls associated to the
> speculative call and clone all..."
>> + related direct edges before cloning the related
>> + indirect edge. */
>> + id->dst_node->clone_reference (ref, stmt);
>> +
>> + edge = old_edge->next_callee;
>> + edge = edge->clone (id->dst_node, call_stmt,
>> + gimple_uid (stmt), num, den,
>> + true);
>> + old_edge = old_edge->next_callee;
>> + gcc_assert (!edge->indirect_unknown_callee);
>> + old_edge->speculative_call_info (direct, indirect,
>> + ref);
> Why do you call this at the end of loop? And how do you know that al the
> edges are associated to the given speculative call?
Speculative targets are sorted by decrease order of execution count in
tree-profile.
speculative_id in each direct target will ensure the identity in
speculative_call_info.
Here, speculative_call_info is called first before the while loop, if direct
target1 exists,
it will be cloned to dst_node. Then speculative_call_info is called second
time, if direct
target2 exsits, also clone it to dst_node, else the while condition is false,
the indirect
edge is cloned to dst_node in following code out of the while loop.
We all know that you are very busy:), it's so nice of you take the time to
review patch to
improve code quality. Thanks!
Xiong Hu
BR
>> + }
>>
>> profile_count indir_cnt = indirect->count;
>> indirect = indirect->clone (id->dst_node, call_stmt,
>> diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
>> index 6a4e62f5bae..b4435b9b2a8 100644
>> --- a/gcc/tree-profile.c
>> +++ b/gcc/tree-profile.c
>> @@ -73,8 +73,8 @@ static GTY(()) tree ic_tuple_callee_field;
>> /* Do initialization work for the edge profiler. */
>>
>> /* Add code:
>> - __thread gcov* __gcov_indirect_call_counters; // pointer to actual
>> counter
>> - __thread void* __gcov_indirect_call_callee; // actual callee address
>> + __thread gcov* __gcov_indirect_call.counters; // pointer to actual
>> counter
>> + __thread void* __gcov_indirect_call.callee; // actual callee address
>> __thread int __gcov_function_counter; // time profiler function counter
>> */
>> static void
>> @@ -381,7 +381,7 @@ gimple_gen_ic_profiler (histogram_value value, unsigned
>> tag)
>> f_1 = foo;
>> __gcov_indirect_call.counters = &__gcov4.main[0];
>> PROF_9 = f_1;
>> - __gcov_indirect_call_callee = PROF_9;
>> + __gcov_indirect_call.callee = PROF_9;
>> _4 = f_1 ();
>> */
>>
>> @@ -444,11 +444,11 @@ gimple_gen_ic_func_profiler (void)
>>
>> /* Insert code:
>>
>> - if (__gcov_indirect_call_callee != NULL)
>> + if (__gcov_indirect_call.callee != NULL)
>> __gcov_indirect_call_profiler_v3 (profile_id,
>> ¤t_function_decl);
>>
>> The function __gcov_indirect_call_profiler_v3 is responsible for
>> - resetting __gcov_indirect_call_callee to NULL. */
>> + resetting __gcov_indirect_call.callee to NULL. */
>>
>> gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
>> void0 = build_int_cst (ptr_type_node, 0);
>> @@ -890,7 +890,7 @@ pass_ipa_tree_profile::gate (function *)
>> {
>> /* When profile instrumentation, use or test coverage shall be performed.
>> But for AutoFDO, this there is no instrumentation, thus this pass is
>> - diabled. */
>> + disabled. */
>> return (!in_lto_p && !flag_auto_profile
>> && (flag_branch_probabilities || flag_test_coverage
>> || profile_arc_flag));
>
> Also commit this independently?
>
> Patch looks really nice overall. It will be easy to teach ipa-devirt to
> use multiple targets too.
>
> I apologize for very late response and thanks for all the pings
> (I will try to get more timely)
> Honza
>> diff --git a/gcc/value-prof.c b/gcc/value-prof.c
>> index cc3542f0295..f64f515c1ee 100644
>> --- a/gcc/value-prof.c
>> +++ b/gcc/value-prof.c
>> @@ -106,7 +106,7 @@ static bool gimple_divmod_fixed_value_transform
>> (gimple_stmt_iterator *);
>> static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *);
>> static bool gimple_mod_subtract_transform (gimple_stmt_iterator *);
>> static bool gimple_stringops_transform (gimple_stmt_iterator *);
>> -static bool gimple_ic_transform (gimple_stmt_iterator *);
>> +static void gimple_ic_transform (gimple_stmt_iterator *);
>>
>> /* Allocate histogram value. */
>>
>> @@ -616,8 +616,7 @@ gimple_value_profile_transformations (void)
>> if (gimple_mod_subtract_transform (&gsi)
>> || gimple_divmod_fixed_value_transform (&gsi)
>> || gimple_mod_pow2_value_transform (&gsi)
>> - || gimple_stringops_transform (&gsi)
>> - || gimple_ic_transform (&gsi))
>> + || gimple_stringops_transform (&gsi))
>> {
>> stmt = gsi_stmt (gsi);
>> changed = true;
>> @@ -628,6 +627,9 @@ gimple_value_profile_transformations (void)
>> gsi = gsi_for_stmt (stmt);
>> }
>> }
>> +
>> + /* The function never thansforms a GIMPLE statement. */
>> + gimple_ic_transform (&gsi);
>> }
>> }
>>
>> @@ -1386,13 +1388,12 @@ gimple_ic (gcall *icall_stmt, struct cgraph_node
>> *direct_call,
>> return dcall_stmt;
>> }
>>
>> -/*
>> - For every checked indirect/virtual call determine if most common pid of
>> - function/class method has probability more than 50%. If yes modify code of
>> - this call to:
>> - */
>> +/* There maybe multiple indirect targets in histogram. Check every
>> + indirect/virtual call if callee function exists, if not exist, leave it
>> to
>> + LTO stage for later process. Modify code of this indirect call to an
>> if-else
>> + structure in ipa-profile finally. */
>>
>> -static bool
>> +static void
>> gimple_ic_transform (gimple_stmt_iterator *gsi)
>> {
>> gcall *stmt;
>> @@ -1402,52 +1403,58 @@ gimple_ic_transform (gimple_stmt_iterator *gsi)
>>
>> stmt = dyn_cast <gcall *> (gsi_stmt (*gsi));
>> if (!stmt)
>> - return false;
>> + return;
>>
>> if (gimple_call_fndecl (stmt) != NULL_TREE)
>> - return false;
>> + return;
>>
>> if (gimple_call_internal_p (stmt))
>> - return false;
>> + return;
>>
>> histogram = gimple_histogram_value_of_type (cfun, stmt,
>> HIST_TYPE_INDIR_CALL);
>> if (!histogram)
>> - return false;
>> + return;
>>
>> - if (!get_nth_most_common_value (NULL, "indirect call", histogram, &val,
>> - &count, &all))
>> - return false;
>> + count = 0;
>> + all = histogram->hvalue.counters[0];
>>
>> - if (4 * count <= 3 * all)
>> - return false;
>> + for (unsigned j = 0; j < GCOV_TOPN_VALUES; j++)
>> + {
>> + if (!get_nth_most_common_value (NULL, "indirect call", histogram,
>> &val,
>> + &count, &all, j))
>> + return;
>>
>> - direct_call = find_func_by_profile_id ((int)val);
>> + /* Minimum probability. should be higher than 25%. */
>> + if (4 * count <= all)
>> + return;
>>
>> - if (direct_call == NULL)
>> - {
>> - if (val)
>> + direct_call = find_func_by_profile_id ((int) val);
>> +
>> + if (direct_call == NULL)
>> {
>> - if (dump_enabled_p ())
>> - dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmt,
>> - "Indirect call -> direct call from other "
>> - "module %T=> %i (will resolve only with LTO)\n",
>> - gimple_call_fn (stmt), (int)val);
>> + if (val)
>> + {
>> + if (dump_enabled_p ())
>> + dump_printf_loc (
>> + MSG_MISSED_OPTIMIZATION, stmt,
>> + "Indirect call -> direct call from other "
>> + "module %T=> %i (will resolve only with LTO)\n",
>> + gimple_call_fn (stmt), (int) val);
>> + }
>> + return;
>> }
>> - return false;
>> - }
>>
>> - if (dump_enabled_p ())
>> - {
>> - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
>> - "Indirect call -> direct call "
>> - "%T => %T transformation on insn postponed\n",
>> - gimple_call_fn (stmt), direct_call->decl);
>> - dump_printf_loc (MSG_NOTE, stmt,
>> - "hist->count %" PRId64
>> - " hist->all %" PRId64"\n", count, all);
>> + if (dump_enabled_p ())
>> + {
>> + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, stmt,
>> + "Indirect call -> direct call "
>> + "%T => %T transformation on insn postponed\n",
>> + gimple_call_fn (stmt), direct_call->decl);
>> + dump_printf_loc (MSG_NOTE, stmt,
>> + "hist->count %" PRId64 " hist->all %" PRId64 "\n",
>> + count, all);
>> + }
>> }
>> -
>> - return true;
>> }
>>
>> /* Return true if the stringop CALL shall be profiled. SIZE_ARG be
>> diff --git a/gcc/value-prof.h b/gcc/value-prof.h
>> index 77c06f60096..b3eeb57d37d 100644
>> --- a/gcc/value-prof.h
>> +++ b/gcc/value-prof.h
>> @@ -89,7 +89,6 @@ void verify_histograms (void);
>> void free_histograms (function *);
>> void stringop_block_profile (gimple *, unsigned int *, HOST_WIDE_INT *);
>> gcall *gimple_ic (gcall *, struct cgraph_node *, profile_probability);
>> -bool check_ic_target (gcall *, struct cgraph_node *);
>> bool get_nth_most_common_value (gimple *stmt, const char *counter_type,
>> histogram_value hist, gcov_type *value,
>> gcov_type *count, gcov_type *all,
>> --
>> 2.21.0.777.g83232e3864
>>
>>