Home | History | Annotate | Line # | Download | only in gcc
symbol-summary.h revision 1.4
      1  1.1  mrg /* Callgraph summary data structure.
      2  1.4  mrg    Copyright (C) 2014-2018 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Martin Liska
      4  1.1  mrg 
      5  1.1  mrg This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      8  1.1  mrg the terms of the GNU General Public License as published by the Free
      9  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     10  1.1  mrg version.
     11  1.1  mrg 
     12  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  1.1  mrg for more details.
     16  1.1  mrg 
     17  1.1  mrg You should have received a copy of the GNU General Public License
     18  1.1  mrg along with GCC; see the file COPYING3.  If not see
     19  1.1  mrg <http://www.gnu.org/licenses/>.  */
     20  1.1  mrg 
     21  1.1  mrg #ifndef GCC_SYMBOL_SUMMARY_H
     22  1.1  mrg #define GCC_SYMBOL_SUMMARY_H
     23  1.1  mrg 
     24  1.1  mrg /* We want to pass just pointer types as argument for function_summary
     25  1.1  mrg    template class.  */
     26  1.1  mrg 
     27  1.1  mrg template <class T>
     28  1.1  mrg class function_summary
     29  1.1  mrg {
     30  1.1  mrg private:
     31  1.1  mrg   function_summary();
     32  1.1  mrg };
     33  1.1  mrg 
     34  1.1  mrg template <class T>
     35  1.1  mrg class GTY((user)) function_summary <T *>
     36  1.1  mrg {
     37  1.1  mrg public:
     38  1.1  mrg   /* Default construction takes SYMTAB as an argument.  */
     39  1.1  mrg   function_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
     40  1.3  mrg     m_insertion_enabled (true), m_released (false), m_map (13, ggc),
     41  1.3  mrg     m_symtab (symtab)
     42  1.1  mrg   {
     43  1.1  mrg     m_symtab_insertion_hook =
     44  1.1  mrg       symtab->add_cgraph_insertion_hook
     45  1.1  mrg       (function_summary::symtab_insertion, this);
     46  1.1  mrg 
     47  1.1  mrg     m_symtab_removal_hook =
     48  1.1  mrg       symtab->add_cgraph_removal_hook
     49  1.1  mrg       (function_summary::symtab_removal, this);
     50  1.1  mrg     m_symtab_duplication_hook =
     51  1.1  mrg       symtab->add_cgraph_duplication_hook
     52  1.1  mrg       (function_summary::symtab_duplication, this);
     53  1.1  mrg   }
     54  1.1  mrg 
     55  1.1  mrg   /* Destructor.  */
     56  1.1  mrg   virtual ~function_summary ()
     57  1.1  mrg   {
     58  1.1  mrg     release ();
     59  1.1  mrg   }
     60  1.1  mrg 
     61  1.1  mrg   /* Destruction method that can be called for GGT purpose.  */
     62  1.1  mrg   void release ()
     63  1.1  mrg   {
     64  1.3  mrg     if (m_released)
     65  1.3  mrg       return;
     66  1.1  mrg 
     67  1.3  mrg     m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
     68  1.3  mrg     m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
     69  1.3  mrg     m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
     70  1.1  mrg 
     71  1.1  mrg     /* Release all summaries.  */
     72  1.3  mrg     typedef typename hash_map <map_hash, T *>::iterator map_iterator;
     73  1.1  mrg     for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
     74  1.1  mrg       release ((*it).second);
     75  1.3  mrg 
     76  1.3  mrg     m_released = true;
     77  1.1  mrg   }
     78  1.1  mrg 
     79  1.1  mrg   /* Traverses all summarys with a function F called with
     80  1.1  mrg      ARG as argument.  */
     81  1.1  mrg   template<typename Arg, bool (*f)(const T &, Arg)>
     82  1.1  mrg   void traverse (Arg a) const
     83  1.1  mrg   {
     84  1.1  mrg     m_map.traverse <f> (a);
     85  1.1  mrg   }
     86  1.1  mrg 
     87  1.1  mrg   /* Basic implementation of insert operation.  */
     88  1.1  mrg   virtual void insert (cgraph_node *, T *) {}
     89  1.1  mrg 
     90  1.1  mrg   /* Basic implementation of removal operation.  */
     91  1.1  mrg   virtual void remove (cgraph_node *, T *) {}
     92  1.1  mrg 
     93  1.1  mrg   /* Basic implementation of duplication operation.  */
     94  1.1  mrg   virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
     95  1.1  mrg 
     96  1.1  mrg   /* Allocates new data that are stored within map.  */
     97  1.1  mrg   T* allocate_new ()
     98  1.1  mrg   {
     99  1.3  mrg     /* Call gcc_internal_because we do not want to call finalizer for
    100  1.3  mrg        a type T.  We call dtor explicitly.  */
    101  1.3  mrg     return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
    102  1.1  mrg   }
    103  1.1  mrg 
    104  1.1  mrg   /* Release an item that is stored within map.  */
    105  1.1  mrg   void release (T *item)
    106  1.1  mrg   {
    107  1.1  mrg     if (m_ggc)
    108  1.1  mrg       {
    109  1.1  mrg 	item->~T ();
    110  1.1  mrg 	ggc_free (item);
    111  1.1  mrg       }
    112  1.1  mrg     else
    113  1.1  mrg       delete item;
    114  1.1  mrg   }
    115  1.1  mrg 
    116  1.1  mrg   /* Getter for summary callgraph node pointer.  */
    117  1.1  mrg   T* get (cgraph_node *node)
    118  1.1  mrg   {
    119  1.3  mrg     gcc_checking_assert (node->summary_uid);
    120  1.1  mrg     return get (node->summary_uid);
    121  1.1  mrg   }
    122  1.1  mrg 
    123  1.1  mrg   /* Return number of elements handled by data structure.  */
    124  1.1  mrg   size_t elements ()
    125  1.1  mrg   {
    126  1.1  mrg     return m_map.elements ();
    127  1.1  mrg   }
    128  1.1  mrg 
    129  1.4  mrg   /* Return true if a summary for the given NODE already exists.  */
    130  1.4  mrg   bool exists (cgraph_node *node)
    131  1.4  mrg   {
    132  1.4  mrg     return m_map.get (node->summary_uid) != NULL;
    133  1.4  mrg   }
    134  1.4  mrg 
    135  1.1  mrg   /* Enable insertion hook invocation.  */
    136  1.1  mrg   void enable_insertion_hook ()
    137  1.1  mrg   {
    138  1.1  mrg     m_insertion_enabled = true;
    139  1.1  mrg   }
    140  1.1  mrg 
    141  1.1  mrg   /* Enable insertion hook invocation.  */
    142  1.1  mrg   void disable_insertion_hook ()
    143  1.1  mrg   {
    144  1.1  mrg     m_insertion_enabled = false;
    145  1.1  mrg   }
    146  1.1  mrg 
    147  1.1  mrg   /* Symbol insertion hook that is registered to symbol table.  */
    148  1.1  mrg   static void symtab_insertion (cgraph_node *node, void *data)
    149  1.1  mrg   {
    150  1.3  mrg     gcc_checking_assert (node->summary_uid);
    151  1.1  mrg     function_summary *summary = (function_summary <T *> *) (data);
    152  1.1  mrg 
    153  1.1  mrg     if (summary->m_insertion_enabled)
    154  1.1  mrg       summary->insert (node, summary->get (node));
    155  1.1  mrg   }
    156  1.1  mrg 
    157  1.1  mrg   /* Symbol removal hook that is registered to symbol table.  */
    158  1.1  mrg   static void symtab_removal (cgraph_node *node, void *data)
    159  1.1  mrg   {
    160  1.1  mrg     gcc_checking_assert (node->summary_uid);
    161  1.1  mrg     function_summary *summary = (function_summary <T *> *) (data);
    162  1.1  mrg 
    163  1.1  mrg     int summary_uid = node->summary_uid;
    164  1.1  mrg     T **v = summary->m_map.get (summary_uid);
    165  1.1  mrg 
    166  1.1  mrg     if (v)
    167  1.1  mrg       {
    168  1.1  mrg 	summary->remove (node, *v);
    169  1.4  mrg 	summary->release (*v);
    170  1.1  mrg 	summary->m_map.remove (summary_uid);
    171  1.1  mrg       }
    172  1.1  mrg   }
    173  1.1  mrg 
    174  1.1  mrg   /* Symbol duplication hook that is registered to symbol table.  */
    175  1.1  mrg   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
    176  1.1  mrg 				  void *data)
    177  1.1  mrg   {
    178  1.1  mrg     function_summary *summary = (function_summary <T *> *) (data);
    179  1.1  mrg     T **v = summary->m_map.get (node->summary_uid);
    180  1.1  mrg 
    181  1.1  mrg     gcc_checking_assert (node2->summary_uid > 0);
    182  1.1  mrg 
    183  1.1  mrg     if (v)
    184  1.1  mrg       {
    185  1.1  mrg 	/* This load is necessary, because we insert a new value!  */
    186  1.1  mrg 	T *data = *v;
    187  1.1  mrg 	T *duplicate = summary->allocate_new ();
    188  1.1  mrg 	summary->m_map.put (node2->summary_uid, duplicate);
    189  1.1  mrg 	summary->duplicate (node, node2, data, duplicate);
    190  1.1  mrg       }
    191  1.1  mrg   }
    192  1.1  mrg 
    193  1.1  mrg protected:
    194  1.1  mrg   /* Indication if we use ggc summary.  */
    195  1.1  mrg   bool m_ggc;
    196  1.1  mrg 
    197  1.1  mrg private:
    198  1.3  mrg   typedef int_hash <int, 0, -1> map_hash;
    199  1.1  mrg 
    200  1.1  mrg   /* Getter for summary callgraph ID.  */
    201  1.1  mrg   T* get (int uid)
    202  1.1  mrg   {
    203  1.1  mrg     bool existed;
    204  1.1  mrg     T **v = &m_map.get_or_insert (uid, &existed);
    205  1.1  mrg     if (!existed)
    206  1.1  mrg       *v = allocate_new ();
    207  1.1  mrg 
    208  1.1  mrg     return *v;
    209  1.1  mrg   }
    210  1.1  mrg 
    211  1.3  mrg   /* Indicates if insertion hook is enabled.  */
    212  1.3  mrg   bool m_insertion_enabled;
    213  1.3  mrg   /* Indicates if the summary is released.  */
    214  1.3  mrg   bool m_released;
    215  1.1  mrg   /* Main summary store, where summary ID is used as key.  */
    216  1.3  mrg   hash_map <map_hash, T *> m_map;
    217  1.1  mrg   /* Internal summary insertion hook pointer.  */
    218  1.1  mrg   cgraph_node_hook_list *m_symtab_insertion_hook;
    219  1.1  mrg   /* Internal summary removal hook pointer.  */
    220  1.1  mrg   cgraph_node_hook_list *m_symtab_removal_hook;
    221  1.1  mrg   /* Internal summary duplication hook pointer.  */
    222  1.1  mrg   cgraph_2node_hook_list *m_symtab_duplication_hook;
    223  1.1  mrg   /* Symbol table the summary is registered to.  */
    224  1.1  mrg   symbol_table *m_symtab;
    225  1.1  mrg 
    226  1.1  mrg   template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
    227  1.1  mrg   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
    228  1.1  mrg   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
    229  1.1  mrg       gt_pointer_operator, void *);
    230  1.1  mrg };
    231  1.1  mrg 
    232  1.1  mrg template <typename T>
    233  1.1  mrg void
    234  1.1  mrg gt_ggc_mx(function_summary<T *>* const &summary)
    235  1.1  mrg {
    236  1.1  mrg   gcc_checking_assert (summary->m_ggc);
    237  1.1  mrg   gt_ggc_mx (&summary->m_map);
    238  1.1  mrg }
    239  1.1  mrg 
    240  1.1  mrg template <typename T>
    241  1.1  mrg void
    242  1.1  mrg gt_pch_nx(function_summary<T *>* const &summary)
    243  1.1  mrg {
    244  1.1  mrg   gcc_checking_assert (summary->m_ggc);
    245  1.1  mrg   gt_pch_nx (&summary->m_map);
    246  1.1  mrg }
    247  1.1  mrg 
    248  1.1  mrg template <typename T>
    249  1.1  mrg void
    250  1.1  mrg gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
    251  1.1  mrg 	  void *cookie)
    252  1.1  mrg {
    253  1.1  mrg   gcc_checking_assert (summary->m_ggc);
    254  1.1  mrg   gt_pch_nx (&summary->m_map, op, cookie);
    255  1.1  mrg }
    256  1.1  mrg 
    257  1.4  mrg /* An impossible class templated by non-pointers so, which makes sure that only
    258  1.4  mrg    summaries gathering pointers can be created.  */
    259  1.4  mrg 
    260  1.4  mrg template <class T>
    261  1.4  mrg class call_summary
    262  1.4  mrg {
    263  1.4  mrg private:
    264  1.4  mrg   call_summary();
    265  1.4  mrg };
    266  1.4  mrg 
    267  1.4  mrg /* Class to store auxiliary information about call graph edges.  */
    268  1.4  mrg 
    269  1.4  mrg template <class T>
    270  1.4  mrg class GTY((user)) call_summary <T *>
    271  1.4  mrg {
    272  1.4  mrg public:
    273  1.4  mrg   /* Default construction takes SYMTAB as an argument.  */
    274  1.4  mrg   call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
    275  1.4  mrg     m_map (13, ggc), m_released (false), m_symtab (symtab)
    276  1.4  mrg   {
    277  1.4  mrg     m_symtab_removal_hook =
    278  1.4  mrg       symtab->add_edge_removal_hook
    279  1.4  mrg       (call_summary::symtab_removal, this);
    280  1.4  mrg     m_symtab_duplication_hook =
    281  1.4  mrg       symtab->add_edge_duplication_hook
    282  1.4  mrg       (call_summary::symtab_duplication, this);
    283  1.4  mrg   }
    284  1.4  mrg 
    285  1.4  mrg   /* Destructor.  */
    286  1.4  mrg   virtual ~call_summary ()
    287  1.4  mrg   {
    288  1.4  mrg     release ();
    289  1.4  mrg   }
    290  1.4  mrg 
    291  1.4  mrg   /* Destruction method that can be called for GGT purpose.  */
    292  1.4  mrg   void release ()
    293  1.4  mrg   {
    294  1.4  mrg     if (m_released)
    295  1.4  mrg       return;
    296  1.4  mrg 
    297  1.4  mrg     m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
    298  1.4  mrg     m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
    299  1.4  mrg 
    300  1.4  mrg     /* Release all summaries.  */
    301  1.4  mrg     typedef typename hash_map <map_hash, T *>::iterator map_iterator;
    302  1.4  mrg     for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
    303  1.4  mrg       release ((*it).second);
    304  1.4  mrg 
    305  1.4  mrg     m_released = true;
    306  1.4  mrg   }
    307  1.4  mrg 
    308  1.4  mrg   /* Traverses all summarys with a function F called with
    309  1.4  mrg      ARG as argument.  */
    310  1.4  mrg   template<typename Arg, bool (*f)(const T &, Arg)>
    311  1.4  mrg   void traverse (Arg a) const
    312  1.4  mrg   {
    313  1.4  mrg     m_map.traverse <f> (a);
    314  1.4  mrg   }
    315  1.4  mrg 
    316  1.4  mrg   /* Basic implementation of removal operation.  */
    317  1.4  mrg   virtual void remove (cgraph_edge *, T *) {}
    318  1.4  mrg 
    319  1.4  mrg   /* Basic implementation of duplication operation.  */
    320  1.4  mrg   virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
    321  1.4  mrg 
    322  1.4  mrg   /* Allocates new data that are stored within map.  */
    323  1.4  mrg   T* allocate_new ()
    324  1.4  mrg   {
    325  1.4  mrg     /* Call gcc_internal_because we do not want to call finalizer for
    326  1.4  mrg        a type T.  We call dtor explicitly.  */
    327  1.4  mrg     return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
    328  1.4  mrg   }
    329  1.4  mrg 
    330  1.4  mrg   /* Release an item that is stored within map.  */
    331  1.4  mrg   void release (T *item)
    332  1.4  mrg   {
    333  1.4  mrg     if (m_ggc)
    334  1.4  mrg       {
    335  1.4  mrg 	item->~T ();
    336  1.4  mrg 	ggc_free (item);
    337  1.4  mrg       }
    338  1.4  mrg     else
    339  1.4  mrg       delete item;
    340  1.4  mrg   }
    341  1.4  mrg 
    342  1.4  mrg   /* Getter for summary callgraph edge pointer.  */
    343  1.4  mrg   T* get (cgraph_edge *edge)
    344  1.4  mrg   {
    345  1.4  mrg     return get (hashable_uid (edge));
    346  1.4  mrg   }
    347  1.4  mrg 
    348  1.4  mrg   /* Return number of elements handled by data structure.  */
    349  1.4  mrg   size_t elements ()
    350  1.4  mrg   {
    351  1.4  mrg     return m_map.elements ();
    352  1.4  mrg   }
    353  1.4  mrg 
    354  1.4  mrg   /* Return true if a summary for the given EDGE already exists.  */
    355  1.4  mrg   bool exists (cgraph_edge *edge)
    356  1.4  mrg   {
    357  1.4  mrg     return m_map.get (hashable_uid (edge)) != NULL;
    358  1.4  mrg   }
    359  1.4  mrg 
    360  1.4  mrg   /* Symbol removal hook that is registered to symbol table.  */
    361  1.4  mrg   static void symtab_removal (cgraph_edge *edge, void *data)
    362  1.4  mrg   {
    363  1.4  mrg     call_summary *summary = (call_summary <T *> *) (data);
    364  1.4  mrg 
    365  1.4  mrg     int h_uid = summary->hashable_uid (edge);
    366  1.4  mrg     T **v = summary->m_map.get (h_uid);
    367  1.4  mrg 
    368  1.4  mrg     if (v)
    369  1.4  mrg       {
    370  1.4  mrg 	summary->remove (edge, *v);
    371  1.4  mrg 	summary->release (*v);
    372  1.4  mrg 	summary->m_map.remove (h_uid);
    373  1.4  mrg       }
    374  1.4  mrg   }
    375  1.4  mrg 
    376  1.4  mrg   /* Symbol duplication hook that is registered to symbol table.  */
    377  1.4  mrg   static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
    378  1.4  mrg 				  void *data)
    379  1.4  mrg   {
    380  1.4  mrg     call_summary *summary = (call_summary <T *> *) (data);
    381  1.4  mrg     T **v = summary->m_map.get (summary->hashable_uid (edge1));
    382  1.4  mrg 
    383  1.4  mrg     if (v)
    384  1.4  mrg       {
    385  1.4  mrg 	/* This load is necessary, because we insert a new value!  */
    386  1.4  mrg 	T *data = *v;
    387  1.4  mrg 	T *duplicate = summary->allocate_new ();
    388  1.4  mrg 	summary->m_map.put (summary->hashable_uid (edge2), duplicate);
    389  1.4  mrg 	summary->duplicate (edge1, edge2, data, duplicate);
    390  1.4  mrg       }
    391  1.4  mrg   }
    392  1.4  mrg 
    393  1.4  mrg protected:
    394  1.4  mrg   /* Indication if we use ggc summary.  */
    395  1.4  mrg   bool m_ggc;
    396  1.4  mrg 
    397  1.4  mrg private:
    398  1.4  mrg   typedef int_hash <int, 0, -1> map_hash;
    399  1.4  mrg 
    400  1.4  mrg   /* Getter for summary callgraph ID.  */
    401  1.4  mrg   T* get (int uid)
    402  1.4  mrg   {
    403  1.4  mrg     bool existed;
    404  1.4  mrg     T **v = &m_map.get_or_insert (uid, &existed);
    405  1.4  mrg     if (!existed)
    406  1.4  mrg       *v = allocate_new ();
    407  1.4  mrg 
    408  1.4  mrg     return *v;
    409  1.4  mrg   }
    410  1.4  mrg 
    411  1.4  mrg   /* Get a hashable uid of EDGE.  */
    412  1.4  mrg   int hashable_uid (cgraph_edge *edge)
    413  1.4  mrg   {
    414  1.4  mrg     /* Edge uids start at zero which our hash_map does not like.  */
    415  1.4  mrg     return edge->uid + 1;
    416  1.4  mrg   }
    417  1.4  mrg 
    418  1.4  mrg   /* Main summary store, where summary ID is used as key.  */
    419  1.4  mrg   hash_map <map_hash, T *> m_map;
    420  1.4  mrg   /* Internal summary removal hook pointer.  */
    421  1.4  mrg   cgraph_edge_hook_list *m_symtab_removal_hook;
    422  1.4  mrg   /* Internal summary duplication hook pointer.  */
    423  1.4  mrg   cgraph_2edge_hook_list *m_symtab_duplication_hook;
    424  1.4  mrg   /* Indicates if the summary is released.  */
    425  1.4  mrg   bool m_released;
    426  1.4  mrg   /* Symbol table the summary is registered to.  */
    427  1.4  mrg   symbol_table *m_symtab;
    428  1.4  mrg 
    429  1.4  mrg   template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
    430  1.4  mrg   template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
    431  1.4  mrg   template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
    432  1.4  mrg       gt_pointer_operator, void *);
    433  1.4  mrg };
    434  1.4  mrg 
    435  1.4  mrg template <typename T>
    436  1.4  mrg void
    437  1.4  mrg gt_ggc_mx(call_summary<T *>* const &summary)
    438  1.4  mrg {
    439  1.4  mrg   gcc_checking_assert (summary->m_ggc);
    440  1.4  mrg   gt_ggc_mx (&summary->m_map);
    441  1.4  mrg }
    442  1.4  mrg 
    443  1.4  mrg template <typename T>
    444  1.4  mrg void
    445  1.4  mrg gt_pch_nx(call_summary<T *>* const &summary)
    446  1.4  mrg {
    447  1.4  mrg   gcc_checking_assert (summary->m_ggc);
    448  1.4  mrg   gt_pch_nx (&summary->m_map);
    449  1.4  mrg }
    450  1.4  mrg 
    451  1.4  mrg template <typename T>
    452  1.4  mrg void
    453  1.4  mrg gt_pch_nx(call_summary<T *>* const& summary, gt_pointer_operator op,
    454  1.4  mrg 	  void *cookie)
    455  1.4  mrg {
    456  1.4  mrg   gcc_checking_assert (summary->m_ggc);
    457  1.4  mrg   gt_pch_nx (&summary->m_map, op, cookie);
    458  1.4  mrg }
    459  1.4  mrg 
    460  1.1  mrg #endif  /* GCC_SYMBOL_SUMMARY_H  */
    461