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
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
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
28 class 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. */
46 class GTY((user
)) function_summary
<T
*>
49 /* Default construction takes SYMTAB as an argument. */
50 function_summary (symbol_table
*symtab
, bool ggc
= false);
53 virtual ~function_summary ()
58 /* Destruction method that can be called for GGT purpose. */
61 /* Traverses all summarys with a function F called with
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. */
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
)
94 T
**v
= &m_map
.get_or_insert (node
->get_uid (), &existed
);
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
);
120 /* Return number of elements handled by data structure. */
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
,
155 /* Indication if we use ggc summary. */
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. */
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
),
187 m_symtab_insertion_hook
188 = symtab
->add_cgraph_insertion_hook (function_summary::symtab_insertion
,
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
,
198 template <typename T
>
200 function_summary
<T
*>::release ()
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
);
217 template <typename T
>
219 function_summary
<T
*>::release (T
*item
)
230 template <typename T
>
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
>
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
);
253 summary
->remove (node
, *v
);
258 summary
->m_map
.remove (uid
);
262 template <typename T
>
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
);
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
>
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
>
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
>
297 gt_pch_nx(function_summary
<T
*>* const& summary
, gt_pointer_operator op
,
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. */
314 /* Class to store auxiliary information about call graph edges. */
317 class GTY((user
)) call_summary
<T
*>
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),
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);
334 virtual ~call_summary ()
339 /* Destruction method that can be called for GGT purpose. */
342 /* Traverses all summarys with a function F called with
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. */
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
)
372 T
**v
= &m_map
.get_or_insert (edge
->get_uid (), &existed
);
374 *v
= allocate_new ();
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
);
398 /* Return number of elements handled by data structure. */
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
,
418 /* Indication if we use ggc summary. */
421 /* Initialize summary for an edge that is cloned. */
422 bool m_initialize_when_cloning
;
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. */
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
>
446 call_summary
<T
*>::release ()
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
);
462 template <typename T
>
464 call_summary
<T
*>::release (T
*item
)
475 template <typename T
>
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
);
486 summary
->remove (edge
, *v
);
487 summary
->release (*v
);
488 summary
->m_map
.remove (h_uid
);
492 template <typename T
>
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
);
504 T
**v
= summary
->m_map
.get (edge1
->get_uid ());
507 /* This load is necessary, because we insert a new value! */
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
>
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
>
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
>
538 gt_pch_nx(call_summary
<T
*>* const& summary
, gt_pointer_operator op
,
541 gcc_checking_assert (summary
->m_ggc
);
542 gt_pch_nx (&summary
->m_map
, op
, cookie
);
545 #endif /* GCC_SYMBOL_SUMMARY_H */