]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/symbol-summary.h
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / symbol-summary.h
CommitLineData
4008290f 1/* Callgraph summary data structure.
99dee823 2 Copyright (C) 2014-2021 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. */
251c9aea
ML
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),
dbe348c1 40 m_allocator ("function summary" PASS_MEM_STAT)
251c9aea
ML
41 {
42 enable_insertion_hook ();
43 m_symtab_removal_hook
44 = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this);
45 enable_duplication_hook ();
46 }
db30281f
ML
47
48 /* Basic implementation of insert operation. */
40e67ab8
JH
49 virtual void insert (cgraph_node *, T *)
50 {
51 /* In most cases, it makes no sense to create summaries without
52 initializing them. */
53 gcc_unreachable ();
54 }
db30281f
ML
55
56 /* Basic implementation of removal operation. */
57 virtual void remove (cgraph_node *, T *) {}
58
59 /* Basic implementation of duplication operation. */
40e67ab8
JH
60 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
61 {
62 /* It makes no sense to not copy anything during duplication. */
63 gcc_unreachable ();
64 }
db30281f
ML
65
66 /* Enable insertion hook invocation. */
67 void enable_insertion_hook ()
68 {
251c9aea
ML
69 if (m_symtab_insertion_hook == NULL)
70 m_symtab_insertion_hook
71 = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
db30281f
ML
72 }
73
74 /* Enable insertion hook invocation. */
75 void disable_insertion_hook ()
76 {
251c9aea
ML
77 if (m_symtab_insertion_hook != NULL)
78 {
79 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
80 m_symtab_insertion_hook = NULL;
81 }
db30281f
ML
82 }
83
40e67ab8
JH
84 /* Enable duplication hook invocation. */
85 void enable_duplication_hook ()
86 {
251c9aea
ML
87 if (m_symtab_duplication_hook == NULL)
88 m_symtab_duplication_hook
89 = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this);
40e67ab8
JH
90 }
91
92 /* Enable duplication hook invocation. */
93 void disable_duplication_hook ()
94 {
251c9aea
ML
95 if (m_symtab_duplication_hook != NULL)
96 {
97 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
98 m_symtab_duplication_hook = NULL;
99 }
40e67ab8
JH
100 }
101
db30281f
ML
102protected:
103 /* Allocates new data that are stored within map. */
104 T* allocate_new ()
105 {
106 /* Call gcc_internal_because we do not want to call finalizer for
107 a type T. We call dtor explicitly. */
a895e6d7 108 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
dbe348c1 109 : m_allocator.allocate () ;
db30281f
ML
110 }
111
112 /* Release an item that is stored within map. */
113 void release (T *item)
114 {
115 if (is_ggc ())
9aca5960 116 ggc_delete (item);
db30281f 117 else
dbe348c1 118 m_allocator.remove (item);
db30281f
ML
119 }
120
121 /* Unregister all call-graph hooks. */
122 void unregister_hooks ();
123
251c9aea
ML
124 /* Symbol table the summary is registered to. */
125 symbol_table *m_symtab;
126
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;
133
db30281f
ML
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;
db30281f
ML
140
141private:
142 /* Return true when the summary uses GGC memory for allocation. */
143 virtual bool is_ggc () = 0;
dbe348c1
ML
144
145 /* Object allocator for heap allocation. */
146 object_allocator<T> m_allocator;
db30281f
ML
147};
148
149template <typename T>
150void
151function_summary_base<T>::unregister_hooks ()
152{
251c9aea 153 disable_insertion_hook ();
db30281f 154 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
251c9aea 155 disable_duplication_hook ();
db30281f
ML
156}
157
4008290f
ML
158/* We want to pass just pointer types as argument for function_summary
159 template class. */
160
161template <class T>
162class function_summary
163{
164private:
165 function_summary();
166};
167
ef2ceb10
ML
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.
175
176 The function summary class can work both with a heap-allocated memory and
177 a memory gained by garbage collected memory. */
178
4008290f 179template <class T>
db30281f 180class GTY((user)) function_summary <T *>: public function_summary_base<T>
4008290f
ML
181{
182public:
183 /* Default construction takes SYMTAB as an argument. */
fd46280d 184 function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
4008290f
ML
185
186 /* Destructor. */
78cd68c0 187 virtual ~function_summary ();
4008290f
ML
188
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
193 {
fccd5b48 194 m_map.template traverse <f> (a);
4008290f
ML
195 }
196
99353fcf
ML
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)
4008290f 200 {
e08bf125
ML
201 bool existed;
202 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
203 if (!existed)
db30281f 204 *v = this->allocate_new ();
e08bf125
ML
205
206 return *v;
0148358a
ML
207 }
208
209 /* Getter for summary callgraph node pointer. */
e08bf125 210 T* get (cgraph_node *node) ATTRIBUTE_PURE
0148358a 211 {
e08bf125
ML
212 T **v = m_map.get (node->get_uid ());
213 return v == NULL ? NULL : *v;
4008290f
ML
214 }
215
56f62793 216 /* Remove node from summary. */
db30281f 217 using function_summary_base<T>::remove;
56f62793
ML
218 void remove (cgraph_node *node)
219 {
220 int uid = node->get_uid ();
221 T **v = m_map.get (uid);
222 if (v)
223 {
224 m_map.remove (uid);
db30281f 225 this->release (*v);
56f62793
ML
226 }
227 }
228
57e563ac
MJ
229 /* Return true if a summary for the given NODE already exists. */
230 bool exists (cgraph_node *node)
231 {
4325656f 232 return m_map.get (node->get_uid ()) != NULL;
57e563ac
MJ
233 }
234
4008290f 235 /* Symbol insertion hook that is registered to symbol table. */
ef2ceb10 236 static void symtab_insertion (cgraph_node *node, void *data);
4008290f
ML
237
238 /* Symbol removal hook that is registered to symbol table. */
ef2ceb10 239 static void symtab_removal (cgraph_node *node, void *data);
4008290f
ML
240
241 /* Symbol duplication hook that is registered to symbol table. */
242 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
ef2ceb10 243 void *data);
4008290f
ML
244
245protected:
246 /* Indication if we use ggc summary. */
247 bool m_ggc;
248
249private:
db30281f
ML
250 /* Indication if we use ggc summary. */
251 virtual bool is_ggc ()
252 {
253 return m_ggc;
254 }
255
e0702244 256 typedef int_hash <int, 0, -1> map_hash;
4008290f 257
4008290f 258 /* Main summary store, where summary ID is used as key. */
fb5c464a 259 hash_map <map_hash, T *> m_map;
4008290f
ML
260
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 *);
265};
266
ef2ceb10 267template <typename T>
fd46280d
ML
268function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
269 MEM_STAT_DECL):
251c9aea
ML
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) {}
ef2ceb10
ML
275
276template <typename T>
78cd68c0 277function_summary<T *>::~function_summary ()
ef2ceb10 278{
db30281f 279 this->unregister_hooks ();
ef2ceb10
ML
280
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)
db30281f 284 this->release ((*it).second);
ef2ceb10
ML
285}
286
287template <typename T>
288void
289function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
290{
4325656f 291 gcc_checking_assert (node->get_uid ());
ef2ceb10 292 function_summary *summary = (function_summary <T *> *) (data);
251c9aea 293 summary->insert (node, summary->get_create (node));
ef2ceb10
ML
294}
295
296template <typename T>
297void
298function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
299{
4325656f 300 gcc_checking_assert (node->get_uid ());
ef2ceb10 301 function_summary *summary = (function_summary <T *> *) (data);
db30281f 302 summary->remove (node);
ef2ceb10
ML
303}
304
305template <typename T>
306void
307function_summary<T *>::symtab_duplication (cgraph_node *node,
308 cgraph_node *node2, void *data)
309{
310 function_summary *summary = (function_summary <T *> *) (data);
251c9aea 311 T *v = summary->get (node);
ef2ceb10 312
251c9aea
ML
313 if (v)
314 summary->duplicate (node, node2, v, summary->get_create (node2));
ef2ceb10
ML
315}
316
4008290f
ML
317template <typename T>
318void
319gt_ggc_mx(function_summary<T *>* const &summary)
320{
321 gcc_checking_assert (summary->m_ggc);
322 gt_ggc_mx (&summary->m_map);
323}
324
325template <typename T>
326void
315d4248 327gt_pch_nx (function_summary<T *> *const &)
4008290f 328{
315d4248 329 gcc_unreachable ();
4008290f
ML
330}
331
332template <typename T>
333void
315d4248 334gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
4008290f 335{
315d4248 336 gcc_unreachable ();
4008290f
ML
337}
338
db30281f 339/* Help template from std c++11. */
57e563ac 340
db30281f
ML
341template<typename T, typename U>
342struct is_same
343{
344 static const bool value = false;
345};
346
347template<typename T>
348struct is_same<T,T> //specialization
349{
350 static const bool value = true;
351};
352
353/* We want to pass just pointer types as argument for fast_function_summary
354 template class. */
355
356template <class T, class V>
357class fast_function_summary
57e563ac
MJ
358{
359private:
db30281f 360 fast_function_summary ();
57e563ac
MJ
361};
362
db30281f
ML
363/* Function vector summary is a fast implementation of function_summary that
364 utilizes vector as primary storage of summaries. */
57e563ac 365
db30281f
ML
366template <class T, class V>
367class GTY((user)) fast_function_summary <T *, V>
368 : public function_summary_base<T>
57e563ac
MJ
369{
370public:
371 /* Default construction takes SYMTAB as an argument. */
fd46280d 372 fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
57e563ac
MJ
373
374 /* Destructor. */
78cd68c0 375 virtual ~fast_function_summary ();
57e563ac
MJ
376
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
381 {
db30281f
ML
382 for (unsigned i = 0; i < m_vector->length (); i++)
383 if ((*m_vector[i]) != NULL)
721bd210 384 f ((*m_vector)[i], a);
db30281f
ML
385 }
386
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)
390 {
391 int id = node->get_summary_id ();
392 if (id == -1)
393 id = this->m_symtab->assign_summary_id (node);
394
395 if ((unsigned int)id >= m_vector->length ())
a292e31d
ML
396 vec_safe_grow_cleared (m_vector,
397 this->m_symtab->cgraph_max_summary_id);
db30281f
ML
398
399 if ((*m_vector)[id] == NULL)
400 (*m_vector)[id] = this->allocate_new ();
401
402 return (*m_vector)[id];
403 }
404
405 /* Getter for summary callgraph node pointer. */
406 T* get (cgraph_node *node) ATTRIBUTE_PURE
407 {
408 return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
57e563ac
MJ
409 }
410
db30281f
ML
411 using function_summary_base<T>::remove;
412 void remove (cgraph_node *node)
413 {
414 if (exists (node))
415 {
416 int id = node->get_summary_id ();
417 this->release ((*m_vector)[id]);
418 (*m_vector)[id] = NULL;
419 }
420 }
421
422 /* Return true if a summary for the given NODE already exists. */
423 bool exists (cgraph_node *node)
424 {
425 int id = node->get_summary_id ();
426 return (id != -1
427 && (unsigned int)id < m_vector->length ()
428 && (*m_vector)[id] != NULL);
429 }
430
431 /* Symbol insertion hook that is registered to symbol table. */
432 static void symtab_insertion (cgraph_node *node, void *data);
433
434 /* Symbol removal hook that is registered to symbol table. */
435 static void symtab_removal (cgraph_node *node, void *data);
436
437 /* Symbol duplication hook that is registered to symbol table. */
438 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
439 void *data);
440
441private:
442 virtual bool is_ggc ();
443
444 /* Summary is stored in the vector. */
445 vec <T *, V> *m_vector;
446
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 *);
451};
452
453template <typename T, typename V>
251c9aea
ML
454fast_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)
db30281f 461{
fd46280d 462 vec_alloc (m_vector, 13 PASS_MEM_STAT);
db30281f
ML
463}
464
465template <typename T, typename V>
78cd68c0 466fast_function_summary<T *, V>::~fast_function_summary ()
db30281f 467{
db30281f
ML
468 this->unregister_hooks ();
469
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]);
ea3628bd 474 vec_free (m_vector);
db30281f
ML
475}
476
477template <typename T, typename V>
478void
479fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
480{
481 gcc_checking_assert (node->get_uid ());
482 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
251c9aea 483 summary->insert (node, summary->get_create (node));
db30281f
ML
484}
485
486template <typename T, typename V>
487void
488fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
489{
490 gcc_checking_assert (node->get_uid ());
491 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
492
493 if (summary->exists (node))
494 summary->remove (node);
495}
496
497template <typename T, typename V>
498void
499fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
500 cgraph_node *node2,
501 void *data)
502{
503 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
251c9aea 504 T *v = summary->get (node);
40e67ab8 505
251c9aea
ML
506 if (v)
507 {
508 T *duplicate = summary->get_create (node2);
509 summary->duplicate (node, node2, v, duplicate);
db30281f
ML
510 }
511}
512
513template <typename T, typename V>
514inline bool
515fast_function_summary<T *, V>::is_ggc ()
516{
517 return is_same<V, va_gc>::value;
518}
519
520template <typename T>
521void
522gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
523{
524}
525
526template <typename T>
527void
528gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
529{
530}
531
532template <typename T>
533void
534gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
535 void *)
536{
537}
538
539template <typename T>
540void
541gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
542{
543 ggc_test_and_set_mark (summary->m_vector);
544 gt_ggc_mx (summary->m_vector);
545}
546
547template <typename T>
548void
315d4248 549gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
db30281f 550{
315d4248 551 gcc_unreachable ();
db30281f
ML
552}
553
554template <typename T>
555void
315d4248
ML
556gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
557 void *)
db30281f 558{
315d4248 559 gcc_unreachable ();
db30281f
ML
560}
561
562/* Base class for call_summary and fast_call_summary classes. */
563
564template <class T>
565class call_summary_base
566{
567public:
568 /* Default construction takes SYMTAB as an argument. */
953a9d63
ML
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),
a895e6d7 573 m_initialize_when_cloning (false),
dbe348c1 574 m_allocator ("call summary" PASS_MEM_STAT)
953a9d63
ML
575 {
576 m_symtab_removal_hook
577 = m_symtab->add_edge_removal_hook (m_symtab_removal, this);
578 enable_duplication_hook ();
579 }
db30281f 580
57e563ac
MJ
581 /* Basic implementation of removal operation. */
582 virtual void remove (cgraph_edge *, T *) {}
583
584 /* Basic implementation of duplication operation. */
40e67ab8
JH
585 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
586 {
587 gcc_unreachable ();
588 }
589
590 /* Enable duplication hook invocation. */
591 void enable_duplication_hook ()
592 {
953a9d63
ML
593 if (m_symtab_duplication_hook == NULL)
594 m_symtab_duplication_hook
595 = m_symtab->add_edge_duplication_hook (m_symtab_duplication,
596 this);
40e67ab8
JH
597 }
598
599 /* Enable duplication hook invocation. */
600 void disable_duplication_hook ()
601 {
953a9d63
ML
602 if (m_symtab_duplication_hook != NULL)
603 {
604 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
605 m_symtab_duplication_hook = NULL;
606 }
40e67ab8 607 }
57e563ac 608
db30281f 609protected:
57e563ac
MJ
610 /* Allocates new data that are stored within map. */
611 T* allocate_new ()
612 {
613 /* Call gcc_internal_because we do not want to call finalizer for
614 a type T. We call dtor explicitly. */
a895e6d7 615 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
dbe348c1 616 : m_allocator.allocate ();
57e563ac
MJ
617 }
618
619 /* Release an item that is stored within map. */
db30281f
ML
620 void release (T *item)
621 {
622 if (is_ggc ())
9aca5960 623 ggc_delete (item);
db30281f 624 else
dbe348c1 625 m_allocator.remove (item);
db30281f
ML
626 }
627
628 /* Unregister all call-graph hooks. */
629 void unregister_hooks ();
630
631 /* Symbol table the summary is registered to. */
632 symbol_table *m_symtab;
633
953a9d63
ML
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;
638
db30281f
ML
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;
db30281f
ML
645
646private:
647 /* Return true when the summary uses GGC memory for allocation. */
648 virtual bool is_ggc () = 0;
dbe348c1
ML
649
650 /* Object allocator for heap allocation. */
651 object_allocator<T> m_allocator;
db30281f
ML
652};
653
654template <typename T>
655void
656call_summary_base<T>::unregister_hooks ()
657{
658 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
953a9d63 659 disable_duplication_hook ();
db30281f
ML
660}
661
662/* An impossible class templated by non-pointers so, which makes sure that only
663 summaries gathering pointers can be created. */
664
665template <class T>
666class call_summary
667{
668private:
669 call_summary ();
670};
671
672/* Class to store auxiliary information about call graph edges. */
673
674template <class T>
675class GTY((user)) call_summary <T *>: public call_summary_base<T>
676{
677public:
678 /* Default construction takes SYMTAB as an argument. */
fd46280d
ML
679 call_summary (symbol_table *symtab, bool ggc = false
680 CXX_MEM_STAT_INFO)
953a9d63
ML
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) {}
db30281f
ML
684
685 /* Destructor. */
78cd68c0 686 virtual ~call_summary ();
db30281f
ML
687
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
692 {
fccd5b48 693 m_map.template traverse <f> (a);
db30281f 694 }
57e563ac 695
99353fcf
ML
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)
57e563ac 699 {
e08bf125
ML
700 bool existed;
701 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
702 if (!existed)
db30281f 703 *v = this->allocate_new ();
e08bf125
ML
704
705 return *v;
dbea5bf9
ML
706 }
707
708 /* Getter for summary callgraph edge pointer. */
e08bf125 709 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
dbea5bf9 710 {
e08bf125
ML
711 T **v = m_map.get (edge->get_uid ());
712 return v == NULL ? NULL : *v;
57e563ac
MJ
713 }
714
9fb50ad8 715 /* Remove edge from summary. */
db30281f 716 using call_summary_base<T>::remove;
9fb50ad8
ML
717 void remove (cgraph_edge *edge)
718 {
8b25212d 719 int uid = edge->get_uid ();
9fb50ad8
ML
720 T **v = m_map.get (uid);
721 if (v)
722 {
723 m_map.remove (uid);
db30281f 724 this->release (*v);
9fb50ad8
ML
725 }
726 }
727
57e563ac
MJ
728 /* Return true if a summary for the given EDGE already exists. */
729 bool exists (cgraph_edge *edge)
730 {
8b25212d 731 return m_map.get (edge->get_uid ()) != NULL;
57e563ac
MJ
732 }
733
734 /* Symbol removal hook that is registered to symbol table. */
2a281178 735 static void symtab_removal (cgraph_edge *edge, void *data);
57e563ac
MJ
736
737 /* Symbol duplication hook that is registered to symbol table. */
738 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
2a281178 739 void *data);
57e563ac
MJ
740
741protected:
742 /* Indication if we use ggc summary. */
743 bool m_ggc;
744
745private:
db30281f
ML
746 /* Indication if we use ggc summary. */
747 virtual bool is_ggc ()
748 {
749 return m_ggc;
750 }
751
57e563ac
MJ
752 typedef int_hash <int, 0, -1> map_hash;
753
57e563ac
MJ
754 /* Main summary store, where summary ID is used as key. */
755 hash_map <map_hash, T *> m_map;
57e563ac
MJ
756
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 *);
761};
762
2a281178 763template <typename T>
78cd68c0 764call_summary<T *>::~call_summary ()
2a281178 765{
db30281f 766 this->unregister_hooks ();
2a281178
ML
767
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)
db30281f 771 this->release ((*it).second);
2a281178
ML
772}
773
774template <typename T>
775void
776call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
777{
778 call_summary *summary = (call_summary <T *> *) (data);
db30281f 779 summary->remove (edge);
2a281178
ML
780}
781
782template <typename T>
783void
784call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
785 cgraph_edge *edge2, void *data)
786{
787 call_summary *summary = (call_summary <T *> *) (data);
953a9d63 788 T *edge1_summary = NULL;
2a281178 789
953a9d63
ML
790 if (summary->m_initialize_when_cloning)
791 edge1_summary = summary->get_create (edge1);
792 else
793 edge1_summary = summary->get (edge1);
dbea5bf9 794
953a9d63
ML
795 if (edge1_summary)
796 summary->duplicate (edge1, edge2, edge1_summary,
797 summary->get_create (edge2));
2a281178
ML
798}
799
57e563ac
MJ
800template <typename T>
801void
802gt_ggc_mx(call_summary<T *>* const &summary)
803{
804 gcc_checking_assert (summary->m_ggc);
805 gt_ggc_mx (&summary->m_map);
806}
807
808template <typename T>
809void
315d4248 810gt_pch_nx (call_summary<T *> *const &)
57e563ac 811{
315d4248 812 gcc_unreachable ();
57e563ac
MJ
813}
814
815template <typename T>
816void
315d4248 817gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
57e563ac 818{
315d4248 819 gcc_unreachable ();
57e563ac
MJ
820}
821
db30281f
ML
822/* We want to pass just pointer types as argument for fast_call_summary
823 template class. */
824
825template <class T, class V>
826class fast_call_summary
827{
828private:
829 fast_call_summary ();
830};
831
832/* Call vector summary is a fast implementation of call_summary that
833 utilizes vector as primary storage of summaries. */
834
835template <class T, class V>
836class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
837{
838public:
839 /* Default construction takes SYMTAB as an argument. */
fd46280d 840 fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
953a9d63
ML
841 : call_summary_base<T> (symtab, fast_call_summary::symtab_removal,
842 fast_call_summary::symtab_duplication PASS_MEM_STAT),
843 m_vector (NULL)
db30281f 844 {
fd46280d 845 vec_alloc (m_vector, 13 PASS_MEM_STAT);
db30281f
ML
846 }
847
848 /* Destructor. */
78cd68c0 849 virtual ~fast_call_summary ();
db30281f
ML
850
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
855 {
856 for (unsigned i = 0; i < m_vector->length (); i++)
857 if ((*m_vector[i]) != NULL)
721bd210 858 f ((*m_vector)[i], a);
db30281f
ML
859 }
860
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)
864 {
865 int id = edge->get_summary_id ();
866 if (id == -1)
867 id = this->m_symtab->assign_summary_id (edge);
868
869 if ((unsigned)id >= m_vector->length ())
a292e31d 870 vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
db30281f
ML
871
872 if ((*m_vector)[id] == NULL)
873 (*m_vector)[id] = this->allocate_new ();
874
875 return (*m_vector)[id];
876 }
877
878 /* Getter for summary callgraph edge pointer. */
879 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
880 {
881 return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL;
882 }
883
884 /* Remove edge from summary. */
885 using call_summary_base<T>::remove;
886 void remove (cgraph_edge *edge)
887 {
888 if (exists (edge))
889 {
890 int id = edge->get_summary_id ();
891 this->release ((*m_vector)[id]);
892 (*m_vector)[id] = NULL;
893 }
894 }
895
896 /* Return true if a summary for the given EDGE already exists. */
897 bool exists (cgraph_edge *edge)
898 {
899 int id = edge->get_summary_id ();
900 return (id != -1
901 && (unsigned)id < m_vector->length ()
902 && (*m_vector)[id] != NULL);
903 }
904
905 /* Symbol removal hook that is registered to symbol table. */
906 static void symtab_removal (cgraph_edge *edge, void *data);
907
908 /* Symbol duplication hook that is registered to symbol table. */
909 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
910 void *data);
911
912private:
913 virtual bool is_ggc ();
914
915 /* Summary is stored in the vector. */
916 vec <T *, V> *m_vector;
917
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 *);
922};
923
924template <typename T, typename V>
78cd68c0 925fast_call_summary<T *, V>::~fast_call_summary ()
db30281f 926{
db30281f
ML
927 this->unregister_hooks ();
928
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]);
ea3628bd 933 vec_free (m_vector);
db30281f
ML
934}
935
936template <typename T, typename V>
937void
938fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
939{
940 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
941 summary->remove (edge);
942}
943
944template <typename T, typename V>
945void
946fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
947 cgraph_edge *edge2, void *data)
948{
949 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
953a9d63
ML
950 T *edge1_summary = NULL;
951
952 if (summary->m_initialize_when_cloning)
953 edge1_summary = summary->get_create (edge1);
954 else
955 edge1_summary = summary->get (edge1);
956
957 if (edge1_summary)
db30281f 958 {
953a9d63
ML
959 T *duplicate = summary->get_create (edge2);
960 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
db30281f
ML
961 }
962}
963
964template <typename T, typename V>
965inline bool
966fast_call_summary<T *, V>::is_ggc ()
967{
968 return is_same<V, va_gc>::value;
969}
970
971template <typename T>
972void
721bd210 973gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
db30281f
ML
974{
975}
976
977template <typename T>
978void
721bd210 979gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
db30281f
ML
980{
981}
982
983template <typename T>
984void
721bd210
ML
985gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
986 gt_pointer_operator op ATTRIBUTE_UNUSED,
987 void *cookie ATTRIBUTE_UNUSED)
db30281f
ML
988{
989}
990
991template <typename T>
992void
993gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary)
994{
995 ggc_test_and_set_mark (summary->m_vector);
996 gt_ggc_mx (&summary->m_vector);
997}
998
999template <typename T>
1000void
315d4248 1001gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
db30281f 1002{
315d4248 1003 gcc_unreachable ();
db30281f
ML
1004}
1005
1006template <typename T>
1007void
315d4248 1008gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
db30281f 1009{
315d4248 1010 gcc_unreachable ();
db30281f
ML
1011}
1012
4008290f 1013#endif /* GCC_SYMBOL_SUMMARY_H */