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 */
|