> > gcc/ChangeLog
> > 
> >     2019-12-02  Xiong Hu Luo  <luo...@linux.ibm.com>
> > 
> >     PR ipa/69678
> >     * Makefile.in (GTFILES): Add ipa-profile.c.
> >     * cgraph.c (symbol_table::create_edge): Init speculative_id.
> >     (cgraph_edge::make_speculative): Add param for setting speculative_id.
> >     (cgraph_edge::speculative_call_info): Update comments and 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. Update comments.
> >     (cgraph_edge::redirect_call_stmt_to_callee): Likewise.
> >     (cgraph_node::dump): Print num_speculative_call_targets.
> >     (cgraph_node::verify_node): Don't report error if speculative
> >     edge not include statement.
> >     (cgraph_edge::num_speculative_call_targets_p): New function.
> >     * cgraph.h (int common_target_id): Remove.
> >     (int common_target_probability): Remove.
> >     (num_speculative_call_targets): New variable.
> >     (make_speculative): Add param for setting speculative_id.
> >     (cgraph_edge::num_speculative_call_targets_p): New declare.
> >     (speculative_id): New variable.
> >     * cgraphclones.c (cgraph_node::create_clone): Clone speculative_id.
> >     * ipa-profile.c (struct speculative_call_target): New struct.
> >     (class speculative_call_summary): New class.
> >     (class speculative_call_summaries): New class.
> >     (call_sums): New variable.
> >     (ipa_profile_generate_summary): Generate indirect multiple targets 
> > summaries.
> >     (ipa_profile_write_edge_summary): New function.
> >     (ipa_profile_write_summary): Stream out indirect multiple targets 
> > summaries.
> >     (ipa_profile_dump_all_summaries): New function.
> >     (ipa_profile_read_edge_summary): New function.
> >     (ipa_profile_read_summary_section): New function.
> >     (ipa_profile_read_summary): Stream in indirect multiple targets 
> > summaries.
> >     (ipa_profile): Generate num_speculative_call_targets from
> >     summaries.
> >     * ipa-ref.h (speculative_id): New variable.
> >     * lto-cgraph.c (lto_output_edge): Remove indirect common_target_id and
> >     common_target_probability.   Stream out speculative_id and
> >     num_speculative_call_targets.
> >     (input_edge): Likewise.
> >     * predict.c (dump_prediction): Remove 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-12-02  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.

> > -cgraph_edge::make_speculative (cgraph_node *n2, profile_count direct_count)
> > +cgraph_edge::make_speculative (cgraph_node *n2, profile_count direct_count,
> > +                          unsigned int speculative_id)

Please document speculative_id parameter.
> > +/* Speculative calls represent a transformation of indirect calls
> > +   which may be later inserted into gimple in the following form:
> > 
> > -   Given speculative call edge, return all three components.
> > +   if (call_dest == target1)
> > +   target1 ();
> > +   else if (call_dest == target2)
> > +   target2 ();
> > +   else
> > +   call_dest ();
> > +
> > +   This is a win in case when target1 and target2 are common values for

  ... in the case ...
I guess :)
> > -/* Collect histogram from CFG profiles.  */
> > +/* Structure containing speculative target information from profile.  */
> > +
> > +struct GTY (()) speculative_call_target
There is no need to place this in the garbage collector, so remove GTY.
> > +{
> > +  speculative_call_target (unsigned int id, int prob)
> > +    : target_id (id), target_probability (prob)
> > +  {
> > +  }
> > +
> > +  /* Profile_id of target obtained from profile.  */
> > +  unsigned int target_id;
> > +  /* Probability that call will land in function with target_id.  */
> > +  int target_probability;
> > +};
> > +
> > +class GTY ((for_user)) speculative_call_summary
Similarly here, drop GTY marker.
> > +{
> > +public:
> > +  speculative_call_summary () : speculative_call_targets ()
> > +  {}
> > +
> > +  vec<speculative_call_target, va_gc> *speculative_call_targets;
Making this auto_vec will save the need to deallocate explicitly.
> > +  ~speculative_call_summary ();
> > +
> > +  void dump (FILE *f);
> > +
> > +  /* Check whether this is a empty summary.  */
> > +  bool is_empty ();
> > +};
> > +
> > +  /* Class to manage call summaries.  */
> > +
> > +class GTY ((user)) ipa_profile_call_summaries
> > +  : public call_summary<speculative_call_summary *>
Remove GTY and make this non-ggc
> > +{
> > +public:
> > +  ipa_profile_call_summaries (symbol_table *table, bool ggc)
> > +    : call_summary<speculative_call_summary *> (table, ggc)
> > +  {}
Do we need the empty constructor at all?
> > +
> > +  /* Duplicate info when an edge is cloned.  */
> > +  virtual void duplicate (cgraph_edge *, cgraph_edge *,
> > +                     speculative_call_summary *old_sum,
> > +                     speculative_call_summary *new_sum);
> > +};
> > +
> > +static GTY (()) ipa_profile_call_summaries *call_sums = NULL;
> > +
> > +speculative_call_summary::~speculative_call_summary ()
> > +{
> > +  if (speculative_call_targets)
> > +    {
> > +      vec_free (speculative_call_targets);
> > +      speculative_call_targets = NULL;
> > +    }
> > +}

This desctuctor is unnecesary if you turn call tarets to auto_vec.
> > +
> > +/* Dump all information in speculative call summary to F.  */
> > +
> > +void
> > +speculative_call_summary::dump (FILE *f)
> > +{
> > +  speculative_call_target *item;
> > +  cgraph_node *n2;
> > +  unsigned int i;
> > +
> > +  FOR_EACH_VEC_SAFE_ELT (speculative_call_targets, i, item)
> > +    {
> > +      n2 = find_func_by_profile_id (item->target_id);
> > +      if (n2)
> > +   fprintf (f, "    The %i speculative target is %s with prob %3.2f\n", i,
> > +            n2->dump_name (),
> > +            item->target_probability / (float) REG_BR_PROB_BASE);
> > +      else
> > +   fprintf (f, "    The %i speculative target is %u with prob %3.2f\n", i,
> > +            item->target_id,
> > +            item->target_probability / (float) REG_BR_PROB_BASE);
> > +    }
> > +}
> > +
> > +/* Check whether this is a empty summary.  */
> > +bool
> > +speculative_call_summary::is_empty ()
> > +{
> > +  return speculative_call_targets == NULL
> > +    || speculative_call_targets->is_empty ();
> > +}

We probably do not want to have empty summaries around, so the second
test chould be assert?
> > +
> > +/* Duplicate info when an edge is cloned.  */
> > +
> > +void
> > +ipa_profile_call_summaries::duplicate (cgraph_edge *, cgraph_edge *,
> > +                             speculative_call_summary *old_sum,
> > +                             speculative_call_summary *new_sum)
> > +{
> > +  if (!old_sum || !old_sum->speculative_call_targets)
> > +    return;
> > +
> > +  speculative_call_target *item;
> > +  unsigned int i;
> > +
> > +  FOR_EACH_VEC_SAFE_ELT (old_sum->speculative_call_targets, i, item)
> > +    {
> > +      vec_safe_push (new_sum->speculative_call_targets, *item);
> > +    }
vec_copy will do.
> > diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
> > index 00af24c77db..b68661d45c8 100644
> > --- a/gcc/ipa-ref.h
> > +++ b/gcc/ipa-ref.h
> > @@ -47,30 +47,31 @@ public:
> >     bool cannot_lead_to_return ();
> > 
> >     /* Return true if reference may be used in address compare.  */
> >     bool address_matters_p ();
> > 
> >     /* Return reference list this reference is in.  */
> >     struct ipa_ref_list * referring_ref_list (void);
> > 
> >     /* Return reference list this reference is in.  */
> >     struct ipa_ref_list * referred_ref_list (void);
> > 
> >     symtab_node *referring;
> >     symtab_node *referred;
> >     gimple *stmt;
> >     unsigned int lto_stmt_uid;
> > +  unsigned int speculative_id;
Please add documentation. 
I would also make them 16bit and packed with bitfeilds to be consistent
with cgraph edges.  
ipa_refs are quite critical for memory use of WPA stage. I see it will
not save memory now but it will help us to not forget about the fact
that they have limited value range in future.
> > 
> >                   /* Speculative calls consist of two edges - direct and
> >                      indirect.  Duplicate the whole thing and distribute
> >                      frequencies accordingly.  */
This comment is out of date now.
> >                   if (edge->speculative)
> >                     {
> >                       struct cgraph_edge *direct, *indirect;
> >                       struct ipa_ref *ref;
> > 
> >                       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->num_speculative_call_targets_p ()
> > +                                 > 1)
> > +                       {
> > +                         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);
> > +
> > +                         /* If the indirect edge has multiple speculative
> > +                            calls, iterate through all direct calls
> > +                            associated to the speculative call and clone
> > +                            all related direct edges before cloning the
> > +                            related indirect edge.  */
> > +                         old_edge->speculative_call_info (direct, indirect,
> > +                                                          ref);
> > +                       }
> > 
> >                       profile_count indir_cnt = indirect->count;
> >                       indirect = indirect->clone (id->dst_node, call_stmt,
> >                                                   gimple_uid (stmt),
> >                                                   num, den,
> >                                                   true);
> > 
> >                       profile_probability prob
> >                          = indir_cnt.probability_in (old_cnt + indir_cnt);
> >                       indirect->count
> >                          = copy_basic_block->count.apply_probability (prob);

The udpating of indirect edges needs to be done in loop as well so we
update all of them.

I think you are also not removing the common_target and
common_target_probability from cgraph_edge.
There is now code in ipa-utils merging the histograms. You will need to
update that to your representation. It should not be hard - it either
copies all the values from target function or merges them with given
probability scales.

Honza

Reply via email to