PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/optimize/wpa/Def_use.cpp

http://phc.googlecode.com/
C++ | 478 lines | 277 code | 69 blank | 132 comment | 31 complexity | ce37a93a40140428a370f97798ae7490 MD5 | raw file
Possible License(s): GPL-2.0, 0BSD, BSD-3-Clause, Unlicense, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. * phc -- the open source PHP compiler
  3. * See doc/license/README.license for licensing information
  4. *
  5. *
  6. * Def-use information.
  7. *
  8. * Gather the def-use information while the alias analysis is running.
  9. *
  10. *
  11. * What are we trying to model with Def-use? Just DCE!!
  12. * - So how can we tell if a statement needs to be killed?
  13. * - It doesnt have any useful defs
  14. *
  15. *
  16. * - How can we tell if a whole function is useful?
  17. * - Get all of its defs/may-defs:
  18. * - some of them will be for external definitions:
  19. * - ie globals, parameters, returned values
  20. *
  21. *
  22. * Lets think about the storage, do we want UD/DU chains? Suppose we use ST->x,
  23. * do we need to record the change of ST? No. Therefore we just care about
  24. * index nodes.
  25. *
  26. *
  27. * We keep track of index nodes at 2 levels:
  28. * - ref level:
  29. * - a def uses the ref
  30. * - a ref-def ref-defs the ref-def
  31. * - a ref-def ref-uses the ref-use
  32. * - value level
  33. * - a def defs the value
  34. * - a use uses the value
  35. *
  36. * OK, so given
  37. * 1. $y =& $z;
  38. * 2. $x =& $y;
  39. * 3. $z = 5;
  40. * 4. var_dump ($x);
  41. *
  42. * we need to be sure that enough things are used to be correct:
  43. * - 4 uses $x
  44. * - 3 defs x-value, y-value, z-value, uses x-ref, y-ref and z-ref
  45. * - 2 defs x-ref
  46. * - 1 defs y-ref
  47. *
  48. * What about:
  49. * 0. $c =& $z;
  50. * 1. $y =& $z;
  51. * 2. $x =& $y;
  52. * 3. $z = 5;
  53. * 4. var_dump ($x);
  54. *
  55. * We are overly conservative, since all refs are in the BB. This currently does
  56. * - 4 uses $x
  57. * - 3 defs x-value, y-value, z-value, c-value, uses x-ref, y-ref, z-ref, c-ref
  58. * - 2 defs x-ref
  59. * - 1 defs y-ref
  60. *
  61. * We'd like to:
  62. * - 4 uses $x
  63. * - 3 defs x-value, uses x-ref in a CHI node. defs z-value, uses z-ref in the main block
  64. * - 2 defs x-ref (used by 3), uses y-ref
  65. * - 1 defs y-ref (used by 2), uses z-ref
  66. * - 0 does nothing (unless there is an implicit definition in 4, but there isnt).
  67. *
  68. *
  69. *
  70. * Reference definitions
  71. * Given $x =& $y
  72. * - the is an implicit def to $y, and $y is later used.
  73. * - the value def to $x and implicit one to $y are both already modelled. Nothing special.
  74. *
  75. * - $y (or any of its references) is later defed (but only if $x is used)
  76. * - it will be noted that there is a ref-def of $x a ref-def of $y. A
  77. * ref-use comes up when there is a normal def or a normal use.
  78. *
  79. * - $x is later defed (but only if $y or its refs are used)
  80. * - that will be a ref-use of $x, meaning the corresponding ref-def
  81. * is important.
  82. *
  83. * - $x is later used
  84. * - that will be a use of the normal def associated with $y
  85. *
  86. *
  87. * May-ref/must-def
  88. * - if there is a kill for a variable first, it is a must-def. If there is
  89. * not, it is a may-def. Uses arent split into may- and must- defs.
  90. *
  91. *
  92. * Supporting interprocedural-optimizations (inlining and escape-analysis):
  93. * - We have to make a summary of what is def-ed within the function.
  94. * - How easy is it to calculate what escapes?
  95. *
  96. *
  97. */
  98. #include "Def_use.h"
  99. #include "Points_to.h"
  100. using namespace std;
  101. using namespace boost;
  102. using namespace MIR;
  103. Def_use::Def_use (Whole_program* wp)
  104. : WPA (wp)
  105. {
  106. }
  107. reftype reftypes[] = { REF, VAL };
  108. deftype deftypes[] = { DEF, MAYDEF, USE };
  109. #define foreach_dtrt foreach_rtdt
  110. #define foreach_rtdt \
  111. foreach (reftype rt, reftypes) \
  112. foreach (deftype dt, deftypes)
  113. bool
  114. Def_use::equals (WPA* wpa)
  115. {
  116. Def_use* other = dyc<Def_use> (wpa);
  117. return this->maps.equals (&other->maps);
  118. }
  119. string debug_name (reftype rt, deftype dt)
  120. {
  121. string result = (rt == REF) ? "REF" : "VAL";
  122. result += "-";
  123. if (dt == DEF) result += "DEF";
  124. else if (dt == MAYDEF) result += "MAYDEF";
  125. else if (dt == USE) result += "USE";
  126. else phc_unreachable ();
  127. return result;
  128. }
  129. void
  130. Def_use::dump_set (Context* cx, reftype rt, deftype dt) const
  131. {
  132. string set_name = debug_name (rt, dt);
  133. if (maps[cx][rt][dt].size())
  134. {
  135. cdebug << cx << ": " << set_name << " list: ";
  136. foreach (const Index_node* name, maps[cx][rt][dt])
  137. cdebug << name->str() << ", ";
  138. cdebug << endl;
  139. }
  140. else
  141. cdebug << cx << ": No " << set_name << " results" << endl;
  142. }
  143. void
  144. Def_use::dump (Context* cx, Result_state, string comment) const
  145. {
  146. // Print out the results for existing BBs (done this way so that IN and OUT
  147. // results are presented together).
  148. foreach_rtdt
  149. dump_set (cx, rt, dt);
  150. string st_name = "__MAIN__";
  151. if (!cx->is_outer ())
  152. st_name = cx->symtable_name ();
  153. foreach_rtdt
  154. {
  155. string set_name = debug_name (rt, dt);
  156. if (summary_maps[st_name][rt][dt].size())
  157. {
  158. cdebug << st_name << " (summary): " << set_name << " list: ";
  159. foreach (const Index_node* name, summary_maps[st_name][rt][dt])
  160. cdebug << name->str() << ", ";
  161. cdebug << endl;
  162. }
  163. else
  164. cdebug << st_name << ": No summary " << set_name << " results" << endl;
  165. }
  166. }
  167. void
  168. Def_use::dump_everything (string comment) const
  169. {
  170. foreach (Context* cx, *maps.keys ())
  171. dump (cx, R_OUT, comment);
  172. }
  173. /*
  174. * References
  175. */
  176. void
  177. Def_use::create_reference (Context* cx, const Index_node* lhs, const Index_node* rhs, Certainty cert)
  178. {
  179. // A may-ref is a must-def with no killing
  180. if (has (cx, REF, DEF, lhs))
  181. record (cx, REF, MAYDEF, lhs);
  182. record (cx, REF, USE, rhs);
  183. // Although we know the actual value, we can rarely propagate it, so the
  184. // tends to be needed here (if this statement is not needed, it will
  185. // probably be killed).
  186. record (cx, VAL, USE, rhs);
  187. }
  188. /*
  189. * Value
  190. */
  191. void
  192. Def_use::kill_value (Context* cx, const Index_node* lhs, bool also_kill_refs)
  193. {
  194. record (cx, VAL, DEF, lhs);
  195. record (cx, REF, USE, lhs);
  196. if (also_kill_refs)
  197. record (cx, REF, DEF, lhs);
  198. }
  199. void
  200. Def_use::assign_value (Context* cx, const Index_node* lhs, const Storage_node*)
  201. {
  202. if (not has (cx, VAL, DEF, lhs))
  203. record (cx, VAL, MAYDEF, lhs);
  204. record (cx, REF, USE, lhs);
  205. }
  206. void
  207. Def_use::record_use (Context* cx, const Index_node* use, Certainty cert)
  208. {
  209. record (cx, REF, USE, use);
  210. record (cx, VAL, USE, use);
  211. }
  212. void
  213. Def_use::record (Context* cx, reftype rt, deftype dt, const Index_node* index)
  214. {
  215. if (index->storage == "FAKE")
  216. return;
  217. maps[cx][rt][dt].insert (index);
  218. }
  219. bool
  220. Def_use::has (Context* cx, reftype rt, deftype dt, const Index_node* index) const
  221. {
  222. return maps[cx][rt][dt].has (index);
  223. }
  224. /* Interprocedural support */
  225. // TODO: the caller should use __RETNAME__ in the callee if it has a LHS. If
  226. // LHS is not used, it will be cleaned up with iteration.
  227. bool
  228. in_scope (Context* cx, const Index_node* index)
  229. {
  230. // Index_node index_nodes put the name of the symtable as the prefix.
  231. return index->storage == cx->symtable_name ();
  232. }
  233. void
  234. Def_use::finish_block (Context* cx)
  235. {
  236. string symtable = cx->symtable_name ();
  237. // All defs/uses which are out of scope must be recorded in the function
  238. // summary.
  239. foreach_rtdt
  240. {
  241. foreach (const Index_node* index, maps[cx][rt][dt])
  242. {
  243. if (not in_scope (cx, index))
  244. summary_maps[symtable][rt][dt].insert (index);
  245. }
  246. }
  247. // The exit block must "use" all out-of-scope defs, or they'll be killed
  248. // later.
  249. foreach_dtrt
  250. {
  251. if (dt == USE)
  252. continue;
  253. foreach (const Index_node* index, maps[cx][rt][dt])
  254. {
  255. Context* exit_cx = Context::as_peer (cx, cx->get_bb()->cfg->get_exit_bb ());
  256. if (not in_scope (cx, index))
  257. maps[exit_cx][rt][USE].insert (index);
  258. }
  259. }
  260. }
  261. void
  262. Def_use::merge_contexts ()
  263. {
  264. // TODO: fix storage_nodes in summary_*
  265. foreach (Context* cx, *maps.keys ())
  266. {
  267. Context* new_cx = cx->get_non_contextual ();
  268. foreach_dtrt
  269. {
  270. Set<const Index_node*> new_map;
  271. foreach (const Index_node *index, maps[cx][rt][dt])
  272. new_map.insert (index->convert_context_name ());
  273. maps[new_cx][rt][dt] = new_map;
  274. }
  275. }
  276. }
  277. bool
  278. Def_use::has_analysis_result (Context* cx, Result_state state) const
  279. {
  280. return maps.has (cx);
  281. }
  282. void
  283. Def_use::backward_bind (Context* caller, Context* exit)
  284. {
  285. string st_name = exit->symtable_name ();
  286. foreach_dtrt
  287. {
  288. Set<const Index_node*>& set = summary_maps[st_name][rt][dt];
  289. maps[caller][rt][dt].insert (set.begin(), set.end ());
  290. }
  291. }
  292. cIndex_node_list*
  293. Def_use::get_index_nodes (Basic_block* bb, deftype dt) const
  294. {
  295. cIndex_node_list* result = new cIndex_node_list;
  296. Context* cx = Context::non_contextual (bb);
  297. foreach (const Index_node* name, maps[cx][VAL][dt])
  298. result->push_back (name->get_starred_name ());
  299. foreach (const Index_node* name, maps[cx][REF][dt])
  300. result->push_back (name);
  301. return result;
  302. }
  303. int
  304. Def_use::get_num_refs (CFG* cfg, deftype dt, bool entryexit)
  305. {
  306. int res = 0;
  307. foreach (Basic_block* bb, *cfg->get_all_bbs ())
  308. {
  309. if ((entryexit || !((dynamic_cast<Entry_block*> (bb))
  310. || (dynamic_cast<Exit_block*> (bb)))))
  311. {
  312. Context* cx = Context::non_contextual (bb);
  313. res += maps[cx][REF][dt].size ();
  314. /* foreach (const Index_node* in, maps[cx][REF][dt])
  315. {
  316. if ((cx->get_bb ()->cfg) && in_scope (cx, in))
  317. res++;
  318. }
  319. */
  320. }
  321. }
  322. return res;
  323. }
  324. int
  325. Def_use::get_num_vals (CFG* cfg, deftype dt, bool entryexit)
  326. {
  327. int res = 0;
  328. foreach (Basic_block* bb, *cfg->get_all_bbs ())
  329. {
  330. if ((entryexit || !((dynamic_cast<Entry_block*> (bb))
  331. || (dynamic_cast<Exit_block*> (bb)))))
  332. {
  333. Context* cx = Context::non_contextual (bb);
  334. res += maps[cx][VAL][dt].size ();
  335. /* foreach (const Index_node* in, maps[cx][REF][dt])
  336. {
  337. if ((cx->get_bb ()->cfg) && in_scope (cx, in))
  338. res++;
  339. }
  340. */
  341. }
  342. }
  343. return res;
  344. }
  345. cIndex_node_list*
  346. Def_use::get_defs (Basic_block* bb) const
  347. {
  348. return get_index_nodes (bb, DEF);
  349. }
  350. cIndex_node_list*
  351. Def_use::get_may_defs (Basic_block* bb) const
  352. {
  353. return get_index_nodes (bb, MAYDEF);
  354. }
  355. cIndex_node_list*
  356. Def_use::get_uses (Basic_block* bb) const
  357. {
  358. return get_index_nodes (bb, USE);
  359. }
  360. void
  361. Def_use::insert_index_node (Basic_block* bb, const Index_node *name, deftype dt)
  362. {
  363. Context* cx = Context::non_contextual (bb);
  364. // Only insert non starred nodes.
  365. if (!name->is_starred()) {
  366. maps[cx][VAL][dt].insert(name);
  367. maps[cx][REF][dt].insert(name);
  368. }
  369. }
  370. void
  371. Def_use::insert_def(Basic_block *bb, const Index_node *name)
  372. {
  373. insert_index_node(bb, name, DEF);
  374. }
  375. void
  376. Def_use::insert_may_def(Basic_block *bb, const Index_node *name)
  377. {
  378. insert_index_node(bb, name, MAYDEF);
  379. }
  380. void
  381. Def_use::insert_use(Basic_block *bb, const Index_node *name)
  382. {
  383. insert_index_node(bb, name, USE);
  384. }
  385. void
  386. Def_use::remove_index_node (Basic_block* bb, const Index_node *name, deftype dt)
  387. {
  388. Context* cx = Context::non_contextual (bb);
  389. // Only remove non starred nodes.
  390. if (!name->is_starred()) {
  391. maps[cx][VAL][dt].erase(name);
  392. maps[cx][REF][dt].erase(name);
  393. }
  394. }
  395. void
  396. Def_use::remove_def(Basic_block *bb, const Index_node *name)
  397. {
  398. remove_index_node(bb, name, DEF);
  399. }
  400. void
  401. Def_use::remove_may_def(Basic_block *bb, const Index_node *name)
  402. {
  403. remove_index_node(bb, name, MAYDEF);
  404. }
  405. void
  406. Def_use::remove_use(Basic_block *bb, const Index_node *name)
  407. {
  408. remove_index_node(bb, name, USE);
  409. }