c++: only cache constexpr calls that are constant exprs
[official-gcc.git] / gcc / symbol-summary.h
blob3ed6162738245f537f603ea3094d089018553d05
1 /* Callgraph summary data structure.
2 Copyright (C) 2014-2023 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,
32 cgraph_node_hook symtab_insertion,
33 cgraph_node_hook symtab_removal,
34 cgraph_2node_hook symtab_duplication
35 CXX_MEM_STAT_INFO):
36 m_symtab (symtab), m_symtab_insertion (symtab_insertion),
37 m_symtab_removal (symtab_removal),
38 m_symtab_duplication (symtab_duplication),
39 m_symtab_insertion_hook (NULL), m_symtab_duplication_hook (NULL),
40 m_allocator ("function summary" PASS_MEM_STAT)
42 enable_insertion_hook ();
43 m_symtab_removal_hook
44 = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this);
45 enable_duplication_hook ();
48 /* Basic implementation of insert operation. */
49 virtual void insert (cgraph_node *, T *)
51 /* In most cases, it makes no sense to create summaries without
52 initializing them. */
53 gcc_unreachable ();
56 /* Basic implementation of removal operation. */
57 virtual void remove (cgraph_node *, T *) {}
59 /* Basic implementation of duplication operation. */
60 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
62 /* It makes no sense to not copy anything during duplication. */
63 gcc_unreachable ();
66 /* Enable insertion hook invocation. */
67 void enable_insertion_hook ()
69 if (m_symtab_insertion_hook == NULL)
70 m_symtab_insertion_hook
71 = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
74 /* Enable insertion hook invocation. */
75 void disable_insertion_hook ()
77 if (m_symtab_insertion_hook != NULL)
79 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
80 m_symtab_insertion_hook = NULL;
84 /* Enable duplication hook invocation. */
85 void enable_duplication_hook ()
87 if (m_symtab_duplication_hook == NULL)
88 m_symtab_duplication_hook
89 = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this);
92 /* Enable duplication hook invocation. */
93 void disable_duplication_hook ()
95 if (m_symtab_duplication_hook != NULL)
97 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
98 m_symtab_duplication_hook = NULL;
102 protected:
103 /* Allocates new data that are stored within map. */
104 T* allocate_new ()
106 /* Call gcc_internal_because we do not want to call finalizer for
107 a type T. We call dtor explicitly. */
108 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
109 : m_allocator.allocate () ;
112 /* Release an item that is stored within map. */
113 void release (T *item)
115 if (is_ggc ())
116 ggc_delete (item);
117 else
118 m_allocator.remove (item);
121 /* Unregister all call-graph hooks. */
122 void unregister_hooks ();
124 /* Symbol table the summary is registered to. */
125 symbol_table *m_symtab;
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;
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;
141 private:
142 /* Return true when the summary uses GGC memory for allocation. */
143 virtual bool is_ggc () = 0;
145 /* Object allocator for heap allocation. */
146 object_allocator<T> m_allocator;
149 template <typename T>
150 void
151 function_summary_base<T>::unregister_hooks ()
153 disable_insertion_hook ();
154 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
155 disable_duplication_hook ();
158 /* We want to pass just pointer types as argument for function_summary
159 template class. */
161 template <class T>
162 class function_summary
164 private:
165 function_summary();
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.
176 The function summary class can work both with a heap-allocated memory and
177 a memory gained by garbage collected memory. */
179 template <class T>
180 class GTY((user)) function_summary <T *>: public function_summary_base<T>
182 public:
183 /* Default construction takes SYMTAB as an argument. */
184 function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
186 /* Destructor. */
187 virtual ~function_summary ();
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
194 m_map.template traverse <f> (a);
197 /* Getter for summary callgraph node pointer. If a summary for a node
198 does not exist it will be created. */
199 T* get_create (cgraph_node *node)
201 bool existed;
202 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
203 if (!existed)
204 *v = this->allocate_new ();
206 return *v;
209 /* Getter for summary callgraph node pointer. */
210 T* get (cgraph_node *node) ATTRIBUTE_PURE
212 T **v = m_map.get (node->get_uid ());
213 return v == NULL ? NULL : *v;
216 /* Remove node from summary. */
217 using function_summary_base<T>::remove;
218 void remove (cgraph_node *node)
220 int uid = node->get_uid ();
221 T **v = m_map.get (uid);
222 if (v)
224 m_map.remove (uid);
225 this->release (*v);
229 /* Return true if a summary for the given NODE already exists. */
230 bool exists (cgraph_node *node)
232 return m_map.get (node->get_uid ()) != NULL;
235 /* Symbol insertion hook that is registered to symbol table. */
236 static void symtab_insertion (cgraph_node *node, void *data);
238 /* Symbol removal hook that is registered to symbol table. */
239 static void symtab_removal (cgraph_node *node, void *data);
241 /* Symbol duplication hook that is registered to symbol table. */
242 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
243 void *data);
245 protected:
246 /* Indication if we use ggc summary. */
247 bool m_ggc;
249 private:
250 /* Indication if we use ggc summary. */
251 bool is_ggc () final override
253 return m_ggc;
256 typedef int_hash <int, 0, -1> map_hash;
258 /* Main summary store, where summary ID is used as key. */
259 hash_map <map_hash, T *> m_map;
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 *);
267 template <typename T>
268 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 m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
276 template <typename T>
277 function_summary<T *>::~function_summary ()
279 this->unregister_hooks ();
281 /* Release all summaries. */
282 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
283 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
284 this->release ((*it).second);
287 template <typename T>
288 void
289 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
291 gcc_checking_assert (node->get_uid ());
292 function_summary *summary = (function_summary <T *> *) (data);
293 summary->insert (node, summary->get_create (node));
296 template <typename T>
297 void
298 function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
300 gcc_checking_assert (node->get_uid ());
301 function_summary *summary = (function_summary <T *> *) (data);
302 summary->remove (node);
305 template <typename T>
306 void
307 function_summary<T *>::symtab_duplication (cgraph_node *node,
308 cgraph_node *node2, void *data)
310 function_summary *summary = (function_summary <T *> *) (data);
311 T *v = summary->get (node);
313 if (v)
314 summary->duplicate (node, node2, v, summary->get_create (node2));
317 template <typename T>
318 void
319 gt_ggc_mx(function_summary<T *>* const &summary)
321 gcc_checking_assert (summary->m_ggc);
322 gt_ggc_mx (&summary->m_map);
325 template <typename T>
326 void
327 gt_pch_nx (function_summary<T *> *const &)
329 gcc_unreachable ();
332 template <typename T>
333 void
334 gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
336 gcc_unreachable ();
339 /* Help template from std c++11. */
341 template<typename T, typename U>
342 struct is_same
344 static const bool value = false;
347 template<typename T>
348 struct is_same<T,T> //specialization
350 static const bool value = true;
353 /* We want to pass just pointer types as argument for fast_function_summary
354 template class. */
356 template <class T, class V>
357 class fast_function_summary
359 private:
360 fast_function_summary ();
363 /* Function vector summary is a fast implementation of function_summary that
364 utilizes vector as primary storage of summaries. */
366 template <class T, class V>
367 class GTY((user)) fast_function_summary <T *, V>
368 : public function_summary_base<T>
370 public:
371 /* Default construction takes SYMTAB as an argument. */
372 fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
374 /* Destructor. */
375 virtual ~fast_function_summary ();
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
382 for (unsigned i = 0; i < m_vector->length (); i++)
383 if ((*m_vector[i]) != NULL)
384 f ((*m_vector)[i], a);
387 /* Getter for summary callgraph node pointer. If a summary for a node
388 does not exist it will be created. */
389 T* get_create (cgraph_node *node)
391 int id = node->get_summary_id ();
392 if (id == -1)
393 id = this->m_symtab->assign_summary_id (node);
395 if ((unsigned int)id >= m_vector->length ())
396 vec_safe_grow_cleared (m_vector,
397 this->m_symtab->cgraph_max_summary_id);
399 if ((*m_vector)[id] == NULL)
400 (*m_vector)[id] = this->allocate_new ();
402 return (*m_vector)[id];
405 /* Getter for summary callgraph node pointer. */
406 T* get (cgraph_node *node) ATTRIBUTE_PURE
408 return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
411 using function_summary_base<T>::remove;
412 void remove (cgraph_node *node)
414 if (exists (node))
416 int id = node->get_summary_id ();
417 this->release ((*m_vector)[id]);
418 (*m_vector)[id] = NULL;
422 /* Return true if a summary for the given NODE already exists. */
423 bool exists (cgraph_node *node)
425 int id = node->get_summary_id ();
426 return (id != -1
427 && (unsigned int)id < m_vector->length ()
428 && (*m_vector)[id] != NULL);
431 /* Symbol insertion hook that is registered to symbol table. */
432 static void symtab_insertion (cgraph_node *node, void *data);
434 /* Symbol removal hook that is registered to symbol table. */
435 static void symtab_removal (cgraph_node *node, void *data);
437 /* Symbol duplication hook that is registered to symbol table. */
438 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
439 void *data);
441 private:
442 bool is_ggc () final override;
444 /* Summary is stored in the vector. */
445 vec <T *, V> *m_vector;
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 *);
453 template <typename T, typename V>
454 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 PASS_MEM_STAT), m_vector (NULL)
462 vec_alloc (m_vector, 13 PASS_MEM_STAT);
465 template <typename T, typename V>
466 fast_function_summary<T *, V>::~fast_function_summary ()
468 this->unregister_hooks ();
470 /* Release all summaries. */
471 for (unsigned i = 0; i < m_vector->length (); i++)
472 if ((*m_vector)[i] != NULL)
473 this->release ((*m_vector)[i]);
474 vec_free (m_vector);
477 template <typename T, typename V>
478 void
479 fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
481 gcc_checking_assert (node->get_uid ());
482 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
483 summary->insert (node, summary->get_create (node));
486 template <typename T, typename V>
487 void
488 fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
490 gcc_checking_assert (node->get_uid ());
491 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
493 if (summary->exists (node))
494 summary->remove (node);
497 template <typename T, typename V>
498 void
499 fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
500 cgraph_node *node2,
501 void *data)
503 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
504 T *v = summary->get (node);
506 if (v)
508 T *duplicate = summary->get_create (node2);
509 summary->duplicate (node, node2, v, duplicate);
513 template <typename T, typename V>
514 inline bool
515 fast_function_summary<T *, V>::is_ggc ()
517 return is_same<V, va_gc>::value;
520 template <typename T>
521 void
522 gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
526 template <typename T>
527 void
528 gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
532 template <typename T>
533 void
534 gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
535 void *)
539 template <typename T>
540 void
541 gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
543 ggc_test_and_set_mark (summary->m_vector);
544 gt_ggc_mx (summary->m_vector);
547 template <typename T>
548 void
549 gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
551 gcc_unreachable ();
554 template <typename T>
555 void
556 gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
557 void *)
559 gcc_unreachable ();
562 /* Base class for call_summary and fast_call_summary classes. */
564 template <class T>
565 class call_summary_base
567 public:
568 /* Default construction takes SYMTAB as an argument. */
569 call_summary_base (symbol_table *symtab, cgraph_edge_hook symtab_removal,
570 cgraph_2edge_hook symtab_duplication CXX_MEM_STAT_INFO):
571 m_symtab (symtab), m_symtab_removal (symtab_removal),
572 m_symtab_duplication (symtab_duplication), m_symtab_duplication_hook (NULL),
573 m_initialize_when_cloning (false),
574 m_allocator ("call summary" PASS_MEM_STAT)
576 m_symtab_removal_hook
577 = m_symtab->add_edge_removal_hook (m_symtab_removal, this);
578 enable_duplication_hook ();
581 /* Basic implementation of removal operation. */
582 virtual void remove (cgraph_edge *, T *) {}
584 /* Basic implementation of duplication operation. */
585 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
587 gcc_unreachable ();
590 /* Enable duplication hook invocation. */
591 void enable_duplication_hook ()
593 if (m_symtab_duplication_hook == NULL)
594 m_symtab_duplication_hook
595 = m_symtab->add_edge_duplication_hook (m_symtab_duplication,
596 this);
599 /* Enable duplication hook invocation. */
600 void disable_duplication_hook ()
602 if (m_symtab_duplication_hook != NULL)
604 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
605 m_symtab_duplication_hook = NULL;
609 protected:
610 /* Allocates new data that are stored within map. */
611 T* allocate_new ()
613 /* Call gcc_internal_because we do not want to call finalizer for
614 a type T. We call dtor explicitly. */
615 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
616 : m_allocator.allocate ();
619 /* Release an item that is stored within map. */
620 void release (T *item)
622 if (is_ggc ())
623 ggc_delete (item);
624 else
625 m_allocator.remove (item);
628 /* Unregister all call-graph hooks. */
629 void unregister_hooks ();
631 /* Symbol table the summary is registered to. */
632 symbol_table *m_symtab;
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;
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;
646 private:
647 /* Return true when the summary uses GGC memory for allocation. */
648 virtual bool is_ggc () = 0;
650 /* Object allocator for heap allocation. */
651 object_allocator<T> m_allocator;
654 template <typename T>
655 void
656 call_summary_base<T>::unregister_hooks ()
658 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
659 disable_duplication_hook ();
662 /* An impossible class templated by non-pointers so, which makes sure that only
663 summaries gathering pointers can be created. */
665 template <class T>
666 class call_summary
668 private:
669 call_summary ();
672 /* Class to store auxiliary information about call graph edges. */
674 template <class T>
675 class GTY((user)) call_summary <T *>: public call_summary_base<T>
677 public:
678 /* Default construction takes SYMTAB as an argument. */
679 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 m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
685 /* Destructor. */
686 virtual ~call_summary ();
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
693 m_map.template traverse <f> (a);
696 /* Getter for summary callgraph edge pointer.
697 If a summary for an edge does not exist, it will be created. */
698 T* get_create (cgraph_edge *edge)
700 bool existed;
701 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
702 if (!existed)
703 *v = this->allocate_new ();
705 return *v;
708 /* Getter for summary callgraph edge pointer. */
709 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
711 T **v = m_map.get (edge->get_uid ());
712 return v == NULL ? NULL : *v;
715 /* Remove edge from summary. */
716 using call_summary_base<T>::remove;
717 void remove (cgraph_edge *edge)
719 int uid = edge->get_uid ();
720 T **v = m_map.get (uid);
721 if (v)
723 m_map.remove (uid);
724 this->release (*v);
728 /* Return true if a summary for the given EDGE already exists. */
729 bool exists (cgraph_edge *edge)
731 return m_map.get (edge->get_uid ()) != NULL;
734 /* Symbol removal hook that is registered to symbol table. */
735 static void symtab_removal (cgraph_edge *edge, void *data);
737 /* Symbol duplication hook that is registered to symbol table. */
738 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
739 void *data);
741 protected:
742 /* Indication if we use ggc summary. */
743 bool m_ggc;
745 private:
746 /* Indication if we use ggc summary. */
747 bool is_ggc () final override
749 return m_ggc;
752 typedef int_hash <int, 0, -1> map_hash;
754 /* Main summary store, where summary ID is used as key. */
755 hash_map <map_hash, T *> m_map;
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 *);
763 template <typename T>
764 call_summary<T *>::~call_summary ()
766 this->unregister_hooks ();
768 /* Release all summaries. */
769 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
770 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
771 this->release ((*it).second);
774 template <typename T>
775 void
776 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
778 call_summary *summary = (call_summary <T *> *) (data);
779 summary->remove (edge);
782 template <typename T>
783 void
784 call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
785 cgraph_edge *edge2, void *data)
787 call_summary *summary = (call_summary <T *> *) (data);
788 T *edge1_summary = NULL;
790 if (summary->m_initialize_when_cloning)
791 edge1_summary = summary->get_create (edge1);
792 else
793 edge1_summary = summary->get (edge1);
795 if (edge1_summary)
796 summary->duplicate (edge1, edge2, edge1_summary,
797 summary->get_create (edge2));
800 template <typename T>
801 void
802 gt_ggc_mx(call_summary<T *>* const &summary)
804 gcc_checking_assert (summary->m_ggc);
805 gt_ggc_mx (&summary->m_map);
808 template <typename T>
809 void
810 gt_pch_nx (call_summary<T *> *const &)
812 gcc_unreachable ();
815 template <typename T>
816 void
817 gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
819 gcc_unreachable ();
822 /* We want to pass just pointer types as argument for fast_call_summary
823 template class. */
825 template <class T, class V>
826 class fast_call_summary
828 private:
829 fast_call_summary ();
832 /* Call vector summary is a fast implementation of call_summary that
833 utilizes vector as primary storage of summaries. */
835 template <class T, class V>
836 class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
838 public:
839 /* Default construction takes SYMTAB as an argument. */
840 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 m_vector (NULL)
845 vec_alloc (m_vector, 13 PASS_MEM_STAT);
848 /* Destructor. */
849 virtual ~fast_call_summary ();
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
856 for (unsigned i = 0; i < m_vector->length (); i++)
857 if ((*m_vector[i]) != NULL)
858 f ((*m_vector)[i], a);
861 /* Getter for summary callgraph edge pointer.
862 If a summary for an edge does not exist, it will be created. */
863 T* get_create (cgraph_edge *edge)
865 int id = edge->get_summary_id ();
866 if (id == -1)
867 id = this->m_symtab->assign_summary_id (edge);
869 if ((unsigned)id >= m_vector->length ())
870 vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
872 if ((*m_vector)[id] == NULL)
873 (*m_vector)[id] = this->allocate_new ();
875 return (*m_vector)[id];
878 /* Getter for summary callgraph edge pointer. */
879 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
881 return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL;
884 /* Remove edge from summary. */
885 using call_summary_base<T>::remove;
886 void remove (cgraph_edge *edge)
888 if (exists (edge))
890 int id = edge->get_summary_id ();
891 this->release ((*m_vector)[id]);
892 (*m_vector)[id] = NULL;
896 /* Return true if a summary for the given EDGE already exists. */
897 bool exists (cgraph_edge *edge)
899 int id = edge->get_summary_id ();
900 return (id != -1
901 && (unsigned)id < m_vector->length ()
902 && (*m_vector)[id] != NULL);
905 /* Symbol removal hook that is registered to symbol table. */
906 static void symtab_removal (cgraph_edge *edge, void *data);
908 /* Symbol duplication hook that is registered to symbol table. */
909 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
910 void *data);
912 private:
913 bool is_ggc () final override;
915 /* Summary is stored in the vector. */
916 vec <T *, V> *m_vector;
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 *);
924 template <typename T, typename V>
925 fast_call_summary<T *, V>::~fast_call_summary ()
927 this->unregister_hooks ();
929 /* Release all summaries. */
930 for (unsigned i = 0; i < m_vector->length (); i++)
931 if ((*m_vector)[i] != NULL)
932 this->release ((*m_vector)[i]);
933 vec_free (m_vector);
936 template <typename T, typename V>
937 void
938 fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
940 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
941 summary->remove (edge);
944 template <typename T, typename V>
945 void
946 fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
947 cgraph_edge *edge2, void *data)
949 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
950 T *edge1_summary = NULL;
952 if (summary->m_initialize_when_cloning)
953 edge1_summary = summary->get_create (edge1);
954 else
955 edge1_summary = summary->get (edge1);
957 if (edge1_summary)
959 T *duplicate = summary->get_create (edge2);
960 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
964 template <typename T, typename V>
965 inline bool
966 fast_call_summary<T *, V>::is_ggc ()
968 return is_same<V, va_gc>::value;
971 template <typename T>
972 void
973 gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
977 template <typename T>
978 void
979 gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
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)
991 template <typename T>
992 void
993 gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary)
995 ggc_test_and_set_mark (summary->m_vector);
996 gt_ggc_mx (&summary->m_vector);
999 template <typename T>
1000 void
1001 gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
1003 gcc_unreachable ();
1006 template <typename T>
1007 void
1008 gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
1010 gcc_unreachable ();
1013 #endif /* GCC_SYMBOL_SUMMARY_H */