]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/symbol-summary.h
re PR tree-optimization/91945 (ICE: tree check: expected integer_cst, have var_decl...
[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. */
fd46280d 132 function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
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 215template <typename T>
fd46280d
ML
216function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
217 MEM_STAT_DECL):
218 function_summary_base<T> (symtab), m_ggc (ggc), m_map (13, ggc, true,
219 GATHER_STATISTICS
220 PASS_MEM_STAT)
ef2ceb10 221{
db30281f
ML
222 this->m_symtab_insertion_hook
223 = this->m_symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
224 this);
225 this->m_symtab_removal_hook
226 = this->m_symtab->add_cgraph_removal_hook (function_summary::symtab_removal,
227 this);
228 this->m_symtab_duplication_hook
229 = this->m_symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication,
230 this);
ef2ceb10
ML
231}
232
233template <typename T>
78cd68c0 234function_summary<T *>::~function_summary ()
ef2ceb10 235{
db30281f 236 this->unregister_hooks ();
ef2ceb10
ML
237
238 /* Release all summaries. */
239 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
240 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
db30281f 241 this->release ((*it).second);
ef2ceb10
ML
242}
243
244template <typename T>
245void
246function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
247{
4325656f 248 gcc_checking_assert (node->get_uid ());
ef2ceb10
ML
249 function_summary *summary = (function_summary <T *> *) (data);
250
251 if (summary->m_insertion_enabled)
99353fcf 252 summary->insert (node, summary->get_create (node));
ef2ceb10
ML
253}
254
255template <typename T>
256void
257function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
258{
4325656f 259 gcc_checking_assert (node->get_uid ());
ef2ceb10 260 function_summary *summary = (function_summary <T *> *) (data);
db30281f 261 summary->remove (node);
ef2ceb10
ML
262}
263
264template <typename T>
265void
266function_summary<T *>::symtab_duplication (cgraph_node *node,
267 cgraph_node *node2, void *data)
268{
269 function_summary *summary = (function_summary <T *> *) (data);
0148358a 270 T *v = summary->get (node);
ef2ceb10
ML
271
272 if (v)
db30281f 273 summary->duplicate (node, node2, v, summary->get_create (node2));
ef2ceb10
ML
274}
275
4008290f
ML
276template <typename T>
277void
278gt_ggc_mx(function_summary<T *>* const &summary)
279{
280 gcc_checking_assert (summary->m_ggc);
281 gt_ggc_mx (&summary->m_map);
282}
283
284template <typename T>
285void
315d4248 286gt_pch_nx (function_summary<T *> *const &)
4008290f 287{
315d4248 288 gcc_unreachable ();
4008290f
ML
289}
290
291template <typename T>
292void
315d4248 293gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
4008290f 294{
315d4248 295 gcc_unreachable ();
4008290f
ML
296}
297
db30281f 298/* Help template from std c++11. */
57e563ac 299
db30281f
ML
300template<typename T, typename U>
301struct is_same
302{
303 static const bool value = false;
304};
305
306template<typename T>
307struct is_same<T,T> //specialization
308{
309 static const bool value = true;
310};
311
312/* We want to pass just pointer types as argument for fast_function_summary
313 template class. */
314
315template <class T, class V>
316class fast_function_summary
57e563ac
MJ
317{
318private:
db30281f 319 fast_function_summary ();
57e563ac
MJ
320};
321
db30281f
ML
322/* Function vector summary is a fast implementation of function_summary that
323 utilizes vector as primary storage of summaries. */
57e563ac 324
db30281f
ML
325template <class T, class V>
326class GTY((user)) fast_function_summary <T *, V>
327 : public function_summary_base<T>
57e563ac
MJ
328{
329public:
330 /* Default construction takes SYMTAB as an argument. */
fd46280d 331 fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
57e563ac
MJ
332
333 /* Destructor. */
78cd68c0 334 virtual ~fast_function_summary ();
57e563ac
MJ
335
336 /* Traverses all summarys with a function F called with
337 ARG as argument. */
338 template<typename Arg, bool (*f)(const T &, Arg)>
339 void traverse (Arg a) const
340 {
db30281f
ML
341 for (unsigned i = 0; i < m_vector->length (); i++)
342 if ((*m_vector[i]) != NULL)
721bd210 343 f ((*m_vector)[i], a);
db30281f
ML
344 }
345
346 /* Getter for summary callgraph node pointer. If a summary for a node
347 does not exist it will be created. */
348 T* get_create (cgraph_node *node)
349 {
350 int id = node->get_summary_id ();
351 if (id == -1)
352 id = this->m_symtab->assign_summary_id (node);
353
354 if ((unsigned int)id >= m_vector->length ())
355 vec_safe_grow_cleared (m_vector,
356 this->m_symtab->cgraph_max_summary_id);
357
358 if ((*m_vector)[id] == NULL)
359 (*m_vector)[id] = this->allocate_new ();
360
361 return (*m_vector)[id];
362 }
363
364 /* Getter for summary callgraph node pointer. */
365 T* get (cgraph_node *node) ATTRIBUTE_PURE
366 {
367 return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
57e563ac
MJ
368 }
369
db30281f
ML
370 using function_summary_base<T>::remove;
371 void remove (cgraph_node *node)
372 {
373 if (exists (node))
374 {
375 int id = node->get_summary_id ();
376 this->release ((*m_vector)[id]);
377 (*m_vector)[id] = NULL;
378 }
379 }
380
381 /* Return true if a summary for the given NODE already exists. */
382 bool exists (cgraph_node *node)
383 {
384 int id = node->get_summary_id ();
385 return (id != -1
386 && (unsigned int)id < m_vector->length ()
387 && (*m_vector)[id] != NULL);
388 }
389
390 /* Symbol insertion hook that is registered to symbol table. */
391 static void symtab_insertion (cgraph_node *node, void *data);
392
393 /* Symbol removal hook that is registered to symbol table. */
394 static void symtab_removal (cgraph_node *node, void *data);
395
396 /* Symbol duplication hook that is registered to symbol table. */
397 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
398 void *data);
399
400private:
401 virtual bool is_ggc ();
402
403 /* Summary is stored in the vector. */
404 vec <T *, V> *m_vector;
405
406 template <typename U> friend void gt_ggc_mx (fast_function_summary <U *, va_gc> * const &);
407 template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &);
408 template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &,
409 gt_pointer_operator, void *);
410};
411
412template <typename T, typename V>
fd46280d 413fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab MEM_STAT_DECL):
db30281f
ML
414 function_summary_base<T> (symtab), m_vector (NULL)
415{
fd46280d 416 vec_alloc (m_vector, 13 PASS_MEM_STAT);
db30281f
ML
417 this->m_symtab_insertion_hook
418 = this->m_symtab->add_cgraph_insertion_hook (fast_function_summary::symtab_insertion,
419 this);
420 this->m_symtab_removal_hook
421 = this->m_symtab->add_cgraph_removal_hook (fast_function_summary::symtab_removal,
422 this);
423 this->m_symtab_duplication_hook
424 = this->m_symtab->add_cgraph_duplication_hook (fast_function_summary::symtab_duplication,
425 this);
426}
427
428template <typename T, typename V>
78cd68c0 429fast_function_summary<T *, V>::~fast_function_summary ()
db30281f 430{
db30281f
ML
431 this->unregister_hooks ();
432
433 /* Release all summaries. */
434 for (unsigned i = 0; i < m_vector->length (); i++)
435 if ((*m_vector)[i] != NULL)
436 this->release ((*m_vector)[i]);
ea3628bd 437 vec_free (m_vector);
db30281f
ML
438}
439
440template <typename T, typename V>
441void
442fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
443{
444 gcc_checking_assert (node->get_uid ());
445 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
446
447 if (summary->m_insertion_enabled)
448 summary->insert (node, summary->get_create (node));
449}
450
451template <typename T, typename V>
452void
453fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
454{
455 gcc_checking_assert (node->get_uid ());
456 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
457
458 if (summary->exists (node))
459 summary->remove (node);
460}
461
462template <typename T, typename V>
463void
464fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
465 cgraph_node *node2,
466 void *data)
467{
468 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
469 T *v = summary->get (node);
470
471 if (v)
472 {
473 T *duplicate = summary->get_create (node2);
474 summary->duplicate (node, node2, v, duplicate);
475 }
476}
477
478template <typename T, typename V>
479inline bool
480fast_function_summary<T *, V>::is_ggc ()
481{
482 return is_same<V, va_gc>::value;
483}
484
485template <typename T>
486void
487gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
488{
489}
490
491template <typename T>
492void
493gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
494{
495}
496
497template <typename T>
498void
499gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
500 void *)
501{
502}
503
504template <typename T>
505void
506gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
507{
508 ggc_test_and_set_mark (summary->m_vector);
509 gt_ggc_mx (summary->m_vector);
510}
511
512template <typename T>
513void
315d4248 514gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
db30281f 515{
315d4248 516 gcc_unreachable ();
db30281f
ML
517}
518
519template <typename T>
520void
315d4248
ML
521gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
522 void *)
db30281f 523{
315d4248 524 gcc_unreachable ();
db30281f
ML
525}
526
527/* Base class for call_summary and fast_call_summary classes. */
528
529template <class T>
530class call_summary_base
531{
532public:
533 /* Default construction takes SYMTAB as an argument. */
534 call_summary_base (symbol_table *symtab): m_symtab (symtab),
7237f93e 535 m_initialize_when_cloning (false)
db30281f
ML
536 {}
537
57e563ac
MJ
538 /* Basic implementation of removal operation. */
539 virtual void remove (cgraph_edge *, T *) {}
540
541 /* Basic implementation of duplication operation. */
542 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
543
db30281f 544protected:
57e563ac
MJ
545 /* Allocates new data that are stored within map. */
546 T* allocate_new ()
547 {
548 /* Call gcc_internal_because we do not want to call finalizer for
549 a type T. We call dtor explicitly. */
db30281f 550 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
57e563ac
MJ
551 }
552
553 /* Release an item that is stored within map. */
db30281f
ML
554 void release (T *item)
555 {
556 if (is_ggc ())
557 {
558 item->~T ();
559 ggc_free (item);
560 }
561 else
562 delete item;
563 }
564
565 /* Unregister all call-graph hooks. */
566 void unregister_hooks ();
567
568 /* Symbol table the summary is registered to. */
569 symbol_table *m_symtab;
570
571 /* Internal summary removal hook pointer. */
572 cgraph_edge_hook_list *m_symtab_removal_hook;
573 /* Internal summary duplication hook pointer. */
574 cgraph_2edge_hook_list *m_symtab_duplication_hook;
575 /* Initialize summary for an edge that is cloned. */
576 bool m_initialize_when_cloning;
db30281f
ML
577
578private:
579 /* Return true when the summary uses GGC memory for allocation. */
580 virtual bool is_ggc () = 0;
581};
582
583template <typename T>
584void
585call_summary_base<T>::unregister_hooks ()
586{
587 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
588 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
589}
590
591/* An impossible class templated by non-pointers so, which makes sure that only
592 summaries gathering pointers can be created. */
593
594template <class T>
595class call_summary
596{
597private:
598 call_summary ();
599};
600
601/* Class to store auxiliary information about call graph edges. */
602
603template <class T>
604class GTY((user)) call_summary <T *>: public call_summary_base<T>
605{
606public:
607 /* Default construction takes SYMTAB as an argument. */
fd46280d
ML
608 call_summary (symbol_table *symtab, bool ggc = false
609 CXX_MEM_STAT_INFO)
610 : call_summary_base<T> (symtab), m_ggc (ggc), m_map (13, ggc, true,
611 GATHER_STATISTICS
612 PASS_MEM_STAT)
db30281f
ML
613 {
614 this->m_symtab_removal_hook
615 = this->m_symtab->add_edge_removal_hook (call_summary::symtab_removal,
616 this);
617 this->m_symtab_duplication_hook
618 = this->m_symtab->add_edge_duplication_hook (call_summary::symtab_duplication,
619 this);
620 }
621
622 /* Destructor. */
78cd68c0 623 virtual ~call_summary ();
db30281f
ML
624
625 /* Traverses all summarys with an edge E called with
626 ARG as argument. */
627 template<typename Arg, bool (*f)(const T &, Arg)>
628 void traverse (Arg a) const
629 {
630 m_map.traverse <f> (a);
631 }
57e563ac 632
99353fcf
ML
633 /* Getter for summary callgraph edge pointer.
634 If a summary for an edge does not exist, it will be created. */
635 T* get_create (cgraph_edge *edge)
57e563ac 636 {
e08bf125
ML
637 bool existed;
638 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
639 if (!existed)
db30281f 640 *v = this->allocate_new ();
e08bf125
ML
641
642 return *v;
dbea5bf9
ML
643 }
644
645 /* Getter for summary callgraph edge pointer. */
e08bf125 646 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
dbea5bf9 647 {
e08bf125
ML
648 T **v = m_map.get (edge->get_uid ());
649 return v == NULL ? NULL : *v;
57e563ac
MJ
650 }
651
9fb50ad8 652 /* Remove edge from summary. */
db30281f 653 using call_summary_base<T>::remove;
9fb50ad8
ML
654 void remove (cgraph_edge *edge)
655 {
8b25212d 656 int uid = edge->get_uid ();
9fb50ad8
ML
657 T **v = m_map.get (uid);
658 if (v)
659 {
660 m_map.remove (uid);
db30281f 661 this->release (*v);
9fb50ad8
ML
662 }
663 }
664
57e563ac
MJ
665 /* Return true if a summary for the given EDGE already exists. */
666 bool exists (cgraph_edge *edge)
667 {
8b25212d 668 return m_map.get (edge->get_uid ()) != NULL;
57e563ac
MJ
669 }
670
671 /* Symbol removal hook that is registered to symbol table. */
2a281178 672 static void symtab_removal (cgraph_edge *edge, void *data);
57e563ac
MJ
673
674 /* Symbol duplication hook that is registered to symbol table. */
675 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
2a281178 676 void *data);
57e563ac
MJ
677
678protected:
679 /* Indication if we use ggc summary. */
680 bool m_ggc;
681
682private:
db30281f
ML
683 /* Indication if we use ggc summary. */
684 virtual bool is_ggc ()
685 {
686 return m_ggc;
687 }
688
57e563ac
MJ
689 typedef int_hash <int, 0, -1> map_hash;
690
57e563ac
MJ
691 /* Main summary store, where summary ID is used as key. */
692 hash_map <map_hash, T *> m_map;
57e563ac
MJ
693
694 template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
695 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
696 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
697 gt_pointer_operator, void *);
698};
699
2a281178 700template <typename T>
78cd68c0 701call_summary<T *>::~call_summary ()
2a281178 702{
db30281f 703 this->unregister_hooks ();
2a281178
ML
704
705 /* Release all summaries. */
706 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
707 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
db30281f 708 this->release ((*it).second);
2a281178
ML
709}
710
711template <typename T>
712void
713call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
714{
715 call_summary *summary = (call_summary <T *> *) (data);
db30281f 716 summary->remove (edge);
2a281178
ML
717}
718
719template <typename T>
720void
721call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
722 cgraph_edge *edge2, void *data)
723{
724 call_summary *summary = (call_summary <T *> *) (data);
dbea5bf9 725 T *edge1_summary = NULL;
2a281178 726
dbea5bf9
ML
727 if (summary->m_initialize_when_cloning)
728 edge1_summary = summary->get_create (edge1);
729 else
db30281f 730 edge1_summary = summary->get (edge1);
dbea5bf9
ML
731
732 if (edge1_summary)
db30281f
ML
733 summary->duplicate (edge1, edge2, edge1_summary,
734 summary->get_create (edge2));
2a281178
ML
735}
736
57e563ac
MJ
737template <typename T>
738void
739gt_ggc_mx(call_summary<T *>* const &summary)
740{
741 gcc_checking_assert (summary->m_ggc);
742 gt_ggc_mx (&summary->m_map);
743}
744
745template <typename T>
746void
315d4248 747gt_pch_nx (call_summary<T *> *const &)
57e563ac 748{
315d4248 749 gcc_unreachable ();
57e563ac
MJ
750}
751
752template <typename T>
753void
315d4248 754gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
57e563ac 755{
315d4248 756 gcc_unreachable ();
57e563ac
MJ
757}
758
db30281f
ML
759/* We want to pass just pointer types as argument for fast_call_summary
760 template class. */
761
762template <class T, class V>
763class fast_call_summary
764{
765private:
766 fast_call_summary ();
767};
768
769/* Call vector summary is a fast implementation of call_summary that
770 utilizes vector as primary storage of summaries. */
771
772template <class T, class V>
773class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
774{
775public:
776 /* Default construction takes SYMTAB as an argument. */
fd46280d 777 fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
db30281f
ML
778 : call_summary_base<T> (symtab), m_vector (NULL)
779 {
fd46280d 780 vec_alloc (m_vector, 13 PASS_MEM_STAT);
db30281f
ML
781 this->m_symtab_removal_hook
782 = this->m_symtab->add_edge_removal_hook (fast_call_summary::symtab_removal,
783 this);
784 this->m_symtab_duplication_hook
785 = this->m_symtab->add_edge_duplication_hook (fast_call_summary::symtab_duplication,
786 this);
787 }
788
789 /* Destructor. */
78cd68c0 790 virtual ~fast_call_summary ();
db30281f
ML
791
792 /* Traverses all summarys with an edge F called with
793 ARG as argument. */
794 template<typename Arg, bool (*f)(const T &, Arg)>
795 void traverse (Arg a) const
796 {
797 for (unsigned i = 0; i < m_vector->length (); i++)
798 if ((*m_vector[i]) != NULL)
721bd210 799 f ((*m_vector)[i], a);
db30281f
ML
800 }
801
802 /* Getter for summary callgraph edge pointer.
803 If a summary for an edge does not exist, it will be created. */
804 T* get_create (cgraph_edge *edge)
805 {
806 int id = edge->get_summary_id ();
807 if (id == -1)
808 id = this->m_symtab->assign_summary_id (edge);
809
810 if ((unsigned)id >= m_vector->length ())
811 vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
812
813 if ((*m_vector)[id] == NULL)
814 (*m_vector)[id] = this->allocate_new ();
815
816 return (*m_vector)[id];
817 }
818
819 /* Getter for summary callgraph edge pointer. */
820 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
821 {
822 return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL;
823 }
824
825 /* Remove edge from summary. */
826 using call_summary_base<T>::remove;
827 void remove (cgraph_edge *edge)
828 {
829 if (exists (edge))
830 {
831 int id = edge->get_summary_id ();
832 this->release ((*m_vector)[id]);
833 (*m_vector)[id] = NULL;
834 }
835 }
836
837 /* Return true if a summary for the given EDGE already exists. */
838 bool exists (cgraph_edge *edge)
839 {
840 int id = edge->get_summary_id ();
841 return (id != -1
842 && (unsigned)id < m_vector->length ()
843 && (*m_vector)[id] != NULL);
844 }
845
846 /* Symbol removal hook that is registered to symbol table. */
847 static void symtab_removal (cgraph_edge *edge, void *data);
848
849 /* Symbol duplication hook that is registered to symbol table. */
850 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
851 void *data);
852
853private:
854 virtual bool is_ggc ();
855
856 /* Summary is stored in the vector. */
857 vec <T *, V> *m_vector;
858
859 template <typename U> friend void gt_ggc_mx (fast_call_summary <U *, va_gc> * const &);
860 template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &);
861 template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &,
862 gt_pointer_operator, void *);
863};
864
865template <typename T, typename V>
78cd68c0 866fast_call_summary<T *, V>::~fast_call_summary ()
db30281f 867{
db30281f
ML
868 this->unregister_hooks ();
869
870 /* Release all summaries. */
871 for (unsigned i = 0; i < m_vector->length (); i++)
872 if ((*m_vector)[i] != NULL)
873 this->release ((*m_vector)[i]);
ea3628bd 874 vec_free (m_vector);
db30281f
ML
875}
876
877template <typename T, typename V>
878void
879fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
880{
881 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
882 summary->remove (edge);
883}
884
885template <typename T, typename V>
886void
887fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
888 cgraph_edge *edge2, void *data)
889{
890 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
891 T *edge1_summary = NULL;
892
893 if (summary->m_initialize_when_cloning)
894 edge1_summary = summary->get_create (edge1);
895 else
896 edge1_summary = summary->get (edge1);
897
898 if (edge1_summary)
899 {
900 T *duplicate = summary->get_create (edge2);
901 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
902 }
903}
904
905template <typename T, typename V>
906inline bool
907fast_call_summary<T *, V>::is_ggc ()
908{
909 return is_same<V, va_gc>::value;
910}
911
912template <typename T>
913void
721bd210 914gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
db30281f
ML
915{
916}
917
918template <typename T>
919void
721bd210 920gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
db30281f
ML
921{
922}
923
924template <typename T>
925void
721bd210
ML
926gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
927 gt_pointer_operator op ATTRIBUTE_UNUSED,
928 void *cookie ATTRIBUTE_UNUSED)
db30281f
ML
929{
930}
931
932template <typename T>
933void
934gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary)
935{
936 ggc_test_and_set_mark (summary->m_vector);
937 gt_ggc_mx (&summary->m_vector);
938}
939
940template <typename T>
941void
315d4248 942gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
db30281f 943{
315d4248 944 gcc_unreachable ();
db30281f
ML
945}
946
947template <typename T>
948void
315d4248 949gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
db30281f 950{
315d4248 951 gcc_unreachable ();
db30281f
ML
952}
953
4008290f 954#endif /* GCC_SYMBOL_SUMMARY_H */