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  <luo...@linux.ibm.com>
>>
>>      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, 
>> &current_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
>>
>>

Reply via email to