comparison gcc/symbol-summary.h @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Callgraph summary data structure. 1 /* Callgraph summary data structure.
2 Copyright (C) 2014-2017 Free Software Foundation, Inc. 2 Copyright (C) 2014-2018 Free Software Foundation, Inc.
3 Contributed by Martin Liska 3 Contributed by Martin Liska
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it under 7 GCC is free software; you can redistribute it and/or modify it under
29 { 29 {
30 private: 30 private:
31 function_summary(); 31 function_summary();
32 }; 32 };
33 33
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.
41
42 The function summary class can work both with a heap-allocated memory and
43 a memory gained by garbage collected memory. */
44
34 template <class T> 45 template <class T>
35 class GTY((user)) function_summary <T *> 46 class GTY((user)) function_summary <T *>
36 { 47 {
37 public: 48 public:
38 /* Default construction takes SYMTAB as an argument. */ 49 /* Default construction takes SYMTAB as an argument. */
39 function_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc), 50 function_summary (symbol_table *symtab, bool ggc = false);
40 m_insertion_enabled (true), m_released (false), m_map (13, ggc),
41 m_symtab (symtab)
42 {
43 m_symtab_insertion_hook =
44 symtab->add_cgraph_insertion_hook
45 (function_summary::symtab_insertion, this);
46
47 m_symtab_removal_hook =
48 symtab->add_cgraph_removal_hook
49 (function_summary::symtab_removal, this);
50 m_symtab_duplication_hook =
51 symtab->add_cgraph_duplication_hook
52 (function_summary::symtab_duplication, this);
53 }
54 51
55 /* Destructor. */ 52 /* Destructor. */
56 virtual ~function_summary () 53 virtual ~function_summary ()
57 { 54 {
58 release (); 55 release ();
59 } 56 }
60 57
61 /* Destruction method that can be called for GGT purpose. */ 58 /* Destruction method that can be called for GGT purpose. */
62 void release () 59 void release ();
63 {
64 if (m_released)
65 return;
66
67 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
68 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
69 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
70
71 /* Release all summaries. */
72 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
73 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
74 release ((*it).second);
75
76 m_released = true;
77 }
78 60
79 /* Traverses all summarys with a function F called with 61 /* Traverses all summarys with a function F called with
80 ARG as argument. */ 62 ARG as argument. */
81 template<typename Arg, bool (*f)(const T &, Arg)> 63 template<typename Arg, bool (*f)(const T &, Arg)>
82 void traverse (Arg a) const 64 void traverse (Arg a) const
100 a type T. We call dtor explicitly. */ 82 a type T. We call dtor explicitly. */
101 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ; 83 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
102 } 84 }
103 85
104 /* Release an item that is stored within map. */ 86 /* Release an item that is stored within map. */
105 void release (T *item) 87 void release (T *item);
106 { 88
107 if (m_ggc) 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)
92 {
93 bool existed;
94 T **v = &m_map.get_or_insert (node->get_uid (), &existed);
95 if (!existed)
96 *v = allocate_new ();
97
98 return *v;
99 }
100
101 /* Getter for summary callgraph node pointer. */
102 T* get (cgraph_node *node) ATTRIBUTE_PURE
103 {
104 T **v = m_map.get (node->get_uid ());
105 return v == NULL ? NULL : *v;
106 }
107
108 /* Remove node from summary. */
109 void remove (cgraph_node *node)
110 {
111 int uid = node->get_uid ();
112 T **v = m_map.get (uid);
113 if (v)
108 { 114 {
109 item->~T (); 115 m_map.remove (uid);
110 ggc_free (item); 116 release (*v);
111 } 117 }
112 else
113 delete item;
114 }
115
116 /* Getter for summary callgraph node pointer. */
117 T* get (cgraph_node *node)
118 {
119 gcc_checking_assert (node->summary_uid);
120 return get (node->summary_uid);
121 } 118 }
122 119
123 /* Return number of elements handled by data structure. */ 120 /* Return number of elements handled by data structure. */
124 size_t elements () 121 size_t elements ()
125 { 122 {
127 } 124 }
128 125
129 /* Return true if a summary for the given NODE already exists. */ 126 /* Return true if a summary for the given NODE already exists. */
130 bool exists (cgraph_node *node) 127 bool exists (cgraph_node *node)
131 { 128 {
132 return m_map.get (node->summary_uid) != NULL; 129 return m_map.get (node->get_uid ()) != NULL;
133 } 130 }
134 131
135 /* Enable insertion hook invocation. */ 132 /* Enable insertion hook invocation. */
136 void enable_insertion_hook () 133 void enable_insertion_hook ()
137 { 134 {
143 { 140 {
144 m_insertion_enabled = false; 141 m_insertion_enabled = false;
145 } 142 }
146 143
147 /* Symbol insertion hook that is registered to symbol table. */ 144 /* Symbol insertion hook that is registered to symbol table. */
148 static void symtab_insertion (cgraph_node *node, void *data) 145 static void symtab_insertion (cgraph_node *node, void *data);
149 {
150 gcc_checking_assert (node->summary_uid);
151 function_summary *summary = (function_summary <T *> *) (data);
152
153 if (summary->m_insertion_enabled)
154 summary->insert (node, summary->get (node));
155 }
156 146
157 /* Symbol removal hook that is registered to symbol table. */ 147 /* Symbol removal hook that is registered to symbol table. */
158 static void symtab_removal (cgraph_node *node, void *data) 148 static void symtab_removal (cgraph_node *node, void *data);
159 {
160 gcc_checking_assert (node->summary_uid);
161 function_summary *summary = (function_summary <T *> *) (data);
162
163 int summary_uid = node->summary_uid;
164 T **v = summary->m_map.get (summary_uid);
165
166 if (v)
167 {
168 summary->remove (node, *v);
169 summary->release (*v);
170 summary->m_map.remove (summary_uid);
171 }
172 }
173 149
174 /* Symbol duplication hook that is registered to symbol table. */ 150 /* Symbol duplication hook that is registered to symbol table. */
175 static void symtab_duplication (cgraph_node *node, cgraph_node *node2, 151 static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
176 void *data) 152 void *data);
177 {
178 function_summary *summary = (function_summary <T *> *) (data);
179 T **v = summary->m_map.get (node->summary_uid);
180
181 gcc_checking_assert (node2->summary_uid > 0);
182
183 if (v)
184 {
185 /* This load is necessary, because we insert a new value! */
186 T *data = *v;
187 T *duplicate = summary->allocate_new ();
188 summary->m_map.put (node2->summary_uid, duplicate);
189 summary->duplicate (node, node2, data, duplicate);
190 }
191 }
192 153
193 protected: 154 protected:
194 /* Indication if we use ggc summary. */ 155 /* Indication if we use ggc summary. */
195 bool m_ggc; 156 bool m_ggc;
196 157
197 private: 158 private:
198 typedef int_hash <int, 0, -1> map_hash; 159 typedef int_hash <int, 0, -1> map_hash;
199
200 /* Getter for summary callgraph ID. */
201 T* get (int uid)
202 {
203 bool existed;
204 T **v = &m_map.get_or_insert (uid, &existed);
205 if (!existed)
206 *v = allocate_new ();
207
208 return *v;
209 }
210 160
211 /* Indicates if insertion hook is enabled. */ 161 /* Indicates if insertion hook is enabled. */
212 bool m_insertion_enabled; 162 bool m_insertion_enabled;
213 /* Indicates if the summary is released. */ 163 /* Indicates if the summary is released. */
214 bool m_released; 164 bool m_released;
228 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 &,
229 gt_pointer_operator, void *); 179 gt_pointer_operator, void *);
230 }; 180 };
231 181
232 template <typename T> 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)
186 {
187 m_symtab_insertion_hook
188 = symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion,
189 this);
190
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);
196 }
197
198 template <typename T>
199 void
200 function_summary<T *>::release ()
201 {
202 if (m_released)
203 return;
204
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);
208
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);
213
214 m_released = true;
215 }
216
217 template <typename T>
218 void
219 function_summary<T *>::release (T *item)
220 {
221 if (m_ggc)
222 {
223 item->~T ();
224 ggc_free (item);
225 }
226 else
227 delete item;
228 }
229
230 template <typename T>
231 void
232 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data)
233 {
234 gcc_checking_assert (node->get_uid ());
235 function_summary *summary = (function_summary <T *> *) (data);
236
237 if (summary->m_insertion_enabled)
238 summary->insert (node, summary->get_create (node));
239 }
240
241 template <typename T>
242 void
243 function_summary<T *>::symtab_removal (cgraph_node *node, void *data)
244 {
245 gcc_checking_assert (node->get_uid ());
246 function_summary *summary = (function_summary <T *> *) (data);
247
248 int uid = node->get_uid ();
249 T **v = summary->m_map.get (uid);
250
251 if (v)
252 {
253 summary->remove (node, *v);
254
255 if (!summary->m_ggc)
256 delete (*v);
257
258 summary->m_map.remove (uid);
259 }
260 }
261
262 template <typename T>
263 void
264 function_summary<T *>::symtab_duplication (cgraph_node *node,
265 cgraph_node *node2, void *data)
266 {
267 function_summary *summary = (function_summary <T *> *) (data);
268 T *v = summary->get (node);
269
270 if (v)
271 {
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);
276 }
277 }
278
279 template <typename T>
233 void 280 void
234 gt_ggc_mx(function_summary<T *>* const &summary) 281 gt_ggc_mx(function_summary<T *>* const &summary)
235 { 282 {
236 gcc_checking_assert (summary->m_ggc); 283 gcc_checking_assert (summary->m_ggc);
237 gt_ggc_mx (&summary->m_map); 284 gt_ggc_mx (&summary->m_map);
270 class GTY((user)) call_summary <T *> 317 class GTY((user)) call_summary <T *>
271 { 318 {
272 public: 319 public:
273 /* Default construction takes SYMTAB as an argument. */ 320 /* Default construction takes SYMTAB as an argument. */
274 call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc), 321 call_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc),
275 m_map (13, ggc), m_released (false), m_symtab (symtab) 322 m_initialize_when_cloning (false), m_map (13, ggc), m_released (false),
323 m_symtab (symtab)
276 { 324 {
277 m_symtab_removal_hook = 325 m_symtab_removal_hook =
278 symtab->add_edge_removal_hook 326 symtab->add_edge_removal_hook
279 (call_summary::symtab_removal, this); 327 (call_summary::symtab_removal, this);
280 m_symtab_duplication_hook = 328 m_symtab_duplication_hook =
287 { 335 {
288 release (); 336 release ();
289 } 337 }
290 338
291 /* Destruction method that can be called for GGT purpose. */ 339 /* Destruction method that can be called for GGT purpose. */
292 void release () 340 void release ();
293 {
294 if (m_released)
295 return;
296
297 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
298 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
299
300 /* Release all summaries. */
301 typedef typename hash_map <map_hash, T *>::iterator map_iterator;
302 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
303 release ((*it).second);
304
305 m_released = true;
306 }
307 341
308 /* Traverses all summarys with a function F called with 342 /* Traverses all summarys with a function F called with
309 ARG as argument. */ 343 ARG as argument. */
310 template<typename Arg, bool (*f)(const T &, Arg)> 344 template<typename Arg, bool (*f)(const T &, Arg)>
311 void traverse (Arg a) const 345 void traverse (Arg a) const
326 a type T. We call dtor explicitly. */ 360 a type T. We call dtor explicitly. */
327 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ; 361 return m_ggc ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
328 } 362 }
329 363
330 /* Release an item that is stored within map. */ 364 /* Release an item that is stored within map. */
331 void release (T *item) 365 void release (T *item);
332 { 366
333 if (m_ggc) 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)
370 {
371 bool existed;
372 T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
373 if (!existed)
374 *v = allocate_new ();
375
376 return *v;
377 }
378
379 /* Getter for summary callgraph edge pointer. */
380 T* get (cgraph_edge *edge) ATTRIBUTE_PURE
381 {
382 T **v = m_map.get (edge->get_uid ());
383 return v == NULL ? NULL : *v;
384 }
385
386 /* Remove edge from summary. */
387 void remove (cgraph_edge *edge)
388 {
389 int uid = edge->get_uid ();
390 T **v = m_map.get (uid);
391 if (v)
334 { 392 {
335 item->~T (); 393 m_map.remove (uid);
336 ggc_free (item); 394 release (*v);
337 } 395 }
338 else
339 delete item;
340 }
341
342 /* Getter for summary callgraph edge pointer. */
343 T* get (cgraph_edge *edge)
344 {
345 return get (hashable_uid (edge));
346 } 396 }
347 397
348 /* Return number of elements handled by data structure. */ 398 /* Return number of elements handled by data structure. */
349 size_t elements () 399 size_t elements ()
350 { 400 {
352 } 402 }
353 403
354 /* Return true if a summary for the given EDGE already exists. */ 404 /* Return true if a summary for the given EDGE already exists. */
355 bool exists (cgraph_edge *edge) 405 bool exists (cgraph_edge *edge)
356 { 406 {
357 return m_map.get (hashable_uid (edge)) != NULL; 407 return m_map.get (edge->get_uid ()) != NULL;
358 } 408 }
359 409
360 /* Symbol removal hook that is registered to symbol table. */ 410 /* Symbol removal hook that is registered to symbol table. */
361 static void symtab_removal (cgraph_edge *edge, void *data) 411 static void symtab_removal (cgraph_edge *edge, void *data);
362 {
363 call_summary *summary = (call_summary <T *> *) (data);
364
365 int h_uid = summary->hashable_uid (edge);
366 T **v = summary->m_map.get (h_uid);
367
368 if (v)
369 {
370 summary->remove (edge, *v);
371 summary->release (*v);
372 summary->m_map.remove (h_uid);
373 }
374 }
375 412
376 /* Symbol duplication hook that is registered to symbol table. */ 413 /* Symbol duplication hook that is registered to symbol table. */
377 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2, 414 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
378 void *data) 415 void *data);
379 {
380 call_summary *summary = (call_summary <T *> *) (data);
381 T **v = summary->m_map.get (summary->hashable_uid (edge1));
382
383 if (v)
384 {
385 /* This load is necessary, because we insert a new value! */
386 T *data = *v;
387 T *duplicate = summary->allocate_new ();
388 summary->m_map.put (summary->hashable_uid (edge2), duplicate);
389 summary->duplicate (edge1, edge2, data, duplicate);
390 }
391 }
392 416
393 protected: 417 protected:
394 /* Indication if we use ggc summary. */ 418 /* Indication if we use ggc summary. */
395 bool m_ggc; 419 bool m_ggc;
396 420
421 /* Initialize summary for an edge that is cloned. */
422 bool m_initialize_when_cloning;
423
397 private: 424 private:
398 typedef int_hash <int, 0, -1> map_hash; 425 typedef int_hash <int, 0, -1> map_hash;
399
400 /* Getter for summary callgraph ID. */
401 T* get (int uid)
402 {
403 bool existed;
404 T **v = &m_map.get_or_insert (uid, &existed);
405 if (!existed)
406 *v = allocate_new ();
407
408 return *v;
409 }
410
411 /* Get a hashable uid of EDGE. */
412 int hashable_uid (cgraph_edge *edge)
413 {
414 /* Edge uids start at zero which our hash_map does not like. */
415 return edge->uid + 1;
416 }
417 426
418 /* Main summary store, where summary ID is used as key. */ 427 /* Main summary store, where summary ID is used as key. */
419 hash_map <map_hash, T *> m_map; 428 hash_map <map_hash, T *> m_map;
420 /* Internal summary removal hook pointer. */ 429 /* Internal summary removal hook pointer. */
421 cgraph_edge_hook_list *m_symtab_removal_hook; 430 cgraph_edge_hook_list *m_symtab_removal_hook;
432 gt_pointer_operator, void *); 441 gt_pointer_operator, void *);
433 }; 442 };
434 443
435 template <typename T> 444 template <typename T>
436 void 445 void
446 call_summary<T *>::release ()
447 {
448 if (m_released)
449 return;
450
451 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
452 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
453
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);
458
459 m_released = true;
460 }
461
462 template <typename T>
463 void
464 call_summary<T *>::release (T *item)
465 {
466 if (m_ggc)
467 {
468 item->~T ();
469 ggc_free (item);
470 }
471 else
472 delete item;
473 }
474
475 template <typename T>
476 void
477 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
478 {
479 call_summary *summary = (call_summary <T *> *) (data);
480
481 int h_uid = edge->get_uid ();
482 T **v = summary->m_map.get (h_uid);
483
484 if (v)
485 {
486 summary->remove (edge, *v);
487 summary->release (*v);
488 summary->m_map.remove (h_uid);
489 }
490 }
491
492 template <typename T>
493 void
494 call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
495 cgraph_edge *edge2, void *data)
496 {
497 call_summary *summary = (call_summary <T *> *) (data);
498 T *edge1_summary = NULL;
499
500 if (summary->m_initialize_when_cloning)
501 edge1_summary = summary->get_create (edge1);
502 else
503 {
504 T **v = summary->m_map.get (edge1->get_uid ());
505 if (v)
506 {
507 /* This load is necessary, because we insert a new value! */
508 edge1_summary = *v;
509 }
510 }
511
512 if (edge1_summary)
513 {
514 T *duplicate = summary->allocate_new ();
515 summary->m_map.put (edge2->get_uid (), duplicate);
516 summary->duplicate (edge1, edge2, edge1_summary, duplicate);
517 }
518 }
519
520 template <typename T>
521 void
437 gt_ggc_mx(call_summary<T *>* const &summary) 522 gt_ggc_mx(call_summary<T *>* const &summary)
438 { 523 {
439 gcc_checking_assert (summary->m_ggc); 524 gcc_checking_assert (summary->m_ggc);
440 gt_ggc_mx (&summary->m_map); 525 gt_ggc_mx (&summary->m_map);
441 } 526 }