symbol-summary.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  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. this->m_released = true;
  384. }
  385. template <typename T, typename V>
  386. void
  387. fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data)
  388. {
  389. gcc_checking_assert (node->get_uid ());
  390. fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
  391. if (summary->m_insertion_enabled)
  392. summary->insert (node, summary->get_create (node));
  393. }
  394. template <typename T, typename V>
  395. void
  396. fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data)
  397. {
  398. gcc_checking_assert (node->get_uid ());
  399. fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
  400. if (summary->exists (node))
  401. summary->remove (node);
  402. }
  403. template <typename T, typename V>
  404. void
  405. fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node,
  406. cgraph_node *node2,
  407. void *data)
  408. {
  409. fast_function_summary *summary = (fast_function_summary <T *, V> *) (data);
  410. T *v = summary->get (node);
  411. if (v)
  412. {
  413. T *duplicate = summary->get_create (node2);
  414. summary->duplicate (node, node2, v, duplicate);
  415. }
  416. }
  417. template <typename T, typename V>
  418. inline bool
  419. fast_function_summary<T *, V>::is_ggc ()
  420. {
  421. return is_same<V, va_gc>::value;
  422. }
  423. template <typename T>
  424. void
  425. gt_ggc_mx (fast_function_summary<T *, va_heap>* const &)
  426. {
  427. }
  428. template <typename T>
  429. void
  430. gt_pch_nx (fast_function_summary<T *, va_heap>* const &)
  431. {
  432. }
  433. template <typename T>
  434. void
  435. gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator,
  436. void *)
  437. {
  438. }
  439. template <typename T>
  440. void
  441. gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary)
  442. {
  443. ggc_test_and_set_mark (summary->m_vector);
  444. gt_ggc_mx (summary->m_vector);
  445. }
  446. template <typename T>
  447. void
  448. gt_pch_nx (fast_function_summary<T *, va_gc>* const &summary)
  449. {
  450. gt_pch_nx (summary->m_vector);
  451. }
  452. template <typename T>
  453. void
  454. gt_pch_nx (fast_function_summary<T *, va_gc>* const& summary,
  455. gt_pointer_operator op,
  456. void *cookie)
  457. {
  458. gt_pch_nx (summary->m_vector, op, cookie);
  459. }
  460. /* Base class for call_summary and fast_call_summary classes. */
  461. template <class T>
  462. class call_summary_base
  463. {
  464. public:
  465. /* Default construction takes SYMTAB as an argument. */
  466. call_summary_base (symbol_table *symtab): m_symtab (symtab),
  467. m_initialize_when_cloning (true), m_released (false)
  468. {}
  469. /* Basic implementation of removal operation. */
  470. virtual void remove (cgraph_edge *, T *) {}
  471. /* Basic implementation of duplication operation. */
  472. virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {}
  473. protected:
  474. /* Allocates new data that are stored within map. */
  475. T* allocate_new ()
  476. {
  477. /* Call gcc_internal_because we do not want to call finalizer for
  478. a type T. We call dtor explicitly. */
  479. return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ;
  480. }
  481. /* Release an item that is stored within map. */
  482. void release (T *item)
  483. {
  484. if (is_ggc ())
  485. {
  486. item->~T ();
  487. ggc_free (item);
  488. }
  489. else
  490. delete item;
  491. }
  492. /* Unregister all call-graph hooks. */
  493. void unregister_hooks ();
  494. /* Symbol table the summary is registered to. */
  495. symbol_table *m_symtab;
  496. /* Internal summary removal hook pointer. */
  497. cgraph_edge_hook_list *m_symtab_removal_hook;
  498. /* Internal summary duplication hook pointer. */
  499. cgraph_2edge_hook_list *m_symtab_duplication_hook;
  500. /* Initialize summary for an edge that is cloned. */
  501. bool m_initialize_when_cloning;
  502. /* Indicates if the summary is released. */
  503. bool m_released;
  504. private:
  505. /* Return true when the summary uses GGC memory for allocation. */
  506. virtual bool is_ggc () = 0;
  507. };
  508. template <typename T>
  509. void
  510. call_summary_base<T>::unregister_hooks ()
  511. {
  512. m_symtab->remove_edge_removal_hook (m_symtab_removal_hook);
  513. m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook);
  514. }
  515. /* An impossible class templated by non-pointers so, which makes sure that only
  516. summaries gathering pointers can be created. */
  517. template <class T>
  518. class call_summary
  519. {
  520. private:
  521. call_summary ();
  522. };
  523. /* Class to store auxiliary information about call graph edges. */
  524. template <class T>
  525. class GTY((user)) call_summary <T *>: public call_summary_base<T>
  526. {
  527. public:
  528. /* Default construction takes SYMTAB as an argument. */
  529. call_summary (symbol_table *symtab, bool ggc = false)
  530. : call_summary_base<T> (symtab), m_ggc (ggc), m_map (13, ggc)
  531. {
  532. this->m_symtab_removal_hook
  533. = this->m_symtab->add_edge_removal_hook (call_summary::symtab_removal,
  534. this);
  535. this->m_symtab_duplication_hook
  536. = this->m_symtab->add_edge_duplication_hook (call_summary::symtab_duplication,
  537. this);
  538. }
  539. /* Destructor. */
  540. virtual ~call_summary ()
  541. {
  542. release ();
  543. }
  544. /* Destruction method that can be called for GGC purpose. */
  545. using call_summary_base<T>::release;
  546. void release ();
  547. /* Traverses all summarys with an edge E called with
  548. ARG as argument. */
  549. template<typename Arg, bool (*f)(const T &, Arg)>
  550. void traverse (Arg a) const
  551. {
  552. m_map.traverse <f> (a);
  553. }
  554. /* Getter for summary callgraph edge pointer.
  555. If a summary for an edge does not exist, it will be created. */
  556. T* get_create (cgraph_edge *edge)
  557. {
  558. bool existed;
  559. T **v = &m_map.get_or_insert (edge->get_uid (), &existed);
  560. if (!existed)
  561. *v = this->allocate_new ();
  562. return *v;
  563. }
  564. /* Getter for summary callgraph edge pointer. */
  565. T* get (cgraph_edge *edge) ATTRIBUTE_PURE
  566. {
  567. T **v = m_map.get (edge->get_uid ());
  568. return v == NULL ? NULL : *v;
  569. }
  570. /* Remove edge from summary. */
  571. using call_summary_base<T>::remove;
  572. void remove (cgraph_edge *edge)
  573. {
  574. int uid = edge->get_uid ();
  575. T **v = m_map.get (uid);
  576. if (v)
  577. {
  578. m_map.remove (uid);
  579. this->release (*v);
  580. }
  581. }
  582. /* Return true if a summary for the given EDGE already exists. */
  583. bool exists (cgraph_edge *edge)
  584. {
  585. return m_map.get (edge->get_uid ()) != NULL;
  586. }
  587. /* Symbol removal hook that is registered to symbol table. */
  588. static void symtab_removal (cgraph_edge *edge, void *data);
  589. /* Symbol duplication hook that is registered to symbol table. */
  590. static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
  591. void *data);
  592. protected:
  593. /* Indication if we use ggc summary. */
  594. bool m_ggc;
  595. private:
  596. /* Indication if we use ggc summary. */
  597. virtual bool is_ggc ()
  598. {
  599. return m_ggc;
  600. }
  601. typedef int_hash <int, 0, -1> map_hash;
  602. /* Main summary store, where summary ID is used as key. */
  603. hash_map <map_hash, T *> m_map;
  604. template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &);
  605. template <typename U> friend void gt_pch_nx (call_summary <U *> * const &);
  606. template <typename U> friend void gt_pch_nx (call_summary <U *> * const &,
  607. gt_pointer_operator, void *);
  608. };
  609. template <typename T>
  610. void
  611. call_summary<T *>::release ()
  612. {
  613. if (this->m_released)
  614. return;
  615. this->unregister_hooks ();
  616. /* Release all summaries. */
  617. typedef typename hash_map <map_hash, T *>::iterator map_iterator;
  618. for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
  619. this->release ((*it).second);
  620. this->m_released = true;
  621. }
  622. template <typename T>
  623. void
  624. call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data)
  625. {
  626. call_summary *summary = (call_summary <T *> *) (data);
  627. summary->remove (edge);
  628. }
  629. template <typename T>
  630. void
  631. call_summary<T *>::symtab_duplication (cgraph_edge *edge1,
  632. cgraph_edge *edge2, void *data)
  633. {
  634. call_summary *summary = (call_summary <T *> *) (data);
  635. T *edge1_summary = NULL;
  636. if (summary->m_initialize_when_cloning)
  637. edge1_summary = summary->get_create (edge1);
  638. else
  639. edge1_summary = summary->get (edge1);
  640. if (edge1_summary)
  641. summary->duplicate (edge1, edge2, edge1_summary,
  642. summary->get_create (edge2));
  643. }
  644. template <typename T>
  645. void
  646. gt_ggc_mx(call_summary<T *>* const &summary)
  647. {
  648. gcc_checking_assert (summary->m_ggc);
  649. gt_ggc_mx (&summary->m_map);
  650. }
  651. template <typename T>
  652. void
  653. gt_pch_nx(call_summary<T *>* const &summary)
  654. {
  655. gcc_checking_assert (summary->m_ggc);
  656. gt_pch_nx (&summary->m_map);
  657. }
  658. template <typename T>
  659. void
  660. gt_pch_nx(call_summary<T *>* const& summary, gt_pointer_operator op,
  661. void *cookie)
  662. {
  663. gcc_checking_assert (summary->m_ggc);
  664. gt_pch_nx (&summary->m_map, op, cookie);
  665. }
  666. /* We want to pass just pointer types as argument for fast_call_summary
  667. template class. */
  668. template <class T, class V>
  669. class fast_call_summary
  670. {
  671. private:
  672. fast_call_summary ();
  673. };
  674. /* Call vector summary is a fast implementation of call_summary that
  675. utilizes vector as primary storage of summaries. */
  676. template <class T, class V>
  677. class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T>
  678. {
  679. public:
  680. /* Default construction takes SYMTAB as an argument. */
  681. fast_call_summary (symbol_table *symtab)
  682. : call_summary_base<T> (symtab), m_vector (NULL)
  683. {
  684. vec_alloc (m_vector, 13);
  685. this->m_symtab_removal_hook
  686. = this->m_symtab->add_edge_removal_hook (fast_call_summary::symtab_removal,
  687. this);
  688. this->m_symtab_duplication_hook
  689. = this->m_symtab->add_edge_duplication_hook (fast_call_summary::symtab_duplication,
  690. this);
  691. }
  692. /* Destructor. */
  693. virtual ~fast_call_summary ()
  694. {
  695. release ();
  696. }
  697. /* Destruction method that can be called for GGC purpose. */
  698. using call_summary_base<T>::release;
  699. void release ();
  700. /* Traverses all summarys with an edge F called with
  701. ARG as argument. */
  702. template<typename Arg, bool (*f)(const T &, Arg)>
  703. void traverse (Arg a) const
  704. {
  705. for (unsigned i = 0; i < m_vector->length (); i++)
  706. if ((*m_vector[i]) != NULL)
  707. f ((*m_vector)[i]);
  708. }
  709. /* Getter for summary callgraph edge pointer.
  710. If a summary for an edge does not exist, it will be created. */
  711. T* get_create (cgraph_edge *edge)
  712. {
  713. int id = edge->get_summary_id ();
  714. if (id == -1)
  715. id = this->m_symtab->assign_summary_id (edge);
  716. if ((unsigned)id >= m_vector->length ())
  717. vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id);
  718. if ((*m_vector)[id] == NULL)
  719. (*m_vector)[id] = this->allocate_new ();
  720. return (*m_vector)[id];
  721. }
  722. /* Getter for summary callgraph edge pointer. */
  723. T* get (cgraph_edge *edge) ATTRIBUTE_PURE
  724. {
  725. return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL;
  726. }
  727. /* Remove edge from summary. */
  728. using call_summary_base<T>::remove;
  729. void remove (cgraph_edge *edge)
  730. {
  731. if (exists (edge))
  732. {
  733. int id = edge->get_summary_id ();
  734. this->release ((*m_vector)[id]);
  735. (*m_vector)[id] = NULL;
  736. }
  737. }
  738. /* Return true if a summary for the given EDGE already exists. */
  739. bool exists (cgraph_edge *edge)
  740. {
  741. int id = edge->get_summary_id ();
  742. return (id != -1
  743. && (unsigned)id < m_vector->length ()
  744. && (*m_vector)[id] != NULL);
  745. }
  746. /* Symbol removal hook that is registered to symbol table. */
  747. static void symtab_removal (cgraph_edge *edge, void *data);
  748. /* Symbol duplication hook that is registered to symbol table. */
  749. static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2,
  750. void *data);
  751. private:
  752. virtual bool is_ggc ();
  753. /* Summary is stored in the vector. */
  754. vec <T *, V> *m_vector;
  755. template <typename U> friend void gt_ggc_mx (fast_call_summary <U *, va_gc> * const &);
  756. template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &);
  757. template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &,
  758. gt_pointer_operator, void *);
  759. };
  760. template <typename T, typename V>
  761. void
  762. fast_call_summary<T *, V>::release ()
  763. {
  764. if (this->m_released)
  765. return;
  766. this->unregister_hooks ();
  767. /* Release all summaries. */
  768. for (unsigned i = 0; i < m_vector->length (); i++)
  769. if ((*m_vector)[i] != NULL)
  770. this->release ((*m_vector)[i]);
  771. this->m_released = true;
  772. }
  773. template <typename T, typename V>
  774. void
  775. fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data)
  776. {
  777. fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
  778. summary->remove (edge);
  779. }
  780. template <typename T, typename V>
  781. void
  782. fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1,
  783. cgraph_edge *edge2, void *data)
  784. {
  785. fast_call_summary *summary = (fast_call_summary <T *, V> *) (data);
  786. T *edge1_summary = NULL;
  787. if (summary->m_initialize_when_cloning)
  788. edge1_summary = summary->get_create (edge1);
  789. else
  790. edge1_summary = summary->get (edge1);
  791. if (edge1_summary)
  792. {
  793. T *duplicate = summary->get_create (edge2);
  794. summary->duplicate (edge1, edge2, edge1_summary, duplicate);
  795. }
  796. }
  797. template <typename T, typename V>
  798. inline bool
  799. fast_call_summary<T *, V>::is_ggc ()
  800. {
  801. return is_same<V, va_gc>::value;
  802. }
  803. template <typename T>
  804. void
  805. gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary)
  806. {
  807. }
  808. template <typename T>
  809. void
  810. gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary)
  811. {
  812. }
  813. template <typename T>
  814. void
  815. gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary,
  816. gt_pointer_operator op,
  817. void *cookie)
  818. {
  819. }
  820. template <typename T>
  821. void
  822. gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary)
  823. {
  824. ggc_test_and_set_mark (summary->m_vector);
  825. gt_ggc_mx (&summary->m_vector);
  826. }
  827. template <typename T>
  828. void
  829. gt_pch_nx (fast_call_summary<T *, va_gc>* const &summary)
  830. {
  831. gt_pch_nx (&summary->m_vector);
  832. }
  833. template <typename T>
  834. void
  835. gt_pch_nx (fast_call_summary<T *, va_gc>* const& summary,
  836. gt_pointer_operator op,
  837. void *cookie)
  838. {
  839. gt_pch_nx (&summary->m_vector, op, cookie);
  840. }
  841. #endif /* GCC_SYMBOL_SUMMARY_H */