111
|
1 /* Callgraph summary data structure.
|
145
|
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
111
|
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
|
145
|
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
|
111
|
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
|
131
|
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
|
111
|
130 template <class T>
|
145
|
131 class GTY((user)) function_summary <T *>: public function_summary_base<T>
|
111
|
132 {
|
|
133 public:
|
|
134 /* Default construction takes SYMTAB as an argument. */
|
145
|
135 function_summary (symbol_table *symtab, bool ggc = false CXX_MEM_STAT_INFO);
|
111
|
136
|
|
137 /* Destructor. */
|
145
|
138 virtual ~function_summary ();
|
111
|
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
|
131
|
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)
|
111
|
151 {
|
131
|
152 bool existed;
|
|
153 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
|
|
154 if (!existed)
|
145
|
155 *v = this->allocate_new ();
|
131
|
156
|
|
157 return *v;
|
111
|
158 }
|
|
159
|
|
160 /* Getter for summary callgraph node pointer. */
|
131
|
161 T* get (cgraph_node *node) ATTRIBUTE_PURE
|
111
|
162 {
|
131
|
163 T **v = m_map.get (node->get_uid ());
|
|
164 return v == NULL ? NULL : *v;
|
|
165 }
|
|
166
|
|
167 /* Remove node from summary. */
|
145
|
168 using function_summary_base<T>::remove;
|
131
|
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);
|
145
|
176 this->release (*v);
|
131
|
177 }
|
111
|
178 }
|
|
179
|
|
180 /* Return true if a summary for the given NODE already exists. */
|
|
181 bool exists (cgraph_node *node)
|
|
182 {
|
131
|
183 return m_map.get (node->get_uid ()) != NULL;
|
111
|
184 }
|
|
185
|
|
186 /* Symbol insertion hook that is registered to symbol table. */
|
131
|
187 static void symtab_insertion (cgraph_node *node, void *data);
|
111
|
188
|
|
189 /* Symbol removal hook that is registered to symbol table. */
|
131
|
190 static void symtab_removal (cgraph_node *node, void *data);
|
111
|
191
|
|
192 /* Symbol duplication hook that is registered to symbol table. */
|
|
193 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
|
131
|
194 void *data);
|
111
|
195
|
|
196 protected:
|
|
197 /* Indication if we use ggc summary. */
|
|
198 bool m_ggc;
|
|
199
|
|
200 private:
|
145
|
201 /* Indication if we use ggc summary. */
|
|
202 virtual bool is_ggc ()
|
|
203 {
|
|
204 return m_ggc;
|
|
205 }
|
|
206
|
111
|
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>
|
145
|
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)
|
131
|
223 {
|
145
|
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);
|
131
|
233 }
|
|
234
|
|
235 template <typename T>
|
145
|
236 function_summary<T *>::~function_summary ()
|
131
|
237 {
|
145
|
238 this->unregister_hooks ();
|
131
|
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)
|
145
|
243 this->release ((*it).second);
|
131
|
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);
|
145
|
263 summary->remove (node);
|
131
|
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)
|
145
|
275 summary->duplicate (node, node2, v, summary->get_create (node2));
|
131
|
276 }
|
|
277
|
|
278 template <typename T>
|
111
|
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
|
145
|
288 gt_pch_nx (function_summary<T *> *const &)
|
111
|
289 {
|
145
|
290 gcc_unreachable ();
|
111
|
291 }
|
|
292
|
|
293 template <typename T>
|
|
294 void
|
145
|
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 ()
|
111
|
432 {
|
145
|
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);
|
111
|
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:
|
145
|
603 call_summary ();
|
111
|
604 };
|
|
605
|
|
606 /* Class to store auxiliary information about call graph edges. */
|
|
607
|
|
608 template <class T>
|
145
|
609 class GTY((user)) call_summary <T *>: public call_summary_base<T>
|
111
|
610 {
|
|
611 public:
|
|
612 /* Default construction takes SYMTAB as an argument. */
|
145
|
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)
|
111
|
617 {
|
145
|
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);
|
111
|
624 }
|
|
625
|
|
626 /* Destructor. */
|
145
|
627 virtual ~call_summary ();
|
111
|
628
|
145
|
629 /* Traverses all summarys with an edge E called with
|
111
|
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
|
131
|
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)
|
111
|
640 {
|
131
|
641 bool existed;
|
|
642 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
|
|
643 if (!existed)
|
145
|
644 *v = this->allocate_new ();
|
131
|
645
|
|
646 return *v;
|
111
|
647 }
|
|
648
|
|
649 /* Getter for summary callgraph edge pointer. */
|
131
|
650 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
|
111
|
651 {
|
131
|
652 T **v = m_map.get (edge->get_uid ());
|
|
653 return v == NULL ? NULL : *v;
|
|
654 }
|
|
655
|
|
656 /* Remove edge from summary. */
|
145
|
657 using call_summary_base<T>::remove;
|
131
|
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);
|
145
|
665 this->release (*v);
|
131
|
666 }
|
111
|
667 }
|
|
668
|
|
669 /* Return true if a summary for the given EDGE already exists. */
|
|
670 bool exists (cgraph_edge *edge)
|
|
671 {
|
131
|
672 return m_map.get (edge->get_uid ()) != NULL;
|
111
|
673 }
|
|
674
|
|
675 /* Symbol removal hook that is registered to symbol table. */
|
131
|
676 static void symtab_removal (cgraph_edge *edge, void *data);
|
111
|
677
|
|
678 /* Symbol duplication hook that is registered to symbol table. */
|
|
679 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
|
131
|
680 void *data);
|
111
|
681
|
|
682 protected:
|
|
683 /* Indication if we use ggc summary. */
|
|
684 bool m_ggc;
|
|
685
|
145
|
686 private:
|
|
687 /* Indication if we use ggc summary. */
|
|
688 virtual bool is_ggc ()
|
|
689 {
|
|
690 return m_ggc;
|
|
691 }
|
131
|
692
|
111
|
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>
|
145
|
705 call_summary<T *>::~call_summary ()
|
131
|
706 {
|
145
|
707 this->unregister_hooks ();
|
131
|
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)
|
145
|
712 this->release ((*it).second);
|
131
|
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);
|
145
|
720 summary->remove (edge);
|
131
|
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
|
145
|
734 edge1_summary = summary->get (edge1);
|
131
|
735
|
|
736 if (edge1_summary)
|
145
|
737 summary->duplicate (edge1, edge2, edge1_summary,
|
|
738 summary->get_create (edge2));
|
131
|
739 }
|
|
740
|
|
741 template <typename T>
|
|
742 void
|
111
|
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
|
145
|
751 gt_pch_nx (call_summary<T *> *const &)
|
111
|
752 {
|
145
|
753 gcc_unreachable ();
|
111
|
754 }
|
|
755
|
|
756 template <typename T>
|
|
757 void
|
145
|
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>
|
111
|
778 {
|
145
|
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 ();
|
111
|
956 }
|
|
957
|
|
958 #endif /* GCC_SYMBOL_SUMMARY_H */
|