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