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