LCOV - code coverage report
Current view: top level - gcc - symbol-summary.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.6 % 284 263
Test Date: 2026-02-28 14:20:25 Functions: 76.1 % 519 395
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Callgraph summary data structure.
       2              :    Copyright (C) 2014-2026 Free Software Foundation, Inc.
       3              :    Contributed by Martin Liska
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #ifndef GCC_SYMBOL_SUMMARY_H
      22              : #define GCC_SYMBOL_SUMMARY_H
      23              : 
      24              : /* Base class for function_summary and fast_function_summary classes.  */
      25              : 
      26              : template <class T>
      27     14467510 : class function_summary_base
      28              : {
      29              : public:
      30              :   /* Default construction takes SYMTAB as an argument.  */
      31      7329658 :   function_summary_base (symbol_table *symtab,
      32              :                          cgraph_node_hook symtab_insertion,
      33              :                          cgraph_node_hook symtab_removal,
      34              :                          cgraph_2node_hook symtab_duplication
      35              :                          CXX_MEM_STAT_INFO):
      36      7329658 :   m_symtab (symtab), m_symtab_insertion (symtab_insertion),
      37      7329658 :   m_symtab_removal (symtab_removal),
      38      7329658 :   m_symtab_duplication (symtab_duplication),
      39      7329658 :   m_symtab_insertion_hook (NULL), m_symtab_duplication_hook (NULL),
      40      7329658 :   m_allocator ("function summary" PASS_MEM_STAT)
      41              :   {
      42      7329658 :     enable_insertion_hook ();
      43              :     m_symtab_removal_hook
      44      7329658 :       = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this);
      45      7329658 :     enable_duplication_hook ();
      46      7329658 :   }
      47              : 
      48              :   /* Basic implementation of insert operation.  */
      49            0 :   virtual void insert (cgraph_node *, T *)
      50              :   {
      51              :     /* In most cases, it makes no sense to create summaries without
      52              :        initializing them.  */
      53            0 :     gcc_unreachable ();
      54              :   }
      55              : 
      56              :   /* Basic implementation of removal operation.  */
      57            0 :   virtual void remove (cgraph_node *, T *) {}
      58              : 
      59              :   /* Basic implementation of duplication operation.  */
      60            0 :   virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
      61              :   {
      62              :     /* It makes no sense to not copy anything during duplication.  */
      63            0 :     gcc_unreachable ();
      64              :   }
      65              : 
      66              :   /* Enable insertion hook invocation.  */
      67      7571666 :   void enable_insertion_hook ()
      68              :   {
      69      7571666 :     if (m_symtab_insertion_hook == NULL)
      70              :       m_symtab_insertion_hook
      71      7571666 :         = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
      72      7571666 :   }
      73              : 
      74              :   /* Disable insertion hook invocation.  */
      75     13800986 :   void disable_insertion_hook ()
      76              :   {
      77     13800986 :     if (m_symtab_insertion_hook != NULL)
      78              :       {
      79      7562193 :         m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
      80      7562193 :         m_symtab_insertion_hook = NULL;
      81              :       }
      82     13800986 :   }
      83              : 
      84              :   /* Enable duplication hook invocation.  */
      85      7329658 :   void enable_duplication_hook ()
      86              :   {
      87      7329658 :     if (m_symtab_duplication_hook == NULL)
      88              :       m_symtab_duplication_hook
      89      7329658 :         = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this);
      90      7329658 :   }
      91              : 
      92              :   /* Enable duplication hook invocation.  */
      93      7483728 :   void disable_duplication_hook ()
      94              :   {
      95      7483728 :     if (m_symtab_duplication_hook != NULL)
      96              :       {
      97      7233767 :         m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
      98      7233767 :         m_symtab_duplication_hook = NULL;
      99              :       }
     100      7483728 :   }
     101              : 
     102              : protected:
     103              :   /* Allocates new data that are stored within map.  */
     104     41340061 :   T* allocate_new ()
     105              :   {
     106              :     /* Call gcc_internal_because we do not want to call finalizer for
     107              :        a type T.  We call dtor explicitly.  */
     108     68874523 :     return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
     109     13805599 :                      : m_allocator.allocate () ;
     110              :   }
     111              : 
     112              :   /* Release an item that is stored within map.  */
     113     41094598 :   void release (T *item)
     114              :   {
     115     41094598 :     if (is_ggc ())
     116     27330739 :       ggc_delete (item);
     117              :     else
     118     13763859 :       m_allocator.remove (item);
     119     41094598 :   }
     120              : 
     121              :   /* Unregister all call-graph hooks.  */
     122              :   void unregister_hooks ();
     123              : 
     124              :   /* Symbol table the summary is registered to.  */
     125              :   symbol_table *m_symtab;
     126              : 
     127              :   /* Insertion function defined by a summary.  */
     128              :   cgraph_node_hook m_symtab_insertion;
     129              :   /* Removal function defined by a summary.  */
     130              :   cgraph_node_hook m_symtab_removal;
     131              :   /* Duplication function defined by a summary.  */
     132              :   cgraph_2node_hook m_symtab_duplication;
     133              : 
     134              :   /* Internal summary insertion hook pointer.  */
     135              :   cgraph_node_hook_list *m_symtab_insertion_hook;
     136              :   /* Internal summary removal hook pointer.  */
     137              :   cgraph_node_hook_list *m_symtab_removal_hook;
     138              :   /* Internal summary duplication hook pointer.  */
     139              :   cgraph_2node_hook_list *m_symtab_duplication_hook;
     140              : 
     141              : private:
     142              :   /* Return true when the summary uses GGC memory for allocation.  */
     143              :   virtual bool is_ggc () = 0;
     144              : 
     145              :   /* Object allocator for heap allocation.  */
     146              :   object_allocator<T> m_allocator;
     147              : };
     148              : 
     149              : template <typename T>
     150              : void
     151      7233755 : function_summary_base<T>::unregister_hooks ()
     152              : {
     153      7233755 :   disable_insertion_hook ();
     154      7233755 :   m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
     155      7233755 :   disable_duplication_hook ();
     156      7233755 : }
     157              : 
     158              : /* We want to pass just pointer types as argument for function_summary
     159              :    template class.  */
     160              : 
     161              : template <class T>
     162              : class function_summary
     163              : {
     164              : private:
     165              :   function_summary();
     166              : };
     167              : 
     168              : /* Function summary is a helper class that is used to associate a data structure
     169              :    related to a callgraph node.  Typical usage can be seen in IPA passes which
     170              :    create a temporary pass-related structures.  The summary class registers
     171              :    hooks that are triggered when a new node is inserted, duplicated and deleted.
     172              :    A user of a summary class can ovewrite virtual methods than are triggered by
     173              :    the summary if such hook is triggered.  Apart from a callgraph node, the user
     174              :    is given a data structure tied to the node.
     175              : 
     176              :    The function summary class can work both with a heap-allocated memory and
     177              :    a memory gained by garbage collected memory.  */
     178              : 
     179              : template <class T>
     180              : class GTY((user)) function_summary <T *>: public function_summary_base<T>
     181              : {
     182              : public:
     183              :   /* Default construction takes SYMTAB as an argument.  */
     184              :   function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
     185              : 
     186              :   /* Destructor.  */
     187              :   virtual ~function_summary ();
     188              : 
     189              :   /* Traverses all summarys with a function F called with
     190              :      ARG as argument.  */
     191              :   template<typename Arg, bool (*f)(const T &, Arg)>
     192              :   void traverse (Arg a) const
     193              :   {
     194              :     m_map.template traverse <f> (a);
     195              :   }
     196              : 
     197              :   /* Getter for summary callgraph node pointer.  If a summary for a node
     198              :      does not exist it will be created.  */
     199     19299996 :   T* get_create (cgraph_node *node)
     200              :   {
     201              :     bool existed;
     202     19299996 :     T **v = &m_map.get_or_insert (node->get_uid (), &existed);
     203     19299996 :     if (!existed)
     204      9933797 :       *v = this->allocate_new ();
     205              : 
     206     19299996 :     return *v;
     207              :   }
     208              : 
     209              :   /* Getter for summary callgraph node pointer.  */
     210    130890625 :   T* get (cgraph_node *node) ATTRIBUTE_PURE
     211              :   {
     212    130890625 :     T **v = m_map.get (node->get_uid ());
     213    130890625 :     return v == NULL ? NULL : *v;
     214              :   }
     215              : 
     216              :   /* Remove node from summary.  */
     217              :   using function_summary_base<T>::remove;
     218     10632316 :   void remove (cgraph_node *node)
     219              :   {
     220     10632316 :     int uid = node->get_uid ();
     221     10632316 :     T **v = m_map.get (uid);
     222     10632316 :     if (v)
     223              :       {
     224      2356790 :         m_map.remove (uid);
     225      2356790 :         this->release (*v);
     226              :       }
     227     10632316 :   }
     228              : 
     229              :   /* Return true if a summary for the given NODE already exists.  */
     230              :   bool exists (cgraph_node *node)
     231              :   {
     232              :     return m_map.get (node->get_uid ()) != NULL;
     233              :   }
     234              : 
     235              :   /* Symbol insertion hook that is registered to symbol table.  */
     236              :   static void symtab_insertion (cgraph_node *node, void *data);
     237              : 
     238              :   /* Symbol removal hook that is registered to symbol table.  */
     239              :   static void symtab_removal (cgraph_node *node, void *data);
     240              : 
     241              :   /* Symbol duplication hook that is registered to symbol table.  */
     242              :   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
     243              :                                   void *data);
     244              : 
     245              : protected:
     246              :   /* Indication if we use ggc summary.  */
     247              :   bool m_ggc;
     248              : 
     249              : private:
     250              :   /* Indication if we use ggc summary.  */
     251     19664554 :   bool is_ggc () final override
     252              :   {
     253     19664554 :     return m_ggc;
     254              :   }
     255              : 
     256              :   typedef int_hash <int, 0, -1> map_hash;
     257              : 
     258              :   /* Main summary store, where summary ID is used as key.  */
     259              :   hash_map <map_hash, T *> m_map;
     260              : 
     261              :   template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
     262              :   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
     263              :   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
     264              :       gt_pointer_operator, void *);
     265              : };
     266              : 
     267              : template <typename T>
     268      5404172 : function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
     269              :                                          MEM_STAT_DECL):
     270              :   function_summary_base<T> (symtab, function_summary::symtab_insertion,
     271              :                             function_summary::symtab_removal,
     272              :                             function_summary::symtab_duplication
     273              :                             PASS_MEM_STAT),
     274      5404172 :   m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
     275              : 
     276              : template <typename T>
     277      5341589 : function_summary<T *>::~function_summary ()
     278              : {
     279      5317963 :   this->unregister_hooks ();
     280              : 
     281              :   /* Release all summaries.  */
     282              :   typedef typename hash_map <map_hash, T *>::iterator map_iterator;
     283     20065897 :   for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
     284      7373967 :     this->release ((*it).second);
     285     10659552 : }
     286              : 
     287              : template <typename T>
     288              : void
     289        18046 : function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
     290              : {
     291        18046 :   gcc_checking_assert (node->get_uid ());
     292        18046 :   function_summary *summary = (function_summary <T *> *) (data);
     293        18046 :   summary->insert (node, summary->get_create (node));
     294        18046 : }
     295              : 
     296              : template <typename T>
     297              : void
     298      9042154 : function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
     299              : {
     300      9042154 :   gcc_checking_assert (node->get_uid ());
     301      9042154 :   function_summary *summary = (function_summary <T *> *) (data);
     302      9042154 :   summary->remove (node);
     303      9042154 : }
     304              : 
     305              : template <typename T>
     306              : void
     307      5194867 : function_summary<T *>::symtab_duplication (cgraph_node *node,
     308              :                                            cgraph_node *node2, void *data)
     309              : {
     310      5194867 :   function_summary *summary = (function_summary <T *> *) (data);
     311      5194867 :   T *v = summary->get (node);
     312              : 
     313      5194867 :   if (v)
     314      1504645 :     summary->duplicate (node, node2, v, summary->get_create (node2));
     315      5194867 : }
     316              : 
     317              : template <typename T>
     318              : void
     319       515139 : gt_ggc_mx(function_summary<T *>* const &summary)
     320              : {
     321       515139 :   gcc_checking_assert (summary->m_ggc);
     322       515139 :   gt_ggc_mx (&summary->m_map);
     323       515139 : }
     324              : 
     325              : template <typename T>
     326              : void
     327            0 : gt_pch_nx (function_summary<T *> *const &)
     328              : {
     329            0 :   gcc_unreachable ();
     330              : }
     331              : 
     332              : template <typename T>
     333              : void
     334            0 : gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
     335              : {
     336            0 :   gcc_unreachable ();
     337              : }
     338              : 
     339              : /* Help template from std c++11.  */
     340              : 
     341              : template<typename T, typename U>
     342              : struct is_same
     343              : {
     344              :     static const bool value = false;
     345              : };
     346              : 
     347              : template<typename T>
     348              : struct is_same<T,T>  //specialization
     349              : {
     350              :    static const bool value = true;
     351              : };
     352              : 
     353              : /* We want to pass just pointer types as argument for fast_function_summary
     354              :    template class.  */
     355              : 
     356              : template <class T, class V>
     357              : class fast_function_summary
     358              : {
     359              : private:
     360              :   fast_function_summary ();
     361              : };
     362              : 
     363              : /* Function vector summary is a fast implementation of function_summary that
     364              :    utilizes vector as primary storage of summaries.  */
     365              : 
     366              : template <class T, class V>
     367              : class GTY((user)) fast_function_summary <T *, V>
     368              :   : public function_summary_base<T>
     369              : {
     370              : public:
     371              :   /* Default construction takes SYMTAB as an argument.  */
     372              :   fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
     373              : 
     374              :   /* Destructor.  */
     375              :   virtual ~fast_function_summary ();
     376              : 
     377              :   /* Traverses all summarys with a function F called with
     378              :      ARG as argument.  */
     379              :   template<typename Arg, bool (*f)(const T &, Arg)>
     380              :   void traverse (Arg a) const
     381              :   {
     382              :     for (unsigned i = 0; i < m_vector->length (); i++)
     383              :       if ((*m_vector[i]) != NULL)
     384              :         f ((*m_vector)[i], a);
     385              :   }
     386              : 
     387              :   /* Getter for summary callgraph node pointer.  If a summary for a node
     388              :      does not exist it will be created.  */
     389     53549341 :   T* get_create (cgraph_node *node)
     390              :   {
     391     53549341 :     int id = node->get_summary_id ();
     392     53549341 :     if (id == -1)
     393      6156287 :       id = this->m_symtab->assign_summary_id (node);
     394              : 
     395     53549341 :     if ((unsigned int)id >= m_vector->length ())
     396     10215511 :       vec_safe_grow_cleared (m_vector,
     397     10215511 :                              this->m_symtab->cgraph_max_summary_id);
     398              : 
     399     53549341 :     if ((*m_vector)[id] == NULL)
     400     31406264 :       (*m_vector)[id] = this->allocate_new ();
     401              : 
     402     53549341 :     return (*m_vector)[id];
     403              :   }
     404              : 
     405              :   /* Getter for summary callgraph node pointer.  */
     406    460953599 :   T* get (cgraph_node *node) ATTRIBUTE_PURE
     407              :   {
     408    460953599 :     return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
     409              :   }
     410              : 
     411              :   using function_summary_base<T>::remove;
     412     28552559 :   void remove (cgraph_node *node)
     413              :   {
     414     28552559 :     if (exists (node))
     415              :       {
     416     17287312 :         int id = node->get_summary_id ();
     417     17287312 :         this->release ((*m_vector)[id]);
     418     17287312 :         (*m_vector)[id] = NULL;
     419              :       }
     420     28552559 :   }
     421              : 
     422              :   /* Return true if a summary for the given NODE already exists.  */
     423    508444555 :   bool exists (cgraph_node *node)
     424              :   {
     425    508444555 :     int id = node->get_summary_id ();
     426              :     return (id != -1
     427    503816527 :             && (unsigned int)id < m_vector->length ()
     428   1000329516 :             && (*m_vector)[id] != NULL);
     429              :   }
     430              : 
     431              :   /* Symbol insertion hook that is registered to symbol table.  */
     432              :   static void symtab_insertion (cgraph_node *node, void *data);
     433              : 
     434              :   /* Symbol removal hook that is registered to symbol table.  */
     435              :   static void symtab_removal (cgraph_node *node, void *data);
     436              : 
     437              :   /* Symbol duplication hook that is registered to symbol table.  */
     438              :   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
     439              :                                   void *data);
     440              : 
     441              : private:
     442              :   bool is_ggc () final override;
     443              : 
     444              :   /* Summary is stored in the vector.  */
     445              :   vec <T *, V> *m_vector;
     446              : 
     447              :   template <typename U> friend void gt_ggc_mx (fast_function_summary <U *, va_gc> * const &);
     448              :   template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &);
     449              :   template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &,
     450              :       gt_pointer_operator, void *);
     451              : };
     452              : 
     453              : template <typename T, typename V>
     454      1925486 : fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab
     455              :                                                       MEM_STAT_DECL):
     456              :   function_summary_base<T> (symtab,
     457              :                             fast_function_summary::symtab_insertion,
     458              :                             fast_function_summary::symtab_removal,
     459              :                             fast_function_summary::symtab_duplication
     460      1925486 :                             PASS_MEM_STAT), m_vector (NULL)
     461              : {
     462      1925486 :   vec_alloc (m_vector, 13 PASS_MEM_STAT);
     463      1925486 : }
     464              : 
     465              : template <typename T, typename V>
     466      2145851 : fast_function_summary<T *, V>::~fast_function_summary ()
     467              : {
     468      1915792 :   this->unregister_hooks ();
     469              : 
     470              :   /* Release all summaries.  */
     471     24922556 :   for (unsigned i = 0; i < m_vector->length (); i++)
     472     23006764 :     if ((*m_vector)[i] != NULL)
     473     14076529 :       this->release ((*m_vector)[i]);
     474      1915792 :   vec_free (m_vector);
     475      4061643 : }
     476              : 
     477              : template <typename T, typename V>
     478              : void
     479       128045 : fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
     480              : {
     481       128045 :   gcc_checking_assert (node->get_uid ());
     482       128045 :   fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
     483       128045 :   summary->insert (node, summary->get_create (node));
     484       128045 : }
     485              : 
     486              : template <typename T, typename V>
     487              : void
     488     13386494 : fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
     489              : {
     490     13386494 :   gcc_checking_assert (node->get_uid ());
     491     13386494 :   fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
     492              : 
     493     13386494 :   if (summary->exists (node))
     494      4375146 :     summary->remove (node);
     495     13386494 : }
     496              : 
     497              : template <typename T, typename V>
     498              : void
     499     11501455 : fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
     500              :                                                    cgraph_node *node2,
     501              :                                                    void *data)
     502              : {
     503     11501455 :   fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
     504     11501455 :   T *v = summary->get (node);
     505              : 
     506     11501455 :   if (v)
     507              :     {
     508      9726065 :       T *duplicate = summary->get_create (node2);
     509      9726065 :       summary->duplicate (node, node2, v, duplicate);
     510              :     }
     511     11501455 : }
     512              : 
     513              : template <typename T, typename V>
     514              : inline bool
     515     62770105 : fast_function_summary<T *, V>::is_ggc ()
     516              : {
     517     62770105 :   return is_same<V, va_gc>::value;
     518              : }
     519              : 
     520              : template <typename T>
     521              : void
     522              : gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
     523              : {
     524              : }
     525              : 
     526              : template <typename T>
     527              : void
     528              : gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
     529              : {
     530              : }
     531              : 
     532              : template <typename T>
     533              : void
     534              : gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
     535              :            void *)
     536              : {
     537              : }
     538              : 
     539              : template <typename T>
     540              : void
     541       584688 : gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
     542              : {
     543       584688 :   ggc_test_and_set_mark (summary->m_vector);
     544       584688 :   gt_ggc_mx (summary->m_vector);
     545       584688 : }
     546              : 
     547              : template <typename T>
     548              : void
     549            0 : gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
     550              : {
     551            0 :   gcc_unreachable ();
     552              : }
     553              : 
     554              : template <typename T>
     555              : void
     556            0 : gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
     557              :            void *)
     558              : {
     559            0 :   gcc_unreachable ();
     560              : }
     561              : 
     562              : /* Base class for call_summary and fast_call_summary classes.  */
     563              : 
     564              : template <class T>
     565      3322818 : class call_summary_base
     566              : {
     567              : public:
     568              :   /* Default construction takes SYMTAB as an argument.  */
     569      1661423 :   call_summary_base (symbol_table *symtab, cgraph_edge_hook symtab_removal,
     570              :                      cgraph_2edge_hook symtab_duplication CXX_MEM_STAT_INFO):
     571      1661423 :   m_symtab (symtab), m_symtab_removal (symtab_removal),
     572      1661423 :   m_symtab_duplication (symtab_duplication), m_symtab_duplication_hook (NULL),
     573      1661423 :   m_initialize_when_cloning (false),
     574      1661423 :   m_allocator ("call summary" PASS_MEM_STAT)
     575              :   {
     576              :     m_symtab_removal_hook
     577      1661423 :       = m_symtab->add_edge_removal_hook (m_symtab_removal, this);
     578      1661423 :     enable_duplication_hook ();
     579      1661423 :   }
     580              : 
     581              :   /* Basic implementation of removal operation.  */
     582            0 :   virtual void remove (cgraph_edge *, T *) {}
     583              : 
     584              :   /* Basic implementation of duplication operation.  */
     585            0 :   virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
     586              :   {
     587            0 :     gcc_unreachable ();
     588              :   }
     589              : 
     590              :   /* Enable duplication hook invocation.  */
     591      1661423 :   void enable_duplication_hook ()
     592              :   {
     593      1661423 :     if (m_symtab_duplication_hook == NULL)
     594              :       m_symtab_duplication_hook
     595      1661423 :         = m_symtab->add_edge_duplication_hook (m_symtab_duplication,
     596              :                                                this);
     597      1661423 :   }
     598              : 
     599              :   /* Enable duplication hook invocation.  */
     600      1891468 :   void disable_duplication_hook ()
     601              :   {
     602      1891468 :     if (m_symtab_duplication_hook != NULL)
     603              :       {
     604      1661409 :         m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
     605      1661409 :         m_symtab_duplication_hook = NULL;
     606              :       }
     607      1891468 :   }
     608              : 
     609              : protected:
     610              :   /* Allocates new data that are stored within map.  */
     611     45673738 :   T* allocate_new ()
     612              :   {
     613              :     /* Call gcc_internal_because we do not want to call finalizer for
     614              :        a type T.  We call dtor explicitly.  */
     615     48602726 :     return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
     616     41270437 :                      : m_allocator.allocate ();
     617              :   }
     618              : 
     619              :   /* Release an item that is stored within map.  */
     620     45673738 :   void release (T *item)
     621              :   {
     622     45673738 :     if (is_ggc ())
     623      4403301 :       ggc_delete (item);
     624              :     else
     625     41270437 :       m_allocator.remove (item);
     626     45673738 :   }
     627              : 
     628              :   /* Unregister all call-graph hooks.  */
     629              :   void unregister_hooks ();
     630              : 
     631              :   /* Symbol table the summary is registered to.  */
     632              :   symbol_table *m_symtab;
     633              : 
     634              :   /* Removal function defined by a summary.  */
     635              :   cgraph_edge_hook m_symtab_removal;
     636              :   /* Duplication function defined by a summary.  */
     637              :   cgraph_2edge_hook m_symtab_duplication;
     638              : 
     639              :   /* Internal summary removal hook pointer.  */
     640              :   cgraph_edge_hook_list *m_symtab_removal_hook;
     641              :   /* Internal summary duplication hook pointer.  */
     642              :   cgraph_2edge_hook_list *m_symtab_duplication_hook;
     643              :   /* Initialize summary for an edge that is cloned.  */
     644              :   bool m_initialize_when_cloning;
     645              : 
     646              : private:
     647              :   /* Return true when the summary uses GGC memory for allocation.  */
     648              :   virtual bool is_ggc () = 0;
     649              : 
     650              :   /* Object allocator for heap allocation.  */
     651              :   object_allocator<T> m_allocator;
     652              : };
     653              : 
     654              : template <typename T>
     655              : void
     656      1661409 : call_summary_base<T>::unregister_hooks ()
     657              : {
     658      1661409 :   m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
     659      1661409 :   disable_duplication_hook ();
     660      1661409 : }
     661              : 
     662              : /* An impossible class templated by non-pointers so, which makes sure that only
     663              :    summaries gathering pointers can be created.  */
     664              : 
     665              : template <class T>
     666              : class call_summary
     667              : {
     668              : private:
     669              :   call_summary ();
     670              : };
     671              : 
     672              : /* Class to store auxiliary information about call graph edges.  */
     673              : 
     674              : template <class T>
     675              : class GTY((user)) call_summary <T *>: public call_summary_base<T>
     676              : {
     677              : public:
     678              :   /* Default construction takes SYMTAB as an argument.  */
     679       977304 :   call_summary (symbol_table *symtab, bool ggc = false
     680              :                 CXX_MEM_STAT_INFO)
     681              :   : call_summary_base<T> (symtab, call_summary::symtab_removal,
     682              :                           call_summary::symtab_duplication PASS_MEM_STAT),
     683       977304 :     m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
     684              : 
     685              :   /* Destructor.  */
     686              :   virtual ~call_summary ();
     687              : 
     688              :   /* Traverses all summarys with an edge E called with
     689              :      ARG as argument.  */
     690              :   template<typename Arg, bool (*f)(const T &, Arg)>
     691              :   void traverse (Arg a) const
     692              :   {
     693              :     m_map.template traverse <f> (a);
     694              :   }
     695              : 
     696              :   /* Getter for summary callgraph edge pointer.
     697              :      If a summary for an edge does not exist, it will be created.  */
     698     15693417 :   T* get_create (cgraph_edge *edge)
     699              :   {
     700              :     bool existed;
     701     15693417 :     T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
     702     15693417 :     if (!existed)
     703     12495691 :       *v = this->allocate_new ();
     704              : 
     705     15693417 :     return *v;
     706              :   }
     707              : 
     708              :   /* Getter for summary callgraph edge pointer.  */
     709     58857297 :   T* get (cgraph_edge *edge) ATTRIBUTE_PURE
     710              :   {
     711     58857297 :     T **v = m_map.get (edge->get_uid ());
     712     58857297 :     return v == NULL ? NULL : *v;
     713              :   }
     714              : 
     715              :   /* Remove edge from summary.  */
     716              :   using call_summary_base<T>::remove;
     717     11255363 :   void remove (cgraph_edge *edge)
     718              :   {
     719     11255363 :     int uid = edge->get_uid ();
     720     11255363 :     T **v = m_map.get (uid);
     721     11255363 :     if (v)
     722              :       {
     723      2225462 :         m_map.remove (uid);
     724      2225462 :         this->release (*v);
     725              :       }
     726     11255363 :   }
     727              : 
     728              :   /* Return true if a summary for the given EDGE already exists.  */
     729         1212 :   bool exists (cgraph_edge *edge)
     730              :   {
     731         1212 :     return m_map.get (edge->get_uid ()) != NULL;
     732              :   }
     733              : 
     734              :   /* Symbol removal hook that is registered to symbol table.  */
     735              :   static void symtab_removal (cgraph_edge *edge, void *data);
     736              : 
     737              :   /* Symbol duplication hook that is registered to symbol table.  */
     738              :   static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
     739              :                                   void *data);
     740              : 
     741              : protected:
     742              :   /* Indication if we use ggc summary.  */
     743              :   bool m_ggc;
     744              : 
     745              : private:
     746              :   /* Indication if we use ggc summary.  */
     747     24991382 :   bool is_ggc () final override
     748              :   {
     749     24991382 :     return m_ggc;
     750              :   }
     751              : 
     752              :   typedef int_hash <int, 0, -1> map_hash;
     753              : 
     754              :   /* Main summary store, where summary ID is used as key.  */
     755              :   hash_map <map_hash, T *> m_map;
     756              : 
     757              :   template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
     758              :   template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
     759              :   template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
     760              :       gt_pointer_operator, void *);
     761              : };
     762              : 
     763              : template <typename T>
     764       977295 : call_summary<T *>::~call_summary ()
     765              : {
     766       977295 :   this->unregister_hooks ();
     767              : 
     768              :   /* Release all summaries.  */
     769              :   typedef typename hash_map <map_hash, T *>::iterator map_iterator;
     770     21517753 :   for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
     771     10270229 :     this->release ((*it).second);
     772      1954590 : }
     773              : 
     774              : template <typename T>
     775              : void
     776      6144228 : call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
     777              : {
     778      6144228 :   call_summary *summary = (call_summary <T *> *) (data);
     779      6144228 :   summary->remove (edge);
     780      6144228 : }
     781              : 
     782              : template <typename T>
     783              : void
     784      9743121 : call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
     785              :                                        cgraph_edge *edge2, void *data)
     786              : {
     787      9743121 :   call_summary *summary = (call_summary <T *> *) (data);
     788      9743121 :   T *edge1_summary = NULL;
     789              : 
     790      9743121 :   if (summary->m_initialize_when_cloning)
     791       199809 :     edge1_summary = summary->get_create (edge1);
     792              :   else
     793      9543312 :     edge1_summary = summary->get (edge1);
     794              : 
     795      9743121 :   if (edge1_summary)
     796      2733721 :     summary->duplicate (edge1, edge2, edge1_summary,
     797              :                         summary->get_create (edge2));
     798      9743121 : }
     799              : 
     800              : template <typename T>
     801              : void
     802         7728 : gt_ggc_mx(call_summary<T *>* const &summary)
     803              : {
     804         7728 :   gcc_checking_assert (summary->m_ggc);
     805         7728 :   gt_ggc_mx (&summary->m_map);
     806         7728 : }
     807              : 
     808              : template <typename T>
     809              : void
     810            0 : gt_pch_nx (call_summary<T *> *const &)
     811              : {
     812            0 :   gcc_unreachable ();
     813              : }
     814              : 
     815              : template <typename T>
     816              : void
     817            0 : gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
     818              : {
     819            0 :   gcc_unreachable ();
     820              : }
     821              : 
     822              : /* We want to pass just pointer types as argument for fast_call_summary
     823              :    template class.  */
     824              : 
     825              : template <class T, class V>
     826              : class fast_call_summary
     827              : {
     828              : private:
     829              :   fast_call_summary ();
     830              : };
     831              : 
     832              : /* Call vector summary is a fast implementation of call_summary that
     833              :    utilizes vector as primary storage of summaries.  */
     834              : 
     835              : template <class T, class V>
     836              : class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
     837              : {
     838              : public:
     839              :   /* Default construction takes SYMTAB as an argument.  */
     840       684119 :   fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
     841              :   : call_summary_base<T> (symtab, fast_call_summary::symtab_removal,
     842              :                           fast_call_summary::symtab_duplication PASS_MEM_STAT),
     843       684119 :     m_vector (NULL)
     844              :   {
     845       684119 :     vec_alloc (m_vector, 13 PASS_MEM_STAT);
     846       684119 :   }
     847              : 
     848              :   /* Destructor.  */
     849              :   virtual ~fast_call_summary ();
     850              : 
     851              :   /* Traverses all summarys with an edge F called with
     852              :      ARG as argument.  */
     853              :   template<typename Arg, bool (*f)(const T &, Arg)>
     854              :   void traverse (Arg a) const
     855              :   {
     856              :     for (unsigned i = 0; i < m_vector->length (); i++)
     857              :       if ((*m_vector[i]) != NULL)
     858              :         f ((*m_vector)[i], a);
     859              :   }
     860              : 
     861              :   /* Getter for summary callgraph edge pointer.
     862              :      If a summary for an edge does not exist, it will be created.  */
     863     37402298 :   T* get_create (cgraph_edge *edge)
     864              :   {
     865     37402298 :     int id = edge->get_summary_id ();
     866     37402298 :     if (id == -1)
     867     21184555 :       id = this->m_symtab->assign_summary_id (edge);
     868              : 
     869     37402298 :     if ((unsigned)id >= m_vector->length ())
     870      9450850 :       vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
     871              : 
     872     37402298 :     if ((*m_vector)[id] == NULL)
     873     33178047 :       (*m_vector)[id] = this->allocate_new ();
     874              : 
     875     37402298 :     return (*m_vector)[id];
     876              :   }
     877              : 
     878              :   /* Getter for summary callgraph edge pointer.  */
     879    683604408 :   T* get (cgraph_edge *edge) ATTRIBUTE_PURE
     880              :   {
     881    683604408 :     return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL;
     882              :   }
     883              : 
     884              :   /* Remove edge from summary.  */
     885              :   using call_summary_base<T>::remove;
     886     56203879 :   void remove (cgraph_edge *edge)
     887              :   {
     888     56203879 :     if (exists (edge))
     889              :       {
     890     19078275 :         int id = edge->get_summary_id ();
     891     19078275 :         this->release ((*m_vector)[id]);
     892     19078275 :         (*m_vector)[id] = NULL;
     893              :       }
     894     56203879 :   }
     895              : 
     896              :   /* Return true if a summary for the given EDGE already exists.  */
     897    739808287 :   bool exists (cgraph_edge *edge)
     898              :   {
     899    739808287 :     int id = edge->get_summary_id ();
     900              :     return (id != -1
     901    789273975 :             && (unsigned)id < m_vector->length ()
     902   1438638418 :             && (*m_vector)[id] != NULL);
     903              :   }
     904              : 
     905              :   /* Symbol removal hook that is registered to symbol table.  */
     906              :   static void symtab_removal (cgraph_edge *edge, void *data);
     907              : 
     908              :   /* Symbol duplication hook that is registered to symbol table.  */
     909              :   static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
     910              :                                   void *data);
     911              : 
     912              : private:
     913              :   bool is_ggc () final override;
     914              : 
     915              :   /* Summary is stored in the vector.  */
     916              :   vec <T *, V> *m_vector;
     917              : 
     918              :   template <typename U> friend void gt_ggc_mx (fast_call_summary <U *, va_gc> * const &);
     919              :   template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &);
     920              :   template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &,
     921              :       gt_pointer_operator, void *);
     922              : };
     923              : 
     924              : template <typename T, typename V>
     925       914173 : fast_call_summary<T *, V>::~fast_call_summary ()
     926              : {
     927       684114 :   this->unregister_hooks ();
     928              : 
     929              :   /* Release all summaries.  */
     930     21925505 :   for (unsigned i = 0; i < m_vector->length (); i++)
     931     21241391 :     if ((*m_vector)[i] != NULL)
     932     14099772 :       this->release ((*m_vector)[i]);
     933       684114 :   vec_free (m_vector);
     934      1598287 : }
     935              : 
     936              : template <typename T, typename V>
     937              : void
     938     21969497 : fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
     939              : {
     940     21969497 :   fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
     941     21969497 :   summary->remove (edge);
     942     21969497 : }
     943              : 
     944              : template <typename T, typename V>
     945              : void
     946      4263044 : fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
     947              :                                                  cgraph_edge *edge2, void *data)
     948              : {
     949      4263044 :   fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
     950      4263044 :   T *edge1_summary = NULL;
     951              : 
     952      4263044 :   if (summary->m_initialize_when_cloning)
     953            0 :     edge1_summary = summary->get_create (edge1);
     954              :   else
     955      4263044 :     edge1_summary = summary->get (edge1);
     956              : 
     957      4263044 :   if (edge1_summary)
     958              :     {
     959      3647070 :       T *duplicate = summary->get_create (edge2);
     960      3647070 :       summary->duplicate (edge1, edge2, edge1_summary, duplicate);
     961              :     }
     962      4263044 : }
     963              : 
     964              : template <typename T, typename V>
     965              : inline bool
     966     66356094 : fast_call_summary<T *, V>::is_ggc ()
     967              : {
     968     66356094 :   return is_same<V, va_gc>::value;
     969              : }
     970              : 
     971              : template <typename T>
     972              : void
     973              : gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
     974              : {
     975              : }
     976              : 
     977              : template <typename T>
     978              : void
     979              : gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
     980              : {
     981              : }
     982              : 
     983              : template <typename T>
     984              : void
     985              : gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
     986              :            gt_pointer_operator op ATTRIBUTE_UNUSED,
     987              :            void *cookie ATTRIBUTE_UNUSED)
     988              : {
     989              : }
     990              : 
     991              : template <typename T>
     992              : void
     993              : gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary)
     994              : {
     995              :   ggc_test_and_set_mark (summary->m_vector);
     996              :   gt_ggc_mx (&summary->m_vector);
     997              : }
     998              : 
     999              : template <typename T>
    1000              : void
    1001              : gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
    1002              : {
    1003              :   gcc_unreachable ();
    1004              : }
    1005              : 
    1006              : template <typename T>
    1007              : void
    1008              : gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
    1009              : {
    1010              :   gcc_unreachable ();
    1011              : }
    1012              : 
    1013              : #endif  /* GCC_SYMBOL_SUMMARY_H  */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.