2017-01-22 Matthias Klose <doko@ubuntu.com>
[platform/upstream/gcc.git] / gcc / symbol-summary.h
1 /* Callgraph summary data structure.
2    Copyright (C) 2014-2017 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 /* We want to pass just pointer types as argument for function_summary
25    template class.  */
26
27 template <class T>
28 class function_summary
29 {
30 private:
31   function_summary();
32 };
33
34 template <class T>
35 class GTY((user)) function_summary <T *>
36 {
37 public:
38   /* Default construction takes SYMTAB as an argument.  */
39   function_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
40     m_map (13, ggc), m_insertion_enabled (true), m_symtab (symtab)
41   {
42     m_symtab_insertion_hook =
43       symtab->add_cgraph_insertion_hook
44       (function_summary::symtab_insertion, this);
45
46     m_symtab_removal_hook =
47       symtab->add_cgraph_removal_hook
48       (function_summary::symtab_removal, this);
49     m_symtab_duplication_hook =
50       symtab->add_cgraph_duplication_hook
51       (function_summary::symtab_duplication, this);
52   }
53
54   /* Destructor.  */
55   virtual ~function_summary ()
56   {
57     release ();
58   }
59
60   /* Destruction method that can be called for GGT purpose.  */
61   void release ()
62   {
63     if (m_symtab_insertion_hook)
64       m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
65
66     if (m_symtab_removal_hook)
67       m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
68
69     if (m_symtab_duplication_hook)
70       m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
71
72     m_symtab_insertion_hook = NULL;
73     m_symtab_removal_hook = NULL;
74     m_symtab_duplication_hook = NULL;
75
76     /* Release all summaries.  */
77     typedef typename hash_map <map_hash, T *>::iterator map_iterator;
78     for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
79       release ((*it).second);
80   }
81
82   /* Traverses all summarys with a function F called with
83      ARG as argument.  */
84   template<typename Arg, bool (*f)(const T &, Arg)>
85   void traverse (Arg a) const
86   {
87     m_map.traverse <f> (a);
88   }
89
90   /* Basic implementation of insert operation.  */
91   virtual void insert (cgraph_node *, T *) {}
92
93   /* Basic implementation of removal operation.  */
94   virtual void remove (cgraph_node *, T *) {}
95
96   /* Basic implementation of duplication operation.  */
97   virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
98
99   /* Allocates new data that are stored within map.  */
100   T* allocate_new ()
101   {
102     return m_ggc ? new (ggc_alloc <T> ()) T() : new T () ;
103   }
104
105   /* Release an item that is stored within map.  */
106   void release (T *item)
107   {
108     if (m_ggc)
109       {
110         item->~T ();
111         ggc_free (item);
112       }
113     else
114       delete item;
115   }
116
117   /* Getter for summary callgraph node pointer.  */
118   T* get (cgraph_node *node)
119   {
120     gcc_checking_assert (node->summary_uid);
121     return get (node->summary_uid);
122   }
123
124   /* Return number of elements handled by data structure.  */
125   size_t elements ()
126   {
127     return m_map.elements ();
128   }
129
130   /* Enable insertion hook invocation.  */
131   void enable_insertion_hook ()
132   {
133     m_insertion_enabled = true;
134   }
135
136   /* Enable insertion hook invocation.  */
137   void disable_insertion_hook ()
138   {
139     m_insertion_enabled = false;
140   }
141
142   /* Symbol insertion hook that is registered to symbol table.  */
143   static void symtab_insertion (cgraph_node *node, void *data)
144   {
145     gcc_checking_assert (node->summary_uid);
146     function_summary *summary = (function_summary <T *> *) (data);
147
148     if (summary->m_insertion_enabled)
149       summary->insert (node, summary->get (node));
150   }
151
152   /* Symbol removal hook that is registered to symbol table.  */
153   static void symtab_removal (cgraph_node *node, void *data)
154   {
155     gcc_checking_assert (node->summary_uid);
156     function_summary *summary = (function_summary <T *> *) (data);
157
158     int summary_uid = node->summary_uid;
159     T **v = summary->m_map.get (summary_uid);
160
161     if (v)
162       {
163         summary->remove (node, *v);
164
165         if (!summary->m_ggc)
166           delete (*v);
167
168         summary->m_map.remove (summary_uid);
169       }
170   }
171
172   /* Symbol duplication hook that is registered to symbol table.  */
173   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
174                                   void *data)
175   {
176     function_summary *summary = (function_summary <T *> *) (data);
177     T **v = summary->m_map.get (node->summary_uid);
178
179     gcc_checking_assert (node2->summary_uid > 0);
180
181     if (v)
182       {
183         /* This load is necessary, because we insert a new value!  */
184         T *data = *v;
185         T *duplicate = summary->allocate_new ();
186         summary->m_map.put (node2->summary_uid, duplicate);
187         summary->duplicate (node, node2, data, duplicate);
188       }
189   }
190
191 protected:
192   /* Indication if we use ggc summary.  */
193   bool m_ggc;
194
195 private:
196   typedef int_hash <int, 0, -1> map_hash;
197
198   /* Getter for summary callgraph ID.  */
199   T* get (int uid)
200   {
201     bool existed;
202     T **v = &m_map.get_or_insert (uid, &existed);
203     if (!existed)
204       *v = allocate_new ();
205
206     return *v;
207   }
208
209   /* Main summary store, where summary ID is used as key.  */
210   hash_map <map_hash, T *> m_map;
211   /* Internal summary insertion hook pointer.  */
212   cgraph_node_hook_list *m_symtab_insertion_hook;
213   /* Internal summary removal hook pointer.  */
214   cgraph_node_hook_list *m_symtab_removal_hook;
215   /* Internal summary duplication hook pointer.  */
216   cgraph_2node_hook_list *m_symtab_duplication_hook;
217   /* Indicates if insertion hook is enabled.  */
218   bool m_insertion_enabled;
219   /* Symbol table the summary is registered to.  */
220   symbol_table *m_symtab;
221
222   template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
223   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
224   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
225       gt_pointer_operator, void *);
226 };
227
228 template <typename T>
229 void
230 gt_ggc_mx(function_summary<T *>* const &summary)
231 {
232   gcc_checking_assert (summary->m_ggc);
233   gt_ggc_mx (&summary->m_map);
234 }
235
236 template <typename T>
237 void
238 gt_pch_nx(function_summary<T *>* const &summary)
239 {
240   gcc_checking_assert (summary->m_ggc);
241   gt_pch_nx (&summary->m_map);
242 }
243
244 template <typename T>
245 void
246 gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
247           void *cookie)
248 {
249   gcc_checking_assert (summary->m_ggc);
250   gt_pch_nx (&summary->m_map, op, cookie);
251 }
252
253 #endif  /* GCC_SYMBOL_SUMMARY_H  */