您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

966 行
26KB

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