Add testcase of PR c++/92542, already fixed.
[official-gcc.git] / gcc / symbol-summary.h
bloba38eb1db7787e62e888be8921af9309d85ba5d4f
1 /* Callgraph summary data structure.
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
3 Contributed by Martin Liska
5 This file is part of GCC.
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.
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.
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/>. */
21 #ifndef GCC_SYMBOL_SUMMARY_H
22 #define GCC_SYMBOL_SUMMARY_H
24 /* Base class for function_summary and fast_function_summary classes. */
26 template <class T>
27 class function_summary_base
29 public:
30 /* Default construction takes SYMTAB as an argument. */
31 function_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
32 m_symtab (symtab),
33 m_insertion_enabled (true),
34 m_allocator ("function summary" PASS_MEM_STAT)
37 /* Basic implementation of insert operation. */
38 virtual void insert (cgraph_node *, T *) {}
40 /* Basic implementation of removal operation. */
41 virtual void remove (cgraph_node *, T *) {}
43 /* Basic implementation of duplication operation. */
44 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
46 /* Enable insertion hook invocation. */
47 void enable_insertion_hook ()
49 m_insertion_enabled = true;
52 /* Enable insertion hook invocation. */
53 void disable_insertion_hook ()
55 m_insertion_enabled = false;
58 protected:
59 /* Allocates new data that are stored within map. */
60 T* allocate_new ()
62 /* Call gcc_internal_because we do not want to call finalizer for
63 a type T. We call dtor explicitly. */
64 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
65 : m_allocator.allocate () ;
68 /* Release an item that is stored within map. */
69 void release (T *item)
71 if (is_ggc ())
72 ggc_delete (item);
73 else
74 m_allocator.remove (item);
77 /* Unregister all call-graph hooks. */
78 void unregister_hooks ();
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;
89 /* Indicates if insertion hook is enabled. */
90 bool m_insertion_enabled;
92 private:
93 /* Return true when the summary uses GGC memory for allocation. */
94 virtual bool is_ggc () = 0;
96 /* Object allocator for heap allocation. */
97 object_allocator<T> m_allocator;
100 template <typename T>
101 void
102 function_summary_base<T>::unregister_hooks ()
104 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
105 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
106 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
109 /* We want to pass just pointer types as argument for function_summary
110 template class. */
112 template <class T>
113 class function_summary
115 private:
116 function_summary();
119 /* Function summary is a helper class that is used to associate a data structure
120 related to a callgraph node. Typical usage can be seen in IPA passes which
121 create a temporary pass-related structures. The summary class registers
122 hooks that are triggered when a new node is inserted, duplicated and deleted.
123 A user of a summary class can ovewrite virtual methods than are triggered by
124 the summary if such hook is triggered. Apart from a callgraph node, the user
125 is given a data structure tied to the node.
127 The function summary class can work both with a heap-allocated memory and
128 a memory gained by garbage collected memory. */
130 template <class T>
131 class GTY((user)) function_summary <T *>: public function_summary_base<T>
133 public:
134 /* Default construction takes SYMTAB as an argument. */
135 function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
137 /* Destructor. */
138 virtual ~function_summary ();
140 /* Traverses all summarys with a function F called with
141 ARG as argument. */
142 template<typename Arg, bool (*f)(const T &, Arg)>
143 void traverse (Arg a) const
145 m_map.traverse <f> (a);
148 /* Getter for summary callgraph node pointer. If a summary for a node
149 does not exist it will be created. */
150 T* get_create (cgraph_node *node)
152 bool existed;
153 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
154 if (!existed)
155 *v = this->allocate_new ();
157 return *v;
160 /* Getter for summary callgraph node pointer. */
161 T* get (cgraph_node *node) ATTRIBUTE_PURE
163 T **v = m_map.get (node->get_uid ());
164 return v == NULL ? NULL : *v;
167 /* Remove node from summary. */
168 using function_summary_base<T>::remove;
169 void remove (cgraph_node *node)
171 int uid = node->get_uid ();
172 T **v = m_map.get (uid);
173 if (v)
175 m_map.remove (uid);
176 this->release (*v);
180 /* Return true if a summary for the given NODE already exists. */
181 bool exists (cgraph_node *node)
183 return m_map.get (node->get_uid ()) != NULL;
186 /* Symbol insertion hook that is registered to symbol table. */
187 static void symtab_insertion (cgraph_node *node, void *data);
189 /* Symbol removal hook that is registered to symbol table. */
190 static void symtab_removal (cgraph_node *node, void *data);
192 /* Symbol duplication hook that is registered to symbol table. */
193 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
194 void *data);
196 protected:
197 /* Indication if we use ggc summary. */
198 bool m_ggc;
200 private:
201 /* Indication if we use ggc summary. */
202 virtual bool is_ggc ()
204 return m_ggc;
207 typedef int_hash <int, 0, -1> map_hash;
209 /* Main summary store, where summary ID is used as key. */
210 hash_map <map_hash, T *> m_map;
212 template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
213 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
214 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
215 gt_pointer_operator, void *);
218 template <typename T>
219 function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
220 MEM_STAT_DECL):
221 function_summary_base<T> (symtab PASS_MEM_STAT), m_ggc (ggc),
222 m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT)
224 this->m_symtab_insertion_hook
225 = this->m_symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
226 this);
227 this->m_symtab_removal_hook
228 = this->m_symtab->add_cgraph_removal_hook (function_summary::symtab_removal,
229 this);
230 this->m_symtab_duplication_hook
231 = this->m_symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication,
232 this);
235 template <typename T>
236 function_summary<T *>::~function_summary ()
238 this->unregister_hooks ();
240 /* Release all summaries. */
241 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
242 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
243 this->release ((*it).second);
246 template <typename T>
247 void
248 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
250 gcc_checking_assert (node->get_uid ());
251 function_summary *summary = (function_summary <T *> *) (data);
253 if (summary->m_insertion_enabled)
254 summary->insert (node, summary->get_create (node));
257 template <typename T>
258 void
259 function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
261 gcc_checking_assert (node->get_uid ());
262 function_summary *summary = (function_summary <T *> *) (data);
263 summary->remove (node);
266 template <typename T>
267 void
268 function_summary<T *>::symtab_duplication (cgraph_node *node,
269 cgraph_node *node2, void *data)
271 function_summary *summary = (function_summary <T *> *) (data);
272 T *v = summary->get (node);
274 if (v)
275 summary->duplicate (node, node2, v, summary->get_create (node2));
278 template <typename T>
279 void
280 gt_ggc_mx(function_summary<T *>* const &summary)
282 gcc_checking_assert (summary->m_ggc);
283 gt_ggc_mx (&summary->m_map);
286 template <typename T>
287 void
288 gt_pch_nx (function_summary<T *> *const &)
290 gcc_unreachable ();
293 template <typename T>
294 void
295 gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
297 gcc_unreachable ();
300 /* Help template from std c++11. */
302 template<typename T, typename U>
303 struct is_same
305 static const bool value = false;
308 template<typename T>
309 struct is_same<T,T> //specialization
311 static const bool value = true;
314 /* We want to pass just pointer types as argument for fast_function_summary
315 template class. */
317 template <class T, class V>
318 class fast_function_summary
320 private:
321 fast_function_summary ();
324 /* Function vector summary is a fast implementation of function_summary that
325 utilizes vector as primary storage of summaries. */
327 template <class T, class V>
328 class GTY((user)) fast_function_summary <T *, V>
329 : public function_summary_base<T>
331 public:
332 /* Default construction takes SYMTAB as an argument. */
333 fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
335 /* Destructor. */
336 virtual ~fast_function_summary ();
338 /* Traverses all summarys with a function F called with
339 ARG as argument. */
340 template<typename Arg, bool (*f)(const T &, Arg)>
341 void traverse (Arg a) const
343 for (unsigned i = 0; i < m_vector->length (); i++)
344 if ((*m_vector[i]) != NULL)
345 f ((*m_vector)[i], a);
348 /* Getter for summary callgraph node pointer. If a summary for a node
349 does not exist it will be created. */
350 T* get_create (cgraph_node *node)
352 int id = node->get_summary_id ();
353 if (id == -1)
354 id = this->m_symtab->assign_summary_id (node);
356 if ((unsigned int)id >= m_vector->length ())
357 vec_safe_grow_cleared (m_vector,
358 this->m_symtab->cgraph_max_summary_id);
360 if ((*m_vector)[id] == NULL)
361 (*m_vector)[id] = this->allocate_new ();
363 return (*m_vector)[id];
366 /* Getter for summary callgraph node pointer. */
367 T* get (cgraph_node *node) ATTRIBUTE_PURE
369 return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
372 using function_summary_base<T>::remove;
373 void remove (cgraph_node *node)
375 if (exists (node))
377 int id = node->get_summary_id ();
378 this->release ((*m_vector)[id]);
379 (*m_vector)[id] = NULL;
383 /* Return true if a summary for the given NODE already exists. */
384 bool exists (cgraph_node *node)
386 int id = node->get_summary_id ();
387 return (id != -1
388 && (unsigned int)id < m_vector->length ()
389 && (*m_vector)[id] != NULL);
392 /* Symbol insertion hook that is registered to symbol table. */
393 static void symtab_insertion (cgraph_node *node, void *data);
395 /* Symbol removal hook that is registered to symbol table. */
396 static void symtab_removal (cgraph_node *node, void *data);
398 /* Symbol duplication hook that is registered to symbol table. */
399 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
400 void *data);
402 private:
403 virtual bool is_ggc ();
405 /* Summary is stored in the vector. */
406 vec <T *, V> *m_vector;
408 template <typename U> friend void gt_ggc_mx (fast_function_summary <U *, va_gc> * const &);
409 template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &);
410 template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &,
411 gt_pointer_operator, void *);
414 template <typename T, typename V>
415 fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab MEM_STAT_DECL):
416 function_summary_base<T> (symtab PASS_MEM_STAT), m_vector (NULL)
418 vec_alloc (m_vector, 13 PASS_MEM_STAT);
419 this->m_symtab_insertion_hook
420 = this->m_symtab->add_cgraph_insertion_hook (fast_function_summary::symtab_insertion,
421 this);
422 this->m_symtab_removal_hook
423 = this->m_symtab->add_cgraph_removal_hook (fast_function_summary::symtab_removal,
424 this);
425 this->m_symtab_duplication_hook
426 = this->m_symtab->add_cgraph_duplication_hook (fast_function_summary::symtab_duplication,
427 this);
430 template <typename T, typename V>
431 fast_function_summary<T *, V>::~fast_function_summary ()
433 this->unregister_hooks ();
435 /* Release all summaries. */
436 for (unsigned i = 0; i < m_vector->length (); i++)
437 if ((*m_vector)[i] != NULL)
438 this->release ((*m_vector)[i]);
439 vec_free (m_vector);
442 template <typename T, typename V>
443 void
444 fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
446 gcc_checking_assert (node->get_uid ());
447 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
449 if (summary->m_insertion_enabled)
450 summary->insert (node, summary->get_create (node));
453 template <typename T, typename V>
454 void
455 fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
457 gcc_checking_assert (node->get_uid ());
458 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
460 if (summary->exists (node))
461 summary->remove (node);
464 template <typename T, typename V>
465 void
466 fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
467 cgraph_node *node2,
468 void *data)
470 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
471 T *v = summary->get (node);
473 if (v)
475 T *duplicate = summary->get_create (node2);
476 summary->duplicate (node, node2, v, duplicate);
480 template <typename T, typename V>
481 inline bool
482 fast_function_summary<T *, V>::is_ggc ()
484 return is_same<V, va_gc>::value;
487 template <typename T>
488 void
489 gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
493 template <typename T>
494 void
495 gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
499 template <typename T>
500 void
501 gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
502 void *)
506 template <typename T>
507 void
508 gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
510 ggc_test_and_set_mark (summary->m_vector);
511 gt_ggc_mx (summary->m_vector);
514 template <typename T>
515 void
516 gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
518 gcc_unreachable ();
521 template <typename T>
522 void
523 gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
524 void *)
526 gcc_unreachable ();
529 /* Base class for call_summary and fast_call_summary classes. */
531 template <class T>
532 class call_summary_base
534 public:
535 /* Default construction takes SYMTAB as an argument. */
536 call_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
537 m_symtab (symtab),
538 m_initialize_when_cloning (false),
539 m_allocator ("call summary" PASS_MEM_STAT)
542 /* Basic implementation of removal operation. */
543 virtual void remove (cgraph_edge *, T *) {}
545 /* Basic implementation of duplication operation. */
546 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
548 protected:
549 /* Allocates new data that are stored within map. */
550 T* allocate_new ()
552 /* Call gcc_internal_because we do not want to call finalizer for
553 a type T. We call dtor explicitly. */
554 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
555 : m_allocator.allocate ();
558 /* Release an item that is stored within map. */
559 void release (T *item)
561 if (is_ggc ())
562 ggc_delete (item);
563 else
564 m_allocator.remove (item);
567 /* Unregister all call-graph hooks. */
568 void unregister_hooks ();
570 /* Symbol table the summary is registered to. */
571 symbol_table *m_symtab;
573 /* Internal summary removal hook pointer. */
574 cgraph_edge_hook_list *m_symtab_removal_hook;
575 /* Internal summary duplication hook pointer. */
576 cgraph_2edge_hook_list *m_symtab_duplication_hook;
577 /* Initialize summary for an edge that is cloned. */
578 bool m_initialize_when_cloning;
580 private:
581 /* Return true when the summary uses GGC memory for allocation. */
582 virtual bool is_ggc () = 0;
584 /* Object allocator for heap allocation. */
585 object_allocator<T> m_allocator;
588 template <typename T>
589 void
590 call_summary_base<T>::unregister_hooks ()
592 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
593 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
596 /* An impossible class templated by non-pointers so, which makes sure that only
597 summaries gathering pointers can be created. */
599 template <class T>
600 class call_summary
602 private:
603 call_summary ();
606 /* Class to store auxiliary information about call graph edges. */
608 template <class T>
609 class GTY((user)) call_summary <T *>: public call_summary_base<T>
611 public:
612 /* Default construction takes SYMTAB as an argument. */
613 call_summary (symbol_table *symtab, bool ggc = false
614 CXX_MEM_STAT_INFO)
615 : call_summary_base<T> (symtab PASS_MEM_STAT), m_ggc (ggc),
616 m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT)
618 this->m_symtab_removal_hook
619 = this->m_symtab->add_edge_removal_hook (call_summary::symtab_removal,
620 this);
621 this->m_symtab_duplication_hook
622 = this->m_symtab->add_edge_duplication_hook (call_summary::symtab_duplication,
623 this);
626 /* Destructor. */
627 virtual ~call_summary ();
629 /* Traverses all summarys with an edge E called with
630 ARG as argument. */
631 template<typename Arg, bool (*f)(const T &, Arg)>
632 void traverse (Arg a) const
634 m_map.traverse <f> (a);
637 /* Getter for summary callgraph edge pointer.
638 If a summary for an edge does not exist, it will be created. */
639 T* get_create (cgraph_edge *edge)
641 bool existed;
642 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
643 if (!existed)
644 *v = this->allocate_new ();
646 return *v;
649 /* Getter for summary callgraph edge pointer. */
650 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
652 T **v = m_map.get (edge->get_uid ());
653 return v == NULL ? NULL : *v;
656 /* Remove edge from summary. */
657 using call_summary_base<T>::remove;
658 void remove (cgraph_edge *edge)
660 int uid = edge->get_uid ();
661 T **v = m_map.get (uid);
662 if (v)
664 m_map.remove (uid);
665 this->release (*v);
669 /* Return true if a summary for the given EDGE already exists. */
670 bool exists (cgraph_edge *edge)
672 return m_map.get (edge->get_uid ()) != NULL;
675 /* Symbol removal hook that is registered to symbol table. */
676 static void symtab_removal (cgraph_edge *edge, void *data);
678 /* Symbol duplication hook that is registered to symbol table. */
679 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
680 void *data);
682 protected:
683 /* Indication if we use ggc summary. */
684 bool m_ggc;
686 private:
687 /* Indication if we use ggc summary. */
688 virtual bool is_ggc ()
690 return m_ggc;
693 typedef int_hash <int, 0, -1> map_hash;
695 /* Main summary store, where summary ID is used as key. */
696 hash_map <map_hash, T *> m_map;
698 template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
699 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
700 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
701 gt_pointer_operator, void *);
704 template <typename T>
705 call_summary<T *>::~call_summary ()
707 this->unregister_hooks ();
709 /* Release all summaries. */
710 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
711 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
712 this->release ((*it).second);
715 template <typename T>
716 void
717 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
719 call_summary *summary = (call_summary <T *> *) (data);
720 summary->remove (edge);
723 template <typename T>
724 void
725 call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
726 cgraph_edge *edge2, void *data)
728 call_summary *summary = (call_summary <T *> *) (data);
729 T *edge1_summary = NULL;
731 if (summary->m_initialize_when_cloning)
732 edge1_summary = summary->get_create (edge1);
733 else
734 edge1_summary = summary->get (edge1);
736 if (edge1_summary)
737 summary->duplicate (edge1, edge2, edge1_summary,
738 summary->get_create (edge2));
741 template <typename T>
742 void
743 gt_ggc_mx(call_summary<T *>* const &summary)
745 gcc_checking_assert (summary->m_ggc);
746 gt_ggc_mx (&summary->m_map);
749 template <typename T>
750 void
751 gt_pch_nx (call_summary<T *> *const &)
753 gcc_unreachable ();
756 template <typename T>
757 void
758 gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
760 gcc_unreachable ();
763 /* We want to pass just pointer types as argument for fast_call_summary
764 template class. */
766 template <class T, class V>
767 class fast_call_summary
769 private:
770 fast_call_summary ();
773 /* Call vector summary is a fast implementation of call_summary that
774 utilizes vector as primary storage of summaries. */
776 template <class T, class V>
777 class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
779 public:
780 /* Default construction takes SYMTAB as an argument. */
781 fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
782 : call_summary_base<T> (symtab PASS_MEM_STAT), m_vector (NULL)
784 vec_alloc (m_vector, 13 PASS_MEM_STAT);
785 this->m_symtab_removal_hook
786 = this->m_symtab->add_edge_removal_hook (fast_call_summary::symtab_removal,
787 this);
788 this->m_symtab_duplication_hook
789 = this->m_symtab->add_edge_duplication_hook (fast_call_summary::symtab_duplication,
790 this);
793 /* Destructor. */
794 virtual ~fast_call_summary ();
796 /* Traverses all summarys with an edge F called with
797 ARG as argument. */
798 template<typename Arg, bool (*f)(const T &, Arg)>
799 void traverse (Arg a) const
801 for (unsigned i = 0; i < m_vector->length (); i++)
802 if ((*m_vector[i]) != NULL)
803 f ((*m_vector)[i], a);
806 /* Getter for summary callgraph edge pointer.
807 If a summary for an edge does not exist, it will be created. */
808 T* get_create (cgraph_edge *edge)
810 int id = edge->get_summary_id ();
811 if (id == -1)
812 id = this->m_symtab->assign_summary_id (edge);
814 if ((unsigned)id >= m_vector->length ())
815 vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
817 if ((*m_vector)[id] == NULL)
818 (*m_vector)[id] = this->allocate_new ();
820 return (*m_vector)[id];
823 /* Getter for summary callgraph edge pointer. */
824 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
826 return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL;
829 /* Remove edge from summary. */
830 using call_summary_base<T>::remove;
831 void remove (cgraph_edge *edge)
833 if (exists (edge))
835 int id = edge->get_summary_id ();
836 this->release ((*m_vector)[id]);
837 (*m_vector)[id] = NULL;
841 /* Return true if a summary for the given EDGE already exists. */
842 bool exists (cgraph_edge *edge)
844 int id = edge->get_summary_id ();
845 return (id != -1
846 && (unsigned)id < m_vector->length ()
847 && (*m_vector)[id] != NULL);
850 /* Symbol removal hook that is registered to symbol table. */
851 static void symtab_removal (cgraph_edge *edge, void *data);
853 /* Symbol duplication hook that is registered to symbol table. */
854 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
855 void *data);
857 private:
858 virtual bool is_ggc ();
860 /* Summary is stored in the vector. */
861 vec <T *, V> *m_vector;
863 template <typename U> friend void gt_ggc_mx (fast_call_summary <U *, va_gc> * const &);
864 template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &);
865 template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &,
866 gt_pointer_operator, void *);
869 template <typename T, typename V>
870 fast_call_summary<T *, V>::~fast_call_summary ()
872 this->unregister_hooks ();
874 /* Release all summaries. */
875 for (unsigned i = 0; i < m_vector->length (); i++)
876 if ((*m_vector)[i] != NULL)
877 this->release ((*m_vector)[i]);
878 vec_free (m_vector);
881 template <typename T, typename V>
882 void
883 fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
885 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
886 summary->remove (edge);
889 template <typename T, typename V>
890 void
891 fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
892 cgraph_edge *edge2, void *data)
894 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
895 T *edge1_summary = NULL;
897 if (summary->m_initialize_when_cloning)
898 edge1_summary = summary->get_create (edge1);
899 else
900 edge1_summary = summary->get (edge1);
902 if (edge1_summary)
904 T *duplicate = summary->get_create (edge2);
905 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
909 template <typename T, typename V>
910 inline bool
911 fast_call_summary<T *, V>::is_ggc ()
913 return is_same<V, va_gc>::value;
916 template <typename T>
917 void
918 gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
922 template <typename T>
923 void
924 gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
928 template <typename T>
929 void
930 gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
931 gt_pointer_operator op ATTRIBUTE_UNUSED,
932 void *cookie ATTRIBUTE_UNUSED)
936 template <typename T>
937 void
938 gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary)
940 ggc_test_and_set_mark (summary->m_vector);
941 gt_ggc_mx (&summary->m_vector);
944 template <typename T>
945 void
946 gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
948 gcc_unreachable ();
951 template <typename T>
952 void
953 gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
955 gcc_unreachable ();
958 #endif /* GCC_SYMBOL_SUMMARY_H */