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