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