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