On 07/16/2015 04:05 PM, Martin Liška wrote:
> On 07/10/2015 03:31 PM, Martin Jambor wrote:
>> Hi,
>>
>> thanks for working on this and sorry for a tad late review:
>>
>> On Thu, Jul 09, 2015 at 11:13:52AM +0200, Martin Liska wrote:
>>> gcc/ChangeLog:
>>>
>>> 2015-07-03  Martin Liska  <mli...@suse.cz>
>>>
>>>     * cgraph.c (symbol_table::create_edge): Introduce summary_uid
>>>     for cgraph_edge.
>>>     * cgraph.h (struct GTY): Likewise.
>>
>> struct GTY does not look right :-)
>>
>>>     * ipa-inline-analysis.c (estimate_function_body_sizes): Use
>>>     new data structure.
>>>     * ipa-profile.c (ipa_profile): Likewise.
>>>     * ipa-prop.c (ipa_print_node_jump_functions):
>>
>>                                                       Likewise.
>>
>>>     (ipa_propagate_indirect_call_infos): Likewise.
>>>     (ipa_free_edge_args_substructures): Likewise.
>>>     (ipa_free_all_edge_args): Likewise.
>>>     (ipa_edge_args_t::remove): Likewise.
>>>     (ipa_edge_removal_hook): Likewise.
>>>     (ipa_edge_args_t::duplicate): Likewise.
>>>     (ipa_register_cgraph_hooks): Likewise.
>>>     (ipa_unregister_cgraph_hooks): Likewise.
>>>     * ipa-prop.h (ipa_check_create_edge_args): Likewise.
>>>     (ipa_edge_args_info_available_for_edge_p): Likewise.
>>
>> Definition of ipa_edge_args_t is missing here.
>>
>>>     * symbol-summary.h (gt_ggc_mx): Indent properly.
>>>     (gt_pch_nx): Likewise.
>>>     (edge_summary): New class.
>>> ---
>>>  gcc/cgraph.c              |   2 +
>>>  gcc/cgraph.h              |   5 +-
>>>  gcc/ipa-inline-analysis.c |   2 +-
>>>  gcc/ipa-profile.c         |   2 +-
>>>  gcc/ipa-prop.c            |  71 +++-------------
>>>  gcc/ipa-prop.h            |  44 ++++++----
>>>  gcc/symbol-summary.h      | 208 
>>> +++++++++++++++++++++++++++++++++++++++++++++-
>>>  7 files changed, 252 insertions(+), 82 deletions(-)
>>>
>>
>> ...
>>
>>> diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
>>> index e6725aa..f0af9b2 100644
>>> --- a/gcc/ipa-prop.h
>>> +++ b/gcc/ipa-prop.h
>>> @@ -493,13 +493,36 @@ public:
>>>  extern ipa_node_params_t *ipa_node_params_sum;
>>>  /* Vector of IPA-CP transformation data for each clone.  */
>>>  extern GTY(()) vec<ipcp_transformation_summary, va_gc> 
>>> *ipcp_transformations;
>>> -/* Vector where the parameter infos are actually stored. */
>>> -extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector;
>>> +
>>> +/* Function summary for ipa_node_params.  */
>>> +class GTY((user)) ipa_edge_args_t: public edge_summary <ipa_edge_args *>
>>> +{
>>> +public:
>>> +  ipa_edge_args_t (symbol_table *symtab):
>>> +    edge_summary <ipa_edge_args*> (symtab, true) { }
>>> +
>>> +  static ipa_edge_args_t *create_ggc (symbol_table *symtab)
>>> +  {
>>
>> Please move the body of this function to where the bodies of the rest
>> of the member functions are.
>>
>>> +    ipa_edge_args_t *summary = new (ggc_cleared_alloc <ipa_edge_args_t> ())
>>> +      ipa_edge_args_t (symtab);
>>> +    return summary;
>>> +  }
>>> +
>>> +  /* Hook that is called by summary when a node is duplicated.  */
>>> +  virtual void duplicate (cgraph_edge *edge,
>>> +                     cgraph_edge *edge2,
>>> +                     ipa_edge_args *data,
>>> +                     ipa_edge_args *data2);
>>> +
>>> +  virtual void remove (cgraph_edge *edge, ipa_edge_args *data);
>>> +};
>>> +
>>> +extern GTY(()) edge_summary <ipa_edge_args *> *ipa_edge_args_sum;
>>>  
>>>  /* Return the associated parameter/argument info corresponding to the given
>>>     node/edge.  */
>>>  #define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE))
>>> -#define IPA_EDGE_REF(EDGE) (&(*ipa_edge_args_vector)[(EDGE)->uid])
>>> +#define IPA_EDGE_REF(EDGE) (ipa_edge_args_sum->get (EDGE))
>>>  /* This macro checks validity of index returned by
>>>     ipa_get_param_decl_index function.  */
>>>  #define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1)
>>> @@ -532,19 +555,8 @@ ipa_check_create_node_params (void)
>>>  static inline void
>>>  ipa_check_create_edge_args (void)
>>>  {
>>> -  if (vec_safe_length (ipa_edge_args_vector)
>>> -      <= (unsigned) symtab->edges_max_uid)
>>> -    vec_safe_grow_cleared (ipa_edge_args_vector, symtab->edges_max_uid + 
>>> 1);
>>> -}
>>> -
>>> -/* Returns true if the array of edge infos is large enough to accommodate 
>>> an
>>> -   info for EDGE.  The main purpose of this function is that debug dumping
>>> -   function can check info availability without causing reallocations.  */
>>> -
>>> -static inline bool
>>> -ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge)
>>> -{
>>> -  return ((unsigned) edge->uid < vec_safe_length (ipa_edge_args_vector));
>>> +  if (ipa_edge_args_sum == NULL)
>>> +    ipa_edge_args_sum = ipa_edge_args_t::create_ggc (symtab);
>>>  }
>>>  
>>>  static inline ipcp_transformation_summary *
>>> diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h
>>> index eefbfd9..5799443 100644
>>> --- a/gcc/symbol-summary.h
>>> +++ b/gcc/symbol-summary.h
>>> @@ -108,7 +108,7 @@ public:
>>>    /* Allocates new data that are stored within map.  */
>>>    T* allocate_new ()
>>>    {
>>> -    return m_ggc ? new (ggc_alloc <T> ()) T() : new T () ;
>>> +    return m_ggc ? new (ggc_alloc <T> ()) T () : new T () ;
>>>    }
>>>  
>>>    /* Release an item that is stored within map.  */
>>> @@ -234,7 +234,7 @@ private:
>>>  
>>>  template <typename T>
>>>  void
>>> -gt_ggc_mx(function_summary<T *>* const &summary)
>>> +gt_ggc_mx (function_summary<T *>* const &summary)
>>>  {
>>>    gcc_checking_assert (summary->m_ggc);
>>>    gt_ggc_mx (&summary->m_map);
>>> @@ -242,7 +242,7 @@ gt_ggc_mx(function_summary<T *>* const &summary)
>>>  
>>>  template <typename T>
>>>  void
>>> -gt_pch_nx(function_summary<T *>* const &summary)
>>> +gt_pch_nx (function_summary<T *>* const &summary)
>>>  {
>>>    gcc_checking_assert (summary->m_ggc);
>>>    gt_pch_nx (&summary->m_map);
>>> @@ -250,11 +250,211 @@ gt_pch_nx(function_summary<T *>* const &summary)
>>>  
>>>  template <typename T>
>>>  void
>>> -gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
>>> +gt_pch_nx (function_summary<T *>* const& summary, gt_pointer_operator op,
>>>       void *cookie)
>>>  {
>>>    gcc_checking_assert (summary->m_ggc);
>>>    gt_pch_nx (&summary->m_map, op, cookie);
>>>  }
>>>  
>>> +/* We want to pass just pointer types as argument for edge_summary
>>> +   template class.  */
>>> +
>>> +template <class T>
>>> +class edge_summary
>>> +{
>>> +private:
>>> +  edge_summary ();
>>> +};
>>> +
>>
>> Two general remarks about both summary classes.  First, they both
>> certainly need some descriptive comment.  I assume this can be added
>> as a followup.
>>
>> Second, I'm afraid that having (non-trivial) function definitions
>> inside the class definition violates our coding conventions
>> (https://gcc.gnu.org/codingconventions.html#Member_Form).  I
>> understand that, many other classes throughout gcc also have them, but
>> it seems there is consensus to eradicate it
>> (https://gcc.gnu.org/ml/gcc/2015-06/msg00241.html) so we at least
>> should not be adding new cases.
>>
>> (And I also think that comments need to be separated by a blank line
>> from the stuff they describe, but that is probably a minor issue, at
>> least for me.)
>>
>>> +template <class T>
>>> +class GTY((user)) edge_summary <T *>
>>> +{
>>> +public:
>>> +  /* Default construction takes SYMTAB as an argument.  */
>>> +  edge_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
>>> +    m_map (13, ggc), m_symtab (symtab)
>>> +  {
>>> +#ifdef ENABLE_CHECKING
>>> +    cgraph_node *node;
>>> +
>>> +    FOR_EACH_FUNCTION (node)
>>> +    {
>>
>> I'm quite sure you want to verify edges, not nodes, here.
>>
>>> +      gcc_checking_assert (node->summary_uid > 0);
>>> +    }
>>> +#endif
>>> +
>>> +    m_symtab_removal_hook =
>>> +      symtab->add_edge_removal_hook
>>> +      (edge_summary::symtab_removal, this);
>>> +    m_symtab_duplication_hook =
>>> +      symtab->add_edge_duplication_hook
>>> +      (edge_summary::symtab_duplication, this);
>>> +  }
>>> +
>>> +  /* Destructor.  */
>>> +  virtual ~edge_summary ()
>>> +  {
>>> +    release ();
>>> +  }
>>> +
>>> +  /* Destruction method that can be called for GGT purpose.  */
>>> +  void release ()
>>> +  {
>>> +    if (m_symtab_removal_hook)
>>> +      m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
>>> +
>>> +    if (m_symtab_duplication_hook)
>>> +      m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
>>> +
>>> +    m_symtab_removal_hook = NULL;
>>> +    m_symtab_duplication_hook = NULL;
>>> +
>>> +    /* Release all summaries.  */
>>> +    typedef typename hash_map <map_hash, T *>::iterator map_iterator;
>>> +    for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
>>> +      release ((*it).second);
>>> +  }
>>> +
>>> +  /* Traverses all summarys with a function F called with
>>> +     ARG as argument.  */
>>> +  template<typename Arg, bool (*f)(const T &, Arg)>
>>> +  void traverse (Arg a) const
>>> +  {
>>> +    m_map.traverse <f> (a);
>>> +  }
>>> +
>>> +  /* Initializer is called after we allocate a new node.  */
>>
>> We don't allocate a node but an edge.
>>
>>> +  virtual void initialize (cgraph_edge *, T *) {}
>>> +
>>> +  /* Basic implementation of removal operation.  */
>>> +  virtual void remove (cgraph_edge *, T *) {}
>>> +
>>> +  /* Basic implementation of duplication operation.  */
>>> +  virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
>>
>> Perhaps this should actually be implemented by a simple assignment for
>> very basic summary types?
>>
>>> +
>>> +  /* Allocates new data that are stored within map.  */
>>> +  T* allocate_new (cgraph_edge *edge)
>>> +  {
>>> +    T *v = m_ggc ? new (ggc_alloc <T> ()) T () : new T () ;
>>> +    initialize (edge, v);
>>> +
>>> +    return v;
>>> +  }
>>> +
>>> +  /* Release an item that is stored within map.  */
>>> +  void release (T *item)
>>> +  {
>>> +    if (m_ggc)
>>> +      {
>>> +   item->~T ();
>>> +   ggc_free (item);
>>> +      }
>>> +    else
>>> +      delete item;
>>> +  }
>>> +
>>> +  /* Getter for summary edge node pointer.  */
>>
>> I'd suggest "Getter of edge summary" instead
>>
>>> +  T* get (cgraph_edge *edge)
>>> +  {
>>> +    bool existed;
>>> +    T **v = &m_map.get_or_insert (edge->summary_uid, &existed);
>>> +    if (!existed)
>>> +      *v = allocate_new (edge);
>>> +
>>> +    return *v;
>>> +  }
>>> +
>>> +  /* Return number of elements handled by data structure.  */
>>> +  size_t elements ()
>>> +  {
>>> +    return m_map.elements ();
>>> +  }
>>> +
>>> +  /* Symbol removal hook that is registered to symbol table.  */
>>> +  static void symtab_removal (cgraph_edge *node, void *data)
>>
>> Please call the first parameter "edge"
>>
>>> +  {
>>> +    gcc_checking_assert (node->summary_uid);
>>> +    edge_summary *summary = (edge_summary <T *> *) (data);
>>> +
>>> +    int summary_uid = node->summary_uid;
>>> +    T **v = summary->m_map.get (summary_uid);
>>> +
>>> +    if (v)
>>> +      {
>>> +   summary->remove (node, *v);
>>> +
>>> +   if (!summary->m_ggc)
>>> +     delete (*v);
>>> +
>>> +   summary->m_map.remove (summary_uid);
>>> +      }
>>> +  }
>>> +
>>> +  /* Symbol duplication hook that is registered to symbol table.  */
>>> +  static void symtab_duplication (cgraph_edge *edge, cgraph_edge *edge2,
>>> +                             void *data)
>>> +  {
>>> +    edge_summary *summary = (edge_summary <T *> *) (data);
>>> +    T *s = summary->get (edge);
>>> +
>>> +    gcc_checking_assert (s);
>>> +    gcc_checking_assert (edge2->summary_uid > 0);
>>> +
>>> +    /* This load is necessary, because we insert a new value!  */
>>
>> What load?
>>
>> Apart from the above, I'll be very glad to have this class.
>>
>> Thanks,
>>
>> Martin
>>
> 
> Hello.
> 
> This is v2 of the patch which reflects handy notes by Martin. I decided to 
> separate method implementations
> after their declarations. Apart from that, I decided to merge all changes in 
> IPA inliner to a single patch.
> 
> Thanks,
> Martin
> 
> 

Hello.

Is the patch ready to be installed to trunk branch?

Thanks,
Martin

Reply via email to