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