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