]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/symbol-summary.h
c++: Clear is_unbraced_* when parsing declaration_seq_opt [PR114917]
[thirdparty/gcc.git] / gcc / symbol-summary.h
1 /* Callgraph summary data structure.
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
3 Contributed by Martin Liska
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along 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
24 /* Base class for function_summary and fast_function_summary classes. */
25
26 template <class T>
27 class function_summary_base
28 {
29 public:
30 /* Default construction takes SYMTAB as an argument. */
31 function_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
32 m_symtab (symtab),
33 m_insertion_enabled (true),
34 m_allocator ("function summary" PASS_MEM_STAT)
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
58 protected:
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. */
64 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
65 : m_allocator.allocate () ;
66 }
67
68 /* Release an item that is stored within map. */
69 void release (T *item)
70 {
71 if (is_ggc ())
72 ggc_delete (item);
73 else
74 m_allocator.remove (item);
75 }
76
77 /* Unregister all call-graph hooks. */
78 void unregister_hooks ();
79
80 /* Internal summary insertion hook pointer. */
81 cgraph_node_hook_list *m_symtab_insertion_hook;
82 /* Internal summary removal hook pointer. */
83 cgraph_node_hook_list *m_symtab_removal_hook;
84 /* Internal summary duplication hook pointer. */
85 cgraph_2node_hook_list *m_symtab_duplication_hook;
86 /* Symbol table the summary is registered to. */
87 symbol_table *m_symtab;
88
89 /* Indicates if insertion hook is enabled. */
90 bool m_insertion_enabled;
91
92 private:
93 /* Return true when the summary uses GGC memory for allocation. */
94 virtual bool is_ggc () = 0;
95
96 /* Object allocator for heap allocation. */
97 object_allocator<T> m_allocator;
98 };
99
100 template <typename T>
101 void
102 function_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
109 /* We want to pass just pointer types as argument for function_summary
110 template class. */
111
112 template <class T>
113 class function_summary
114 {
115 private:
116 function_summary();
117 };
118
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
130 template <class T>
131 class GTY((user)) function_summary <T *>: public function_summary_base<T>
132 {
133 public:
134 /* Default construction takes SYMTAB as an argument. */
135 function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
136
137 /* Destructor. */
138 virtual ~function_summary ();
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
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)
151 {
152 bool existed;
153 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
154 if (!existed)
155 *v = this->allocate_new ();
156
157 return *v;
158 }
159
160 /* Getter for summary callgraph node pointer. */
161 T* get (cgraph_node *node) ATTRIBUTE_PURE
162 {
163 T **v = m_map.get (node->get_uid ());
164 return v == NULL ? NULL : *v;
165 }
166
167 /* Remove node from summary. */
168 using function_summary_base<T>::remove;
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);
176 this->release (*v);
177 }
178 }
179
180 /* Return true if a summary for the given NODE already exists. */
181 bool exists (cgraph_node *node)
182 {
183 return m_map.get (node->get_uid ()) != NULL;
184 }
185
186 /* Symbol insertion hook that is registered to symbol table. */
187 static void symtab_insertion (cgraph_node *node, void *data);
188
189 /* Symbol removal hook that is registered to symbol table. */
190 static void symtab_removal (cgraph_node *node, void *data);
191
192 /* Symbol duplication hook that is registered to symbol table. */
193 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
194 void *data);
195
196 protected:
197 /* Indication if we use ggc summary. */
198 bool m_ggc;
199
200 private:
201 /* Indication if we use ggc summary. */
202 virtual bool is_ggc ()
203 {
204 return m_ggc;
205 }
206
207 typedef int_hash <int, 0, -1> map_hash;
208
209 /* Main summary store, where summary ID is used as key. */
210 hash_map <map_hash, T *> m_map;
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
218 template <typename T>
219 function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
220 MEM_STAT_DECL):
221 function_summary_base<T> (symtab PASS_MEM_STAT), m_ggc (ggc),
222 m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT)
223 {
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);
233 }
234
235 template <typename T>
236 function_summary<T *>::~function_summary ()
237 {
238 this->unregister_hooks ();
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)
243 this->release ((*it).second);
244 }
245
246 template <typename T>
247 void
248 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
249 {
250 gcc_checking_assert (node->get_uid ());
251 function_summary *summary = (function_summary <T *> *) (data);
252
253 if (summary->m_insertion_enabled)
254 summary->insert (node, summary->get_create (node));
255 }
256
257 template <typename T>
258 void
259 function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
260 {
261 gcc_checking_assert (node->get_uid ());
262 function_summary *summary = (function_summary <T *> *) (data);
263 summary->remove (node);
264 }
265
266 template <typename T>
267 void
268 function_summary<T *>::symtab_duplication (cgraph_node *node,
269 cgraph_node *node2, void *data)
270 {
271 function_summary *summary = (function_summary <T *> *) (data);
272 T *v = summary->get (node);
273
274 if (v)
275 summary->duplicate (node, node2, v, summary->get_create (node2));
276 }
277
278 template <typename T>
279 void
280 gt_ggc_mx(function_summary<T *>* const &summary)
281 {
282 gcc_checking_assert (summary->m_ggc);
283 gt_ggc_mx (&summary->m_map);
284 }
285
286 template <typename T>
287 void
288 gt_pch_nx (function_summary<T *> *const &)
289 {
290 gcc_unreachable ();
291 }
292
293 template <typename T>
294 void
295 gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
296 {
297 gcc_unreachable ();
298 }
299
300 /* Help template from std c++11. */
301
302 template<typename T, typename U>
303 struct is_same
304 {
305 static const bool value = false;
306 };
307
308 template<typename T>
309 struct 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
317 template <class T, class V>
318 class fast_function_summary
319 {
320 private:
321 fast_function_summary ();
322 };
323
324 /* Function vector summary is a fast implementation of function_summary that
325 utilizes vector as primary storage of summaries. */
326
327 template <class T, class V>
328 class GTY((user)) fast_function_summary <T *, V>
329 : public function_summary_base<T>
330 {
331 public:
332 /* Default construction takes SYMTAB as an argument. */
333 fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
334
335 /* Destructor. */
336 virtual ~fast_function_summary ();
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 {
343 for (unsigned i = 0; i < m_vector->length (); i++)
344 if ((*m_vector[i]) != NULL)
345 f ((*m_vector)[i], a);
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;
370 }
371
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
402 private:
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
414 template <typename T, typename V>
415 fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab MEM_STAT_DECL):
416 function_summary_base<T> (symtab PASS_MEM_STAT), m_vector (NULL)
417 {
418 vec_alloc (m_vector, 13 PASS_MEM_STAT);
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
430 template <typename T, typename V>
431 fast_function_summary<T *, V>::~fast_function_summary ()
432 {
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]);
439 vec_free (m_vector);
440 }
441
442 template <typename T, typename V>
443 void
444 fast_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
453 template <typename T, typename V>
454 void
455 fast_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
464 template <typename T, typename V>
465 void
466 fast_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
480 template <typename T, typename V>
481 inline bool
482 fast_function_summary<T *, V>::is_ggc ()
483 {
484 return is_same<V, va_gc>::value;
485 }
486
487 template <typename T>
488 void
489 gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
490 {
491 }
492
493 template <typename T>
494 void
495 gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
496 {
497 }
498
499 template <typename T>
500 void
501 gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
502 void *)
503 {
504 }
505
506 template <typename T>
507 void
508 gt_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
514 template <typename T>
515 void
516 gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
517 {
518 gcc_unreachable ();
519 }
520
521 template <typename T>
522 void
523 gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
524 void *)
525 {
526 gcc_unreachable ();
527 }
528
529 /* Base class for call_summary and fast_call_summary classes. */
530
531 template <class T>
532 class call_summary_base
533 {
534 public:
535 /* Default construction takes SYMTAB as an argument. */
536 call_summary_base (symbol_table *symtab CXX_MEM_STAT_INFO):
537 m_symtab (symtab),
538 m_initialize_when_cloning (false),
539 m_allocator ("call summary" PASS_MEM_STAT)
540 {}
541
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
548 protected:
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. */
554 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
555 : m_allocator.allocate ();
556 }
557
558 /* Release an item that is stored within map. */
559 void release (T *item)
560 {
561 if (is_ggc ())
562 ggc_delete (item);
563 else
564 m_allocator.remove (item);
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;
579
580 private:
581 /* Return true when the summary uses GGC memory for allocation. */
582 virtual bool is_ggc () = 0;
583
584 /* Object allocator for heap allocation. */
585 object_allocator<T> m_allocator;
586 };
587
588 template <typename T>
589 void
590 call_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
599 template <class T>
600 class call_summary
601 {
602 private:
603 call_summary ();
604 };
605
606 /* Class to store auxiliary information about call graph edges. */
607
608 template <class T>
609 class GTY((user)) call_summary <T *>: public call_summary_base<T>
610 {
611 public:
612 /* Default construction takes SYMTAB as an argument. */
613 call_summary (symbol_table *symtab, bool ggc = false
614 CXX_MEM_STAT_INFO)
615 : call_summary_base<T> (symtab PASS_MEM_STAT), m_ggc (ggc),
616 m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT)
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. */
627 virtual ~call_summary ();
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 }
636
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)
640 {
641 bool existed;
642 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
643 if (!existed)
644 *v = this->allocate_new ();
645
646 return *v;
647 }
648
649 /* Getter for summary callgraph edge pointer. */
650 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
651 {
652 T **v = m_map.get (edge->get_uid ());
653 return v == NULL ? NULL : *v;
654 }
655
656 /* Remove edge from summary. */
657 using call_summary_base<T>::remove;
658 void remove (cgraph_edge *edge)
659 {
660 int uid = edge->get_uid ();
661 T **v = m_map.get (uid);
662 if (v)
663 {
664 m_map.remove (uid);
665 this->release (*v);
666 }
667 }
668
669 /* Return true if a summary for the given EDGE already exists. */
670 bool exists (cgraph_edge *edge)
671 {
672 return m_map.get (edge->get_uid ()) != NULL;
673 }
674
675 /* Symbol removal hook that is registered to symbol table. */
676 static void symtab_removal (cgraph_edge *edge, void *data);
677
678 /* Symbol duplication hook that is registered to symbol table. */
679 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
680 void *data);
681
682 protected:
683 /* Indication if we use ggc summary. */
684 bool m_ggc;
685
686 private:
687 /* Indication if we use ggc summary. */
688 virtual bool is_ggc ()
689 {
690 return m_ggc;
691 }
692
693 typedef int_hash <int, 0, -1> map_hash;
694
695 /* Main summary store, where summary ID is used as key. */
696 hash_map <map_hash, T *> m_map;
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
704 template <typename T>
705 call_summary<T *>::~call_summary ()
706 {
707 this->unregister_hooks ();
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)
712 this->release ((*it).second);
713 }
714
715 template <typename T>
716 void
717 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
718 {
719 call_summary *summary = (call_summary <T *> *) (data);
720 summary->remove (edge);
721 }
722
723 template <typename T>
724 void
725 call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
726 cgraph_edge *edge2, void *data)
727 {
728 call_summary *summary = (call_summary <T *> *) (data);
729 T *edge1_summary = NULL;
730
731 if (summary->m_initialize_when_cloning)
732 edge1_summary = summary->get_create (edge1);
733 else
734 edge1_summary = summary->get (edge1);
735
736 if (edge1_summary)
737 summary->duplicate (edge1, edge2, edge1_summary,
738 summary->get_create (edge2));
739 }
740
741 template <typename T>
742 void
743 gt_ggc_mx(call_summary<T *>* const &summary)
744 {
745 gcc_checking_assert (summary->m_ggc);
746 gt_ggc_mx (&summary->m_map);
747 }
748
749 template <typename T>
750 void
751 gt_pch_nx (call_summary<T *> *const &)
752 {
753 gcc_unreachable ();
754 }
755
756 template <typename T>
757 void
758 gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
759 {
760 gcc_unreachable ();
761 }
762
763 /* We want to pass just pointer types as argument for fast_call_summary
764 template class. */
765
766 template <class T, class V>
767 class fast_call_summary
768 {
769 private:
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
776 template <class T, class V>
777 class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
778 {
779 public:
780 /* Default construction takes SYMTAB as an argument. */
781 fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
782 : call_summary_base<T> (symtab PASS_MEM_STAT), m_vector (NULL)
783 {
784 vec_alloc (m_vector, 13 PASS_MEM_STAT);
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. */
794 virtual ~fast_call_summary ();
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)
803 f ((*m_vector)[i], a);
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
857 private:
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
869 template <typename T, typename V>
870 fast_call_summary<T *, V>::~fast_call_summary ()
871 {
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]);
878 vec_free (m_vector);
879 }
880
881 template <typename T, typename V>
882 void
883 fast_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
889 template <typename T, typename V>
890 void
891 fast_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
909 template <typename T, typename V>
910 inline bool
911 fast_call_summary<T *, V>::is_ggc ()
912 {
913 return is_same<V, va_gc>::value;
914 }
915
916 template <typename T>
917 void
918 gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
919 {
920 }
921
922 template <typename T>
923 void
924 gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
925 {
926 }
927
928 template <typename T>
929 void
930 gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
931 gt_pointer_operator op ATTRIBUTE_UNUSED,
932 void *cookie ATTRIBUTE_UNUSED)
933 {
934 }
935
936 template <typename T>
937 void
938 gt_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
944 template <typename T>
945 void
946 gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
947 {
948 gcc_unreachable ();
949 }
950
951 template <typename T>
952 void
953 gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
954 {
955 gcc_unreachable ();
956 }
957
958 #endif /* GCC_SYMBOL_SUMMARY_H */