Line data Source code
1 : /* Callgraph summary data structure.
2 : Copyright (C) 2014-2026 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 14457618 : class function_summary_base
28 : {
29 : public:
30 : /* Default construction takes SYMTAB as an argument. */
31 7324609 : 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 7324609 : m_symtab (symtab), m_symtab_insertion (symtab_insertion),
37 7324609 : m_symtab_removal (symtab_removal),
38 7324609 : m_symtab_duplication (symtab_duplication),
39 7324609 : m_symtab_insertion_hook (NULL), m_symtab_duplication_hook (NULL),
40 7324609 : m_allocator ("function summary" PASS_MEM_STAT)
41 : {
42 7324609 : enable_insertion_hook ();
43 : m_symtab_removal_hook
44 7324609 : = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this);
45 7324609 : enable_duplication_hook ();
46 7324609 : }
47 :
48 : /* Basic implementation of insert operation. */
49 0 : virtual void insert (cgraph_node *, T *)
50 : {
51 : /* In most cases, it makes no sense to create summaries without
52 : initializing them. */
53 0 : gcc_unreachable ();
54 : }
55 :
56 : /* Basic implementation of removal operation. */
57 0 : virtual void remove (cgraph_node *, T *) {}
58 :
59 : /* Basic implementation of duplication operation. */
60 0 : virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *)
61 : {
62 : /* It makes no sense to not copy anything during duplication. */
63 0 : gcc_unreachable ();
64 : }
65 :
66 : /* Enable insertion hook invocation. */
67 7568778 : void enable_insertion_hook ()
68 : {
69 7568778 : if (m_symtab_insertion_hook == NULL)
70 : m_symtab_insertion_hook
71 7568778 : = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
72 7568778 : }
73 :
74 : /* Disable insertion hook invocation. */
75 13791836 : void disable_insertion_hook ()
76 : {
77 13791836 : if (m_symtab_insertion_hook != NULL)
78 : {
79 7559300 : m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
80 7559300 : m_symtab_insertion_hook = NULL;
81 : }
82 13791836 : }
83 :
84 : /* Enable duplication hook invocation. */
85 7324609 : void enable_duplication_hook ()
86 : {
87 7324609 : if (m_symtab_duplication_hook == NULL)
88 : m_symtab_duplication_hook
89 7324609 : = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this);
90 7324609 : }
91 :
92 : /* Enable duplication hook invocation. */
93 7480885 : void disable_duplication_hook ()
94 : {
95 7480885 : if (m_symtab_duplication_hook != NULL)
96 : {
97 7228821 : m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
98 7228821 : m_symtab_duplication_hook = NULL;
99 : }
100 7480885 : }
101 :
102 : protected:
103 : /* Allocates new data that are stored within map. */
104 41203370 : 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. */
108 68653174 : return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
109 13753566 : : m_allocator.allocate () ;
110 : }
111 :
112 : /* Release an item that is stored within map. */
113 40959192 : void release (T *item)
114 : {
115 40959192 : if (is_ggc ())
116 27247451 : ggc_delete (item);
117 : else
118 13711741 : m_allocator.remove (item);
119 40959192 : }
120 :
121 : /* Unregister all call-graph hooks. */
122 : void unregister_hooks ();
123 :
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 :
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;
140 :
141 : private:
142 : /* Return true when the summary uses GGC memory for allocation. */
143 : virtual bool is_ggc () = 0;
144 :
145 : /* Object allocator for heap allocation. */
146 : object_allocator<T> m_allocator;
147 : };
148 :
149 : template <typename T>
150 : void
151 7228809 : function_summary_base<T>::unregister_hooks ()
152 : {
153 7228809 : disable_insertion_hook ();
154 7228809 : m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
155 7228809 : disable_duplication_hook ();
156 7228809 : }
157 :
158 : /* We want to pass just pointer types as argument for function_summary
159 : template class. */
160 :
161 : template <class T>
162 : class function_summary
163 : {
164 : private:
165 : function_summary();
166 : };
167 :
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 :
179 : template <class T>
180 : class GTY((user)) function_summary <T *>: public function_summary_base<T>
181 : {
182 : public:
183 : /* Default construction takes SYMTAB as an argument. */
184 : function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
185 :
186 : /* Destructor. */
187 : virtual ~function_summary ();
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 : {
194 : m_map.template traverse <f> (a);
195 : }
196 :
197 : /* Getter for summary callgraph node pointer. If a summary for a node
198 : does not exist it will be created. */
199 19221196 : T* get_create (cgraph_node *node)
200 : {
201 : bool existed;
202 19221196 : T **v = &m_map.get_or_insert (node->get_uid (), &existed);
203 19221196 : if (!existed)
204 9892358 : *v = this->allocate_new ();
205 :
206 19221196 : return *v;
207 : }
208 :
209 : /* Getter for summary callgraph node pointer. */
210 130228923 : T* get (cgraph_node *node) ATTRIBUTE_PURE
211 : {
212 130228923 : T **v = m_map.get (node->get_uid ());
213 130228923 : return v == NULL ? NULL : *v;
214 : }
215 :
216 : /* Remove node from summary. */
217 : using function_summary_base<T>::remove;
218 10562857 : void remove (cgraph_node *node)
219 : {
220 10562857 : int uid = node->get_uid ();
221 10562857 : T **v = m_map.get (uid);
222 10562857 : if (v)
223 : {
224 2345122 : m_map.remove (uid);
225 2345122 : this->release (*v);
226 : }
227 10562857 : }
228 :
229 : /* Return true if a summary for the given NODE already exists. */
230 : bool exists (cgraph_node *node)
231 : {
232 : return m_map.get (node->get_uid ()) != NULL;
233 : }
234 :
235 : /* Symbol insertion hook that is registered to symbol table. */
236 : static void symtab_insertion (cgraph_node *node, void *data);
237 :
238 : /* Symbol removal hook that is registered to symbol table. */
239 : static void symtab_removal (cgraph_node *node, void *data);
240 :
241 : /* Symbol duplication hook that is registered to symbol table. */
242 : static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
243 : void *data);
244 :
245 : protected:
246 : /* Indication if we use ggc summary. */
247 : bool m_ggc;
248 :
249 : private:
250 : /* Indication if we use ggc summary. */
251 19583046 : bool is_ggc () final override
252 : {
253 19583046 : return m_ggc;
254 : }
255 :
256 : typedef int_hash <int, 0, -1> map_hash;
257 :
258 : /* Main summary store, where summary ID is used as key. */
259 : hash_map <map_hash, T *> m_map;
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 :
267 : template <typename T>
268 5388841 : function_summary<T *>::function_summary (symbol_table *symtab, bool ggc
269 : MEM_STAT_DECL):
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 5388841 : m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
275 :
276 : template <typename T>
277 5326321 : function_summary<T *>::~function_summary ()
278 : {
279 5302740 : this->unregister_hooks ();
280 :
281 : /* Release all summaries. */
282 : typedef typename hash_map <map_hash, T *>::iterator map_iterator;
283 19993872 : for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
284 7345566 : this->release ((*it).second);
285 10629061 : }
286 :
287 : template <typename T>
288 : void
289 18049 : function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
290 : {
291 18049 : gcc_checking_assert (node->get_uid ());
292 18049 : function_summary *summary = (function_summary <T *> *) (data);
293 18049 : summary->insert (node, summary->get_create (node));
294 18049 : }
295 :
296 : template <typename T>
297 : void
298 8983260 : function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
299 : {
300 8983260 : gcc_checking_assert (node->get_uid ());
301 8983260 : function_summary *summary = (function_summary <T *> *) (data);
302 8983260 : summary->remove (node);
303 8983260 : }
304 :
305 : template <typename T>
306 : void
307 5159892 : function_summary<T *>::symtab_duplication (cgraph_node *node,
308 : cgraph_node *node2, void *data)
309 : {
310 5159892 : function_summary *summary = (function_summary <T *> *) (data);
311 5159892 : T *v = summary->get (node);
312 :
313 5159892 : if (v)
314 1497372 : summary->duplicate (node, node2, v, summary->get_create (node2));
315 5159892 : }
316 :
317 : template <typename T>
318 : void
319 514565 : gt_ggc_mx(function_summary<T *>* const &summary)
320 : {
321 514565 : gcc_checking_assert (summary->m_ggc);
322 514565 : gt_ggc_mx (&summary->m_map);
323 514565 : }
324 :
325 : template <typename T>
326 : void
327 0 : gt_pch_nx (function_summary<T *> *const &)
328 : {
329 0 : gcc_unreachable ();
330 : }
331 :
332 : template <typename T>
333 : void
334 0 : gt_pch_nx (function_summary<T *> *const &, gt_pointer_operator, void *)
335 : {
336 0 : gcc_unreachable ();
337 : }
338 :
339 : /* Help template from std c++11. */
340 :
341 : template<typename T, typename U>
342 : struct is_same
343 : {
344 : static const bool value = false;
345 : };
346 :
347 : template<typename T>
348 : struct 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 :
356 : template <class T, class V>
357 : class fast_function_summary
358 : {
359 : private:
360 : fast_function_summary ();
361 : };
362 :
363 : /* Function vector summary is a fast implementation of function_summary that
364 : utilizes vector as primary storage of summaries. */
365 :
366 : template <class T, class V>
367 : class GTY((user)) fast_function_summary <T *, V>
368 : : public function_summary_base<T>
369 : {
370 : public:
371 : /* Default construction takes SYMTAB as an argument. */
372 : fast_function_summary (symbol_table *symtab CXX_MEM_STAT_INFO);
373 :
374 : /* Destructor. */
375 : virtual ~fast_function_summary ();
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 : {
382 : for (unsigned i = 0; i < m_vector->length (); i++)
383 : if ((*m_vector[i]) != NULL)
384 : f ((*m_vector)[i], a);
385 : }
386 :
387 : /* Getter for summary callgraph node pointer. If a summary for a node
388 : does not exist it will be created. */
389 53339272 : T* get_create (cgraph_node *node)
390 : {
391 53339272 : int id = node->get_summary_id ();
392 53339272 : if (id == -1)
393 6143462 : id = this->m_symtab->assign_summary_id (node);
394 :
395 53339272 : if ((unsigned int)id >= m_vector->length ())
396 10191020 : vec_safe_grow_cleared (m_vector,
397 10191020 : this->m_symtab->cgraph_max_summary_id);
398 :
399 53339272 : if ((*m_vector)[id] == NULL)
400 31311012 : (*m_vector)[id] = this->allocate_new ();
401 :
402 53339272 : return (*m_vector)[id];
403 : }
404 :
405 : /* Getter for summary callgraph node pointer. */
406 460396489 : T* get (cgraph_node *node) ATTRIBUTE_PURE
407 : {
408 460396489 : return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
409 : }
410 :
411 : using function_summary_base<T>::remove;
412 28365929 : void remove (cgraph_node *node)
413 : {
414 28365929 : if (exists (node))
415 : {
416 17232126 : int id = node->get_summary_id ();
417 17232126 : this->release ((*m_vector)[id]);
418 17232126 : (*m_vector)[id] = NULL;
419 : }
420 28365929 : }
421 :
422 : /* Return true if a summary for the given NODE already exists. */
423 507610049 : bool exists (cgraph_node *node)
424 : {
425 507610049 : int id = node->get_summary_id ();
426 : return (id != -1
427 502967657 : && (unsigned int)id < m_vector->length ()
428 998593735 : && (*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 :
441 : private:
442 : bool is_ggc () final override;
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 :
453 : template <typename T, typename V>
454 1935768 : fast_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 1935768 : PASS_MEM_STAT), m_vector (NULL)
461 : {
462 1935768 : vec_alloc (m_vector, 13 PASS_MEM_STAT);
463 1935768 : }
464 :
465 : template <typename T, typename V>
466 2158345 : fast_function_summary<T *, V>::~fast_function_summary ()
467 : {
468 1926069 : this->unregister_hooks ();
469 :
470 : /* Release all summaries. */
471 24836483 : for (unsigned i = 0; i < m_vector->length (); i++)
472 22910414 : if ((*m_vector)[i] != NULL)
473 14036378 : this->release ((*m_vector)[i]);
474 1926069 : vec_free (m_vector);
475 4084414 : }
476 :
477 : template <typename T, typename V>
478 : void
479 127989 : fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
480 : {
481 127989 : gcc_checking_assert (node->get_uid ());
482 127989 : fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
483 127989 : summary->insert (node, summary->get_create (node));
484 127989 : }
485 :
486 : template <typename T, typename V>
487 : void
488 13321927 : fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
489 : {
490 13321927 : gcc_checking_assert (node->get_uid ());
491 13321927 : fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
492 :
493 13321927 : if (summary->exists (node))
494 4357383 : summary->remove (node);
495 13321927 : }
496 :
497 : template <typename T, typename V>
498 : void
499 11431238 : fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
500 : cgraph_node *node2,
501 : void *data)
502 : {
503 11431238 : fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
504 11431238 : T *v = summary->get (node);
505 :
506 11431238 : if (v)
507 : {
508 9670710 : T *duplicate = summary->get_create (node2);
509 9670710 : summary->duplicate (node, node2, v, duplicate);
510 : }
511 11431238 : }
512 :
513 : template <typename T, typename V>
514 : inline bool
515 62579516 : fast_function_summary<T *, V>::is_ggc ()
516 : {
517 62579516 : return is_same<V, va_gc>::value;
518 : }
519 :
520 : template <typename T>
521 : void
522 : gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
523 : {
524 : }
525 :
526 : template <typename T>
527 : void
528 : gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
529 : {
530 : }
531 :
532 : template <typename T>
533 : void
534 : gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
535 : void *)
536 : {
537 : }
538 :
539 : template <typename T>
540 : void
541 584199 : gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
542 : {
543 584199 : ggc_test_and_set_mark (summary->m_vector);
544 584199 : gt_ggc_mx (summary->m_vector);
545 584199 : }
546 :
547 : template <typename T>
548 : void
549 0 : gt_pch_nx (fast_function_summary<T *, va_gc> *const &)
550 : {
551 0 : gcc_unreachable ();
552 : }
553 :
554 : template <typename T>
555 : void
556 0 : gt_pch_nx (fast_function_summary<T *, va_gc> *const &, gt_pointer_operator,
557 : void *)
558 : {
559 0 : gcc_unreachable ();
560 : }
561 :
562 : /* Base class for call_summary and fast_call_summary classes. */
563 :
564 : template <class T>
565 3338494 : class call_summary_base
566 : {
567 : public:
568 : /* Default construction takes SYMTAB as an argument. */
569 1669261 : call_summary_base (symbol_table *symtab, cgraph_edge_hook symtab_removal,
570 : cgraph_2edge_hook symtab_duplication CXX_MEM_STAT_INFO):
571 1669261 : m_symtab (symtab), m_symtab_removal (symtab_removal),
572 1669261 : m_symtab_duplication (symtab_duplication), m_symtab_duplication_hook (NULL),
573 1669261 : m_initialize_when_cloning (false),
574 1669261 : m_allocator ("call summary" PASS_MEM_STAT)
575 : {
576 : m_symtab_removal_hook
577 1669261 : = m_symtab->add_edge_removal_hook (m_symtab_removal, this);
578 1669261 : enable_duplication_hook ();
579 1669261 : }
580 :
581 : /* Basic implementation of removal operation. */
582 0 : virtual void remove (cgraph_edge *, T *) {}
583 :
584 : /* Basic implementation of duplication operation. */
585 0 : virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *)
586 : {
587 0 : gcc_unreachable ();
588 : }
589 :
590 : /* Enable duplication hook invocation. */
591 1669261 : void enable_duplication_hook ()
592 : {
593 1669261 : if (m_symtab_duplication_hook == NULL)
594 : m_symtab_duplication_hook
595 1669261 : = m_symtab->add_edge_duplication_hook (m_symtab_duplication,
596 : this);
597 1669261 : }
598 :
599 : /* Enable duplication hook invocation. */
600 1901523 : void disable_duplication_hook ()
601 : {
602 1901523 : if (m_symtab_duplication_hook != NULL)
603 : {
604 1669247 : m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
605 1669247 : m_symtab_duplication_hook = NULL;
606 : }
607 1901523 : }
608 :
609 : protected:
610 : /* Allocates new data that are stored within map. */
611 45676096 : 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. */
615 48610229 : return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
616 41279823 : : m_allocator.allocate ();
617 : }
618 :
619 : /* Release an item that is stored within map. */
620 45676096 : void release (T *item)
621 : {
622 45676096 : if (is_ggc ())
623 4396273 : ggc_delete (item);
624 : else
625 41279823 : m_allocator.remove (item);
626 45676096 : }
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 :
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 :
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;
645 :
646 : private:
647 : /* Return true when the summary uses GGC memory for allocation. */
648 : virtual bool is_ggc () = 0;
649 :
650 : /* Object allocator for heap allocation. */
651 : object_allocator<T> m_allocator;
652 : };
653 :
654 : template <typename T>
655 : void
656 1669247 : call_summary_base<T>::unregister_hooks ()
657 : {
658 1669247 : m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
659 1669247 : disable_duplication_hook ();
660 1669247 : }
661 :
662 : /* An impossible class templated by non-pointers so, which makes sure that only
663 : summaries gathering pointers can be created. */
664 :
665 : template <class T>
666 : class call_summary
667 : {
668 : private:
669 : call_summary ();
670 : };
671 :
672 : /* Class to store auxiliary information about call graph edges. */
673 :
674 : template <class T>
675 : class GTY((user)) call_summary <T *>: public call_summary_base<T>
676 : {
677 : public:
678 : /* Default construction takes SYMTAB as an argument. */
679 978491 : call_summary (symbol_table *symtab, bool ggc = false
680 : CXX_MEM_STAT_INFO)
681 : : call_summary_base<T> (symtab, call_summary::symtab_removal,
682 : call_summary::symtab_duplication PASS_MEM_STAT),
683 978491 : m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
684 :
685 : /* Destructor. */
686 : virtual ~call_summary ();
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 : {
693 : m_map.template traverse <f> (a);
694 : }
695 :
696 : /* Getter for summary callgraph edge pointer.
697 : If a summary for an edge does not exist, it will be created. */
698 15697072 : T* get_create (cgraph_edge *edge)
699 : {
700 : bool existed;
701 15697072 : T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
702 15697072 : if (!existed)
703 12495329 : *v = this->allocate_new ();
704 :
705 15697072 : return *v;
706 : }
707 :
708 : /* Getter for summary callgraph edge pointer. */
709 58685622 : T* get (cgraph_edge *edge) ATTRIBUTE_PURE
710 : {
711 58685622 : T **v = m_map.get (edge->get_uid ());
712 58685622 : return v == NULL ? NULL : *v;
713 : }
714 :
715 : /* Remove edge from summary. */
716 : using call_summary_base<T>::remove;
717 11332851 : void remove (cgraph_edge *edge)
718 : {
719 11332851 : int uid = edge->get_uid ();
720 11332851 : T **v = m_map.get (uid);
721 11332851 : if (v)
722 : {
723 2222827 : m_map.remove (uid);
724 2222827 : this->release (*v);
725 : }
726 11332851 : }
727 :
728 : /* Return true if a summary for the given EDGE already exists. */
729 1212 : bool exists (cgraph_edge *edge)
730 : {
731 1212 : return m_map.get (edge->get_uid ()) != NULL;
732 : }
733 :
734 : /* Symbol removal hook that is registered to symbol table. */
735 : static void symtab_removal (cgraph_edge *edge, void *data);
736 :
737 : /* Symbol duplication hook that is registered to symbol table. */
738 : static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
739 : void *data);
740 :
741 : protected:
742 : /* Indication if we use ggc summary. */
743 : bool m_ggc;
744 :
745 : private:
746 : /* Indication if we use ggc summary. */
747 24990658 : bool is_ggc () final override
748 : {
749 24990658 : return m_ggc;
750 : }
751 :
752 : typedef int_hash <int, 0, -1> map_hash;
753 :
754 : /* Main summary store, where summary ID is used as key. */
755 : hash_map <map_hash, T *> m_map;
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 :
763 : template <typename T>
764 978482 : call_summary<T *>::~call_summary ()
765 : {
766 978482 : this->unregister_hooks ();
767 :
768 : /* Release all summaries. */
769 : typedef typename hash_map <map_hash, T *>::iterator map_iterator;
770 21523486 : for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
771 10272502 : this->release ((*it).second);
772 1956964 : }
773 :
774 : template <typename T>
775 : void
776 6169908 : call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
777 : {
778 6169908 : call_summary *summary = (call_summary <T *> *) (data);
779 6169908 : summary->remove (edge);
780 6169908 : }
781 :
782 : template <typename T>
783 : void
784 9766549 : call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
785 : cgraph_edge *edge2, void *data)
786 : {
787 9766549 : call_summary *summary = (call_summary <T *> *) (data);
788 9766549 : T *edge1_summary = NULL;
789 :
790 9766549 : if (summary->m_initialize_when_cloning)
791 199713 : edge1_summary = summary->get_create (edge1);
792 : else
793 9566836 : edge1_summary = summary->get (edge1);
794 :
795 9766549 : if (edge1_summary)
796 2741079 : summary->duplicate (edge1, edge2, edge1_summary,
797 : summary->get_create (edge2));
798 9766549 : }
799 :
800 : template <typename T>
801 : void
802 7704 : gt_ggc_mx(call_summary<T *>* const &summary)
803 : {
804 7704 : gcc_checking_assert (summary->m_ggc);
805 7704 : gt_ggc_mx (&summary->m_map);
806 7704 : }
807 :
808 : template <typename T>
809 : void
810 0 : gt_pch_nx (call_summary<T *> *const &)
811 : {
812 0 : gcc_unreachable ();
813 : }
814 :
815 : template <typename T>
816 : void
817 0 : gt_pch_nx (call_summary<T *> *const &, gt_pointer_operator, void *)
818 : {
819 0 : gcc_unreachable ();
820 : }
821 :
822 : /* We want to pass just pointer types as argument for fast_call_summary
823 : template class. */
824 :
825 : template <class T, class V>
826 : class fast_call_summary
827 : {
828 : private:
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 :
835 : template <class T, class V>
836 : class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
837 : {
838 : public:
839 : /* Default construction takes SYMTAB as an argument. */
840 690770 : fast_call_summary (symbol_table *symtab CXX_MEM_STAT_INFO)
841 : : call_summary_base<T> (symtab, fast_call_summary::symtab_removal,
842 : fast_call_summary::symtab_duplication PASS_MEM_STAT),
843 690770 : m_vector (NULL)
844 : {
845 690770 : vec_alloc (m_vector, 13 PASS_MEM_STAT);
846 690770 : }
847 :
848 : /* Destructor. */
849 : virtual ~fast_call_summary ();
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)
858 : f ((*m_vector)[i], a);
859 : }
860 :
861 : /* Getter for summary callgraph edge pointer.
862 : If a summary for an edge does not exist, it will be created. */
863 37414195 : T* get_create (cgraph_edge *edge)
864 : {
865 37414195 : int id = edge->get_summary_id ();
866 37414195 : if (id == -1)
867 21276763 : id = this->m_symtab->assign_summary_id (edge);
868 :
869 37414195 : if ((unsigned)id >= m_vector->length ())
870 9474662 : vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
871 :
872 37414195 : if ((*m_vector)[id] == NULL)
873 33180767 : (*m_vector)[id] = this->allocate_new ();
874 :
875 37414195 : return (*m_vector)[id];
876 : }
877 :
878 : /* Getter for summary callgraph edge pointer. */
879 668277665 : T* get (cgraph_edge *edge) ATTRIBUTE_PURE
880 : {
881 668277665 : 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 56201930 : void remove (cgraph_edge *edge)
887 : {
888 56201930 : if (exists (edge))
889 : {
890 19048049 : int id = edge->get_summary_id ();
891 19048049 : this->release ((*m_vector)[id]);
892 19048049 : (*m_vector)[id] = NULL;
893 : }
894 56201930 : }
895 :
896 : /* Return true if a summary for the given EDGE already exists. */
897 724479595 : bool exists (cgraph_edge *edge)
898 : {
899 724479595 : int id = edge->get_summary_id ();
900 : return (id != -1
901 772652480 : && (unsigned)id < m_vector->length ()
902 1408316213 : && (*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 :
912 : private:
913 : bool is_ggc () final override;
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 :
924 : template <typename T, typename V>
925 923041 : fast_call_summary<T *, V>::~fast_call_summary ()
926 : {
927 690765 : this->unregister_hooks ();
928 :
929 : /* Release all summaries. */
930 21959693 : for (unsigned i = 0; i < m_vector->length (); i++)
931 21268928 : if ((*m_vector)[i] != NULL)
932 14132718 : this->release ((*m_vector)[i]);
933 690765 : vec_free (m_vector);
934 1613806 : }
935 :
936 : template <typename T, typename V>
937 : void
938 22047647 : fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
939 : {
940 22047647 : fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
941 22047647 : summary->remove (edge);
942 22047647 : }
943 :
944 : template <typename T, typename V>
945 : void
946 4314504 : fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
947 : cgraph_edge *edge2, void *data)
948 : {
949 4314504 : fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
950 4314504 : T *edge1_summary = NULL;
951 :
952 4314504 : if (summary->m_initialize_when_cloning)
953 0 : edge1_summary = summary->get_create (edge1);
954 : else
955 4314504 : edge1_summary = summary->get (edge1);
956 :
957 4314504 : if (edge1_summary)
958 : {
959 3703340 : T *duplicate = summary->get_create (edge2);
960 3703340 : summary->duplicate (edge1, edge2, edge1_summary, duplicate);
961 : }
962 4314504 : }
963 :
964 : template <typename T, typename V>
965 : inline bool
966 66361534 : fast_call_summary<T *, V>::is_ggc ()
967 : {
968 66361534 : return is_same<V, va_gc>::value;
969 : }
970 :
971 : template <typename T>
972 : void
973 : gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
974 : {
975 : }
976 :
977 : template <typename T>
978 : void
979 : gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary ATTRIBUTE_UNUSED)
980 : {
981 : }
982 :
983 : template <typename T>
984 : void
985 : gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary ATTRIBUTE_UNUSED,
986 : gt_pointer_operator op ATTRIBUTE_UNUSED,
987 : void *cookie ATTRIBUTE_UNUSED)
988 : {
989 : }
990 :
991 : template <typename T>
992 : void
993 : gt_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 :
999 : template <typename T>
1000 : void
1001 : gt_pch_nx (fast_call_summary<T *, va_gc> *const &)
1002 : {
1003 : gcc_unreachable ();
1004 : }
1005 :
1006 : template <typename T>
1007 : void
1008 : gt_pch_nx (fast_call_summary<T *, va_gc> *const &, gt_pointer_operator, void *)
1009 : {
1010 : gcc_unreachable ();
1011 : }
1012 :
1013 : #endif /* GCC_SYMBOL_SUMMARY_H */
|