Branch data Line data Source code
1 : : /* Callgraph summary data structure.
2 : : Copyright (C) 2014-2024 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 : 13645720 : class function_summary_base
28 : : {
29 : : public:
30 : : /* Default construction takes SYMTAB as an argument. */
31 : 6909525 : 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 : 6909525 : m_symtab (symtab), m_symtab_insertion (symtab_insertion),
37 : 6909525 : m_symtab_removal (symtab_removal),
38 : 6909525 : m_symtab_duplication (symtab_duplication),
39 : 6909525 : m_symtab_insertion_hook (NULL), m_symtab_duplication_hook (NULL),
40 : 6909525 : m_allocator ("function summary" PASS_MEM_STAT)
41 : : {
42 : 6909525 : enable_insertion_hook ();
43 : : m_symtab_removal_hook
44 : 6909525 : = m_symtab->add_cgraph_removal_hook (m_symtab_removal, this);
45 : 6909525 : enable_duplication_hook ();
46 : 6909525 : }
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 : 7147017 : void enable_insertion_hook ()
68 : : {
69 : 7147017 : if (m_symtab_insertion_hook == NULL)
70 : : m_symtab_insertion_hook
71 : 7147017 : = m_symtab->add_cgraph_insertion_hook (m_symtab_insertion, this);
72 : 7147017 : }
73 : :
74 : : /* Disable insertion hook invocation. */
75 : 12991442 : void disable_insertion_hook ()
76 : : {
77 : 12991442 : if (m_symtab_insertion_hook != NULL)
78 : : {
79 : 7137958 : m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
80 : 7137958 : m_symtab_insertion_hook = NULL;
81 : : }
82 : 12991442 : }
83 : :
84 : : /* Enable duplication hook invocation. */
85 : 6909525 : void enable_duplication_hook ()
86 : : {
87 : 6909525 : if (m_symtab_duplication_hook == NULL)
88 : : m_symtab_duplication_hook
89 : 6909525 : = m_symtab->add_cgraph_duplication_hook (m_symtab_duplication, this);
90 : 6909525 : }
91 : :
92 : : /* Enable duplication hook invocation. */
93 : 7065279 : void disable_duplication_hook ()
94 : : {
95 : 7065279 : if (m_symtab_duplication_hook != NULL)
96 : : {
97 : 6822872 : m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
98 : 6822872 : m_symtab_duplication_hook = NULL;
99 : : }
100 : 7065279 : }
101 : :
102 : : protected:
103 : : /* Allocates new data that are stored within map. */
104 : 37511951 : 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 : 62593552 : return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
109 : 12430350 : : m_allocator.allocate () ;
110 : : }
111 : :
112 : : /* Release an item that is stored within map. */
113 : 37295300 : void release (T *item)
114 : : {
115 : 37295300 : if (is_ggc ())
116 : 24905588 : ggc_delete (item);
117 : : else
118 : 12389712 : m_allocator.remove (item);
119 : 37295300 : }
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 : 6822860 : function_summary_base<T>::unregister_hooks ()
152 : : {
153 : 6822860 : disable_insertion_hook ();
154 : 6822860 : m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
155 : 6822860 : disable_duplication_hook ();
156 : 6822860 : }
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 : 17789599 : T* get_create (cgraph_node *node)
200 : : {
201 : : bool existed;
202 : 17789599 : T **v = &m_map.get_or_insert (node->get_uid (), &existed);
203 : 17789599 : if (!existed)
204 : 9029665 : *v = this->allocate_new ();
205 : :
206 : 17789599 : return *v;
207 : : }
208 : :
209 : : /* Getter for summary callgraph node pointer. */
210 : 101281575 : T* get (cgraph_node *node) ATTRIBUTE_PURE
211 : : {
212 : 101281575 : T **v = m_map.get (node->get_uid ());
213 : 101281575 : return v == NULL ? NULL : *v;
214 : : }
215 : :
216 : : /* Remove node from summary. */
217 : : using function_summary_base<T>::remove;
218 : 9122158 : void remove (cgraph_node *node)
219 : : {
220 : 9122158 : int uid = node->get_uid ();
221 : 9122158 : T **v = m_map.get (uid);
222 : 9122158 : if (v)
223 : : {
224 : 2002657 : m_map.remove (uid);
225 : 2002657 : this->release (*v);
226 : : }
227 : 9122158 : }
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 : 17883912 : bool is_ggc () final override
252 : : {
253 : 17883912 : 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 : 5028754 : 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 : 5028754 : m_ggc (ggc), m_map (13, ggc, true, GATHER_STATISTICS PASS_MEM_STAT) {}
275 : :
276 : : template <typename T>
277 : 4971616 : function_summary<T *>::~function_summary ()
278 : : {
279 : 4951356 : this->unregister_hooks ();
280 : :
281 : : /* Release all summaries. */
282 : : typedef typename hash_map <map_hash, T *>::iterator map_iterator;
283 : 18654536 : for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
284 : 6851590 : this->release ((*it).second);
285 : 9922972 : }
286 : :
287 : : template <typename T>
288 : : void
289 : 17069 : function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
290 : : {
291 : 17069 : gcc_checking_assert (node->get_uid ());
292 : 17069 : function_summary *summary = (function_summary <T *> *) (data);
293 : 17069 : summary->insert (node, summary->get_create (node));
294 : 17069 : }
295 : :
296 : : template <typename T>
297 : : void
298 : 7732368 : function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
299 : : {
300 : 7732368 : gcc_checking_assert (node->get_uid ());
301 : 7732368 : function_summary *summary = (function_summary <T *> *) (data);
302 : 7732368 : summary->remove (node);
303 : 7732368 : }
304 : :
305 : : template <typename T>
306 : : void
307 : 4386780 : function_summary<T *>::symtab_duplication (cgraph_node *node,
308 : : cgraph_node *node2, void *data)
309 : : {
310 : 4386780 : function_summary *summary = (function_summary <T *> *) (data);
311 : 4386780 : T *v = summary->get (node);
312 : :
313 : 4386780 : if (v)
314 : 1245413 : summary->duplicate (node, node2, v, summary->get_create (node2));
315 : 4386780 : }
316 : :
317 : : template <typename T>
318 : : void
319 : 497591 : gt_ggc_mx(function_summary<T *>* const &summary)
320 : : {
321 : 497591 : gcc_checking_assert (summary->m_ggc);
322 : 497591 : gt_ggc_mx (&summary->m_map);
323 : 497591 : }
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 : 48356622 : T* get_create (cgraph_node *node)
390 : : {
391 : 48356622 : int id = node->get_summary_id ();
392 : 48356622 : if (id == -1)
393 : 5500729 : id = this->m_symtab->assign_summary_id (node);
394 : :
395 : 48356622 : if ((unsigned int)id >= m_vector->length ())
396 : 9385801 : vec_safe_grow_cleared (m_vector,
397 : 9385801 : this->m_symtab->cgraph_max_summary_id);
398 : :
399 : 48356622 : if ((*m_vector)[id] == NULL)
400 : 28482286 : (*m_vector)[id] = this->allocate_new ();
401 : :
402 : 48356622 : return (*m_vector)[id];
403 : : }
404 : :
405 : : /* Getter for summary callgraph node pointer. */
406 : 404283972 : T* get (cgraph_node *node) ATTRIBUTE_PURE
407 : : {
408 : 404283972 : return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL;
409 : : }
410 : :
411 : : using function_summary_base<T>::remove;
412 : 25653207 : void remove (cgraph_node *node)
413 : : {
414 : 25653207 : if (exists (node))
415 : : {
416 : 15446091 : int id = node->get_summary_id ();
417 : 15446091 : this->release ((*m_vector)[id]);
418 : 15446091 : (*m_vector)[id] = NULL;
419 : : }
420 : 25653207 : }
421 : :
422 : : /* Return true if a summary for the given NODE already exists. */
423 : 446762700 : bool exists (cgraph_node *node)
424 : : {
425 : 446762700 : int id = node->get_summary_id ();
426 : : return (id != -1
427 : 441864667 : && (unsigned int)id < m_vector->length ()
428 : 878408732 : && (*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 : 1880771 : 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 : 1880771 : PASS_MEM_STAT), m_vector (NULL)
461 : : {
462 : 1880771 : vec_alloc (m_vector, 13 PASS_MEM_STAT);
463 : 1880771 : }
464 : :
465 : : template <typename T, typename V>
466 : 2095472 : fast_function_summary<T *, V>::~fast_function_summary ()
467 : : {
468 : 1871504 : this->unregister_hooks ();
469 : :
470 : : /* Release all summaries. */
471 : 23020150 : for (unsigned i = 0; i < m_vector->length (); i++)
472 : 21148646 : if ((*m_vector)[i] != NULL)
473 : 12994962 : this->release ((*m_vector)[i]);
474 : 1871504 : vec_free (m_vector);
475 : 3966976 : }
476 : :
477 : : template <typename T, typename V>
478 : : void
479 : 120061 : fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
480 : : {
481 : 120061 : gcc_checking_assert (node->get_uid ());
482 : 120061 : fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
483 : 120061 : summary->insert (node, summary->get_create (node));
484 : 120061 : }
485 : :
486 : : template <typename T, typename V>
487 : : void
488 : 11861529 : fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
489 : : {
490 : 11861529 : gcc_checking_assert (node->get_uid ());
491 : 11861529 : fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
492 : :
493 : 11861529 : if (summary->exists (node))
494 : 3891061 : summary->remove (node);
495 : 11861529 : }
496 : :
497 : : template <typename T, typename V>
498 : : void
499 : 9760258 : fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
500 : : cgraph_node *node2,
501 : : void *data)
502 : : {
503 : 9760258 : fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
504 : 9760258 : T *v = summary->get (node);
505 : :
506 : 9760258 : if (v)
507 : : {
508 : 8268490 : T *duplicate = summary->get_create (node2);
509 : 8268490 : summary->duplicate (node, node2, v, duplicate);
510 : : }
511 : 9760258 : }
512 : :
513 : : template <typename T, typename V>
514 : : inline bool
515 : 56923339 : fast_function_summary<T *, V>::is_ggc ()
516 : : {
517 : 56923339 : 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 : 563461 : gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
542 : : {
543 : 563461 : ggc_test_and_set_mark (summary->m_vector);
544 : 563461 : gt_ggc_mx (summary->m_vector);
545 : 563461 : }
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 : 3240460 : class call_summary_base
566 : : {
567 : : public:
568 : : /* Default construction takes SYMTAB as an argument. */
569 : 1620244 : call_summary_base (symbol_table *symtab, cgraph_edge_hook symtab_removal,
570 : : cgraph_2edge_hook symtab_duplication CXX_MEM_STAT_INFO):
571 : 1620244 : m_symtab (symtab), m_symtab_removal (symtab_removal),
572 : 1620244 : m_symtab_duplication (symtab_duplication), m_symtab_duplication_hook (NULL),
573 : 1620244 : m_initialize_when_cloning (false),
574 : 1620244 : m_allocator ("call summary" PASS_MEM_STAT)
575 : : {
576 : : m_symtab_removal_hook
577 : 1620244 : = m_symtab->add_edge_removal_hook (m_symtab_removal, this);
578 : 1620244 : enable_duplication_hook ();
579 : 1620244 : }
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 : 1620244 : void enable_duplication_hook ()
592 : : {
593 : 1620244 : if (m_symtab_duplication_hook == NULL)
594 : : m_symtab_duplication_hook
595 : 1620244 : = m_symtab->add_edge_duplication_hook (m_symtab_duplication,
596 : : this);
597 : 1620244 : }
598 : :
599 : : /* Enable duplication hook invocation. */
600 : 1844198 : void disable_duplication_hook ()
601 : : {
602 : 1844198 : if (m_symtab_duplication_hook != NULL)
603 : : {
604 : 1620230 : m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
605 : 1620230 : m_symtab_duplication_hook = NULL;
606 : : }
607 : 1844198 : }
608 : :
609 : : protected:
610 : : /* Allocates new data that are stored within map. */
611 : 41480311 : 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 : 44142271 : return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T ()
616 : 37544213 : : m_allocator.allocate ();
617 : : }
618 : :
619 : : /* Release an item that is stored within map. */
620 : 41480311 : void release (T *item)
621 : : {
622 : 41480311 : if (is_ggc ())
623 : 3936098 : ggc_delete (item);
624 : : else
625 : 37544213 : m_allocator.remove (item);
626 : 41480311 : }
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 : 1620230 : call_summary_base<T>::unregister_hooks ()
657 : : {
658 : 1620230 : m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
659 : 1620230 : disable_duplication_hook ();
660 : 1620230 : }
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 : 951804 : 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 : 951804 : 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 : 14516631 : T* get_create (cgraph_edge *edge)
699 : : {
700 : : bool existed;
701 : 14516631 : T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
702 : 14516631 : if (!existed)
703 : 11410329 : *v = this->allocate_new ();
704 : :
705 : 14516631 : return *v;
706 : : }
707 : :
708 : : /* Getter for summary callgraph edge pointer. */
709 : 48015274 : T* get (cgraph_edge *edge) ATTRIBUTE_PURE
710 : : {
711 : 48015274 : T **v = m_map.get (edge->get_uid ());
712 : 48015274 : return v == NULL ? NULL : *v;
713 : : }
714 : :
715 : : /* Remove edge from summary. */
716 : : using call_summary_base<T>::remove;
717 : 9189305 : void remove (cgraph_edge *edge)
718 : : {
719 : 9189305 : int uid = edge->get_uid ();
720 : 9189305 : T **v = m_map.get (uid);
721 : 9189305 : if (v)
722 : : {
723 : 1949928 : m_map.remove (uid);
724 : 1949928 : this->release (*v);
725 : : }
726 : 9189305 : }
727 : :
728 : : /* Return true if a summary for the given EDGE already exists. */
729 : 1145 : bool exists (cgraph_edge *edge)
730 : : {
731 : 1145 : 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 : 22820658 : bool is_ggc () final override
748 : : {
749 : 22820658 : 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 : 951795 : call_summary<T *>::~call_summary ()
765 : : {
766 : 951795 : this->unregister_hooks ();
767 : :
768 : : /* Release all summaries. */
769 : : typedef typename hash_map <map_hash, T *>::iterator map_iterator;
770 : 19872597 : for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
771 : 9460401 : this->release ((*it).second);
772 : 1903590 : }
773 : :
774 : : template <typename T>
775 : : void
776 : 4788426 : call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
777 : : {
778 : 4788426 : call_summary *summary = (call_summary <T *> *) (data);
779 : 4788426 : summary->remove (edge);
780 : 4788426 : }
781 : :
782 : : template <typename T>
783 : : void
784 : 7885611 : call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
785 : : cgraph_edge *edge2, void *data)
786 : : {
787 : 7885611 : call_summary *summary = (call_summary <T *> *) (data);
788 : 7885611 : T *edge1_summary = NULL;
789 : :
790 : 7885611 : if (summary->m_initialize_when_cloning)
791 : 185126 : edge1_summary = summary->get_create (edge1);
792 : : else
793 : 7700485 : edge1_summary = summary->get (edge1);
794 : :
795 : 7885611 : if (edge1_summary)
796 : 2263193 : summary->duplicate (edge1, edge2, edge1_summary,
797 : : summary->get_create (edge2));
798 : 7885611 : }
799 : :
800 : : template <typename T>
801 : : void
802 : 7431 : gt_ggc_mx(call_summary<T *>* const &summary)
803 : : {
804 : 7431 : gcc_checking_assert (summary->m_ggc);
805 : 7431 : gt_ggc_mx (&summary->m_map);
806 : 7431 : }
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 : 668440 : 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 : 668440 : m_vector (NULL)
844 : : {
845 : 668440 : vec_alloc (m_vector, 13 PASS_MEM_STAT);
846 : 668440 : }
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 : 33571929 : T* get_create (cgraph_edge *edge)
864 : : {
865 : 33571929 : int id = edge->get_summary_id ();
866 : 33571929 : if (id == -1)
867 : 19398027 : id = this->m_symtab->assign_summary_id (edge);
868 : :
869 : 33571929 : if ((unsigned)id >= m_vector->length ())
870 : 8724287 : vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
871 : :
872 : 33571929 : if ((*m_vector)[id] == NULL)
873 : 30069982 : (*m_vector)[id] = this->allocate_new ();
874 : :
875 : 33571929 : return (*m_vector)[id];
876 : : }
877 : :
878 : : /* Getter for summary callgraph edge pointer. */
879 : 581435680 : T* get (cgraph_edge *edge) ATTRIBUTE_PURE
880 : : {
881 : 581435680 : 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 : 51098609 : void remove (cgraph_edge *edge)
887 : : {
888 : 51098609 : if (exists (edge))
889 : : {
890 : 16919230 : int id = edge->get_summary_id ();
891 : 16919230 : this->release ((*m_vector)[id]);
892 : 16919230 : (*m_vector)[id] = NULL;
893 : : }
894 : 51098609 : }
895 : :
896 : : /* Return true if a summary for the given EDGE already exists. */
897 : 632534289 : bool exists (cgraph_edge *edge)
898 : : {
899 : 632534289 : int id = edge->get_summary_id ();
900 : : return (id != -1
901 : 674702343 : && (unsigned)id < m_vector->length ()
902 : 1225438058 : && (*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 : 892403 : fast_call_summary<T *, V>::~fast_call_summary ()
926 : : {
927 : 668435 : this->unregister_hooks ();
928 : :
929 : : /* Release all summaries. */
930 : 20324428 : for (unsigned i = 0; i < m_vector->length (); i++)
931 : 19655993 : if ((*m_vector)[i] != NULL)
932 : 13150752 : this->release ((*m_vector)[i]);
933 : 668435 : vec_free (m_vector);
934 : 1560838 : }
935 : :
936 : : template <typename T, typename V>
937 : : void
938 : 20201727 : fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
939 : : {
940 : 20201727 : fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
941 : 20201727 : summary->remove (edge);
942 : 20201727 : }
943 : :
944 : : template <typename T, typename V>
945 : : void
946 : 3560830 : fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
947 : : cgraph_edge *edge2, void *data)
948 : : {
949 : 3560830 : fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
950 : 3560830 : T *edge1_summary = NULL;
951 : :
952 : 3560830 : if (summary->m_initialize_when_cloning)
953 : 0 : edge1_summary = summary->get_create (edge1);
954 : : else
955 : 3560830 : edge1_summary = summary->get (edge1);
956 : :
957 : 3560830 : if (edge1_summary)
958 : : {
959 : 3034032 : T *duplicate = summary->get_create (edge2);
960 : 3034032 : summary->duplicate (edge1, edge2, edge1_summary, duplicate);
961 : : }
962 : 3560830 : }
963 : :
964 : : template <typename T, typename V>
965 : : inline bool
966 : 60139964 : fast_call_summary<T *, V>::is_ggc ()
967 : : {
968 : 60139964 : 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 */
|