2018-08-22 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / symbol-summary.h
blob26e9773d3c033bb33a2646362d07025534d78ccc
1 /* Callgraph summary data structure.
2 Copyright (C) 2014-2018 Free Software Foundation, Inc.
3 Contributed by Martin Liska
5 This file is part of GCC.
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.
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.
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/>. */
21 #ifndef GCC_SYMBOL_SUMMARY_H
22 #define GCC_SYMBOL_SUMMARY_H
24 /* We want to pass just pointer types as argument for function_summary
25 template class. */
27 template <class T>
28 class function_summary
30 private:
31 function_summary();
34 /* Function summary is a helper class that is used to associate a data structure
35 related to a callgraph node. Typical usage can be seen in IPA passes which
36 create a temporary pass-related structures. The summary class registers
37 hooks that are triggered when a new node is inserted, duplicated and deleted.
38 A user of a summary class can ovewrite virtual methods than are triggered by
39 the summary if such hook is triggered. Apart from a callgraph node, the user
40 is given a data structure tied to the node.
42 The function summary class can work both with a heap-allocated memory and
43 a memory gained by garbage collected memory. */
45 template <class T>
46 class GTY((user)) function_summary <T *>
48 public:
49 /* Default construction takes SYMTAB as an argument. */
50 function_summary (symbol_table *symtab, bool ggc = false);
52 /* Destructor. */
53 virtual ~function_summary ()
55 release ();
58 /* Destruction method that can be called for GGT purpose. */
59 void release ();
61 /* Traverses all summarys with a function F called with
62 ARG as argument. */
63 template<typename Arg, bool (*f)(const T &, Arg)>
64 void traverse (Arg a) const
66 m_map.traverse <f> (a);
69 /* Basic implementation of insert operation. */
70 virtual void insert (cgraph_node *, T *) {}
72 /* Basic implementation of removal operation. */
73 virtual void remove (cgraph_node *, T *) {}
75 /* Basic implementation of duplication operation. */
76 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
78 /* Allocates new data that are stored within map. */
79 T* allocate_new ()
81 /* Call gcc_internal_because we do not want to call finalizer for
82 a type T. We call dtor explicitly. */
83 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
86 /* Release an item that is stored within map. */
87 void release (T *item);
89 /* Getter for summary callgraph node pointer. If a summary for a node
90 does not exist it will be created. */
91 T* get_create (cgraph_node *node)
93 bool existed;
94 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
95 if (!existed)
96 *v = allocate_new ();
98 return *v;
101 /* Getter for summary callgraph node pointer. */
102 T* get (cgraph_node *node) ATTRIBUTE_PURE
104 T **v = m_map.get (node->get_uid ());
105 return v == NULL ? NULL : *v;
108 /* Remove node from summary. */
109 void remove (cgraph_node *node)
111 int uid = node->get_uid ();
112 T **v = m_map.get (uid);
113 if (v)
115 m_map.remove (uid);
116 release (*v);
120 /* Return number of elements handled by data structure. */
121 size_t elements ()
123 return m_map.elements ();
126 /* Return true if a summary for the given NODE already exists. */
127 bool exists (cgraph_node *node)
129 return m_map.get (node->get_uid ()) != NULL;
132 /* Enable insertion hook invocation. */
133 void enable_insertion_hook ()
135 m_insertion_enabled = true;
138 /* Enable insertion hook invocation. */
139 void disable_insertion_hook ()
141 m_insertion_enabled = false;
144 /* Symbol insertion hook that is registered to symbol table. */
145 static void symtab_insertion (cgraph_node *node, void *data);
147 /* Symbol removal hook that is registered to symbol table. */
148 static void symtab_removal (cgraph_node *node, void *data);
150 /* Symbol duplication hook that is registered to symbol table. */
151 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
152 void *data);
154 protected:
155 /* Indication if we use ggc summary. */
156 bool m_ggc;
158 private:
159 typedef int_hash <int, 0, -1> map_hash;
161 /* Indicates if insertion hook is enabled. */
162 bool m_insertion_enabled;
163 /* Indicates if the summary is released. */
164 bool m_released;
165 /* Main summary store, where summary ID is used as key. */
166 hash_map <map_hash, T *> m_map;
167 /* Internal summary insertion hook pointer. */
168 cgraph_node_hook_list *m_symtab_insertion_hook;
169 /* Internal summary removal hook pointer. */
170 cgraph_node_hook_list *m_symtab_removal_hook;
171 /* Internal summary duplication hook pointer. */
172 cgraph_2node_hook_list *m_symtab_duplication_hook;
173 /* Symbol table the summary is registered to. */
174 symbol_table *m_symtab;
176 template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
177 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
178 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
179 gt_pointer_operator, void *);
182 template <typename T>
183 function_summary<T *>::function_summary (symbol_table *symtab, bool ggc):
184 m_ggc (ggc), m_insertion_enabled (true), m_released (false), m_map (13, ggc),
185 m_symtab (symtab)
187 m_symtab_insertion_hook
188 = symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
189 this);
191 m_symtab_removal_hook
192 = symtab->add_cgraph_removal_hook (function_summary::symtab_removal, this);
193 m_symtab_duplication_hook
194 = symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication,
195 this);
198 template <typename T>
199 void
200 function_summary<T *>::release ()
202 if (m_released)
203 return;
205 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
206 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
207 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
209 /* Release all summaries. */
210 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
211 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
212 release ((*it).second);
214 m_released = true;
217 template <typename T>
218 void
219 function_summary<T *>::release (T *item)
221 if (m_ggc)
223 item->~T ();
224 ggc_free (item);
226 else
227 delete item;
230 template <typename T>
231 void
232 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
234 gcc_checking_assert (node->get_uid ());
235 function_summary *summary = (function_summary <T *> *) (data);
237 if (summary->m_insertion_enabled)
238 summary->insert (node, summary->get_create (node));
241 template <typename T>
242 void
243 function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
245 gcc_checking_assert (node->get_uid ());
246 function_summary *summary = (function_summary <T *> *) (data);
248 int uid = node->get_uid ();
249 T **v = summary->m_map.get (uid);
251 if (v)
253 summary->remove (node, *v);
255 if (!summary->m_ggc)
256 delete (*v);
258 summary->m_map.remove (uid);
262 template <typename T>
263 void
264 function_summary<T *>::symtab_duplication (cgraph_node *node,
265 cgraph_node *node2, void *data)
267 function_summary *summary = (function_summary <T *> *) (data);
268 T *v = summary->get (node);
270 if (v)
272 /* This load is necessary, because we insert a new value! */
273 T *duplicate = summary->allocate_new ();
274 summary->m_map.put (node2->get_uid (), duplicate);
275 summary->duplicate (node, node2, v, duplicate);
279 template <typename T>
280 void
281 gt_ggc_mx(function_summary<T *>* const &summary)
283 gcc_checking_assert (summary->m_ggc);
284 gt_ggc_mx (&summary->m_map);
287 template <typename T>
288 void
289 gt_pch_nx(function_summary<T *>* const &summary)
291 gcc_checking_assert (summary->m_ggc);
292 gt_pch_nx (&summary->m_map);
295 template <typename T>
296 void
297 gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
298 void *cookie)
300 gcc_checking_assert (summary->m_ggc);
301 gt_pch_nx (&summary->m_map, op, cookie);
304 /* An impossible class templated by non-pointers so, which makes sure that only
305 summaries gathering pointers can be created. */
307 template <class T>
308 class call_summary
310 private:
311 call_summary();
314 /* Class to store auxiliary information about call graph edges. */
316 template <class T>
317 class GTY((user)) call_summary <T *>
319 public:
320 /* Default construction takes SYMTAB as an argument. */
321 call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
322 m_initialize_when_cloning (false), m_map (13, ggc), m_released (false),
323 m_symtab (symtab)
325 m_symtab_removal_hook =
326 symtab->add_edge_removal_hook
327 (call_summary::symtab_removal, this);
328 m_symtab_duplication_hook =
329 symtab->add_edge_duplication_hook
330 (call_summary::symtab_duplication, this);
333 /* Destructor. */
334 virtual ~call_summary ()
336 release ();
339 /* Destruction method that can be called for GGT purpose. */
340 void release ();
342 /* Traverses all summarys with a function F called with
343 ARG as argument. */
344 template<typename Arg, bool (*f)(const T &, Arg)>
345 void traverse (Arg a) const
347 m_map.traverse <f> (a);
350 /* Basic implementation of removal operation. */
351 virtual void remove (cgraph_edge *, T *) {}
353 /* Basic implementation of duplication operation. */
354 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
356 /* Allocates new data that are stored within map. */
357 T* allocate_new ()
359 /* Call gcc_internal_because we do not want to call finalizer for
360 a type T. We call dtor explicitly. */
361 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
364 /* Release an item that is stored within map. */
365 void release (T *item);
367 /* Getter for summary callgraph edge pointer.
368 If a summary for an edge does not exist, it will be created. */
369 T* get_create (cgraph_edge *edge)
371 bool existed;
372 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
373 if (!existed)
374 *v = allocate_new ();
376 return *v;
379 /* Getter for summary callgraph edge pointer. */
380 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
382 T **v = m_map.get (edge->get_uid ());
383 return v == NULL ? NULL : *v;
386 /* Remove edge from summary. */
387 void remove (cgraph_edge *edge)
389 int uid = edge->get_uid ();
390 T **v = m_map.get (uid);
391 if (v)
393 m_map.remove (uid);
394 release (*v);
398 /* Return number of elements handled by data structure. */
399 size_t elements ()
401 return m_map.elements ();
404 /* Return true if a summary for the given EDGE already exists. */
405 bool exists (cgraph_edge *edge)
407 return m_map.get (edge->get_uid ()) != NULL;
410 /* Symbol removal hook that is registered to symbol table. */
411 static void symtab_removal (cgraph_edge *edge, void *data);
413 /* Symbol duplication hook that is registered to symbol table. */
414 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
415 void *data);
417 protected:
418 /* Indication if we use ggc summary. */
419 bool m_ggc;
421 /* Initialize summary for an edge that is cloned. */
422 bool m_initialize_when_cloning;
424 private:
425 typedef int_hash <int, 0, -1> map_hash;
427 /* Main summary store, where summary ID is used as key. */
428 hash_map <map_hash, T *> m_map;
429 /* Internal summary removal hook pointer. */
430 cgraph_edge_hook_list *m_symtab_removal_hook;
431 /* Internal summary duplication hook pointer. */
432 cgraph_2edge_hook_list *m_symtab_duplication_hook;
433 /* Indicates if the summary is released. */
434 bool m_released;
435 /* Symbol table the summary is registered to. */
436 symbol_table *m_symtab;
438 template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
439 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
440 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
441 gt_pointer_operator, void *);
444 template <typename T>
445 void
446 call_summary<T *>::release ()
448 if (m_released)
449 return;
451 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
452 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
454 /* Release all summaries. */
455 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
456 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
457 release ((*it).second);
459 m_released = true;
462 template <typename T>
463 void
464 call_summary<T *>::release (T *item)
466 if (m_ggc)
468 item->~T ();
469 ggc_free (item);
471 else
472 delete item;
475 template <typename T>
476 void
477 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
479 call_summary *summary = (call_summary <T *> *) (data);
481 int h_uid = edge->get_uid ();
482 T **v = summary->m_map.get (h_uid);
484 if (v)
486 summary->remove (edge, *v);
487 summary->release (*v);
488 summary->m_map.remove (h_uid);
492 template <typename T>
493 void
494 call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
495 cgraph_edge *edge2, void *data)
497 call_summary *summary = (call_summary <T *> *) (data);
498 T *edge1_summary = NULL;
500 if (summary->m_initialize_when_cloning)
501 edge1_summary = summary->get_create (edge1);
502 else
504 T **v = summary->m_map.get (edge1->get_uid ());
505 if (v)
507 /* This load is necessary, because we insert a new value! */
508 edge1_summary = *v;
512 if (edge1_summary)
514 T *duplicate = summary->allocate_new ();
515 summary->m_map.put (edge2->get_uid (), duplicate);
516 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
520 template <typename T>
521 void
522 gt_ggc_mx(call_summary<T *>* const &summary)
524 gcc_checking_assert (summary->m_ggc);
525 gt_ggc_mx (&summary->m_map);
528 template <typename T>
529 void
530 gt_pch_nx(call_summary<T *>* const &summary)
532 gcc_checking_assert (summary->m_ggc);
533 gt_pch_nx (&summary->m_map);
536 template <typename T>
537 void
538 gt_pch_nx(call_summary<T *>* const& summary, gt_pointer_operator op,
539 void *cookie)
541 gcc_checking_assert (summary->m_ggc);
542 gt_pch_nx (&summary->m_map, op, cookie);
545 #endif /* GCC_SYMBOL_SUMMARY_H */