symbol-summary.h 26 KB

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