optdfa.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. {
  2. DFA
  3. Copyright (c) 2007 by Florian Klaempfl
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {$define DEBUG_DFA}
  18. { this unit implements routines to perform dfa }
  19. unit optdfa;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node;
  24. { reset all dfa info, this is required before creating dfa info
  25. if the tree has been changed without updating dfa }
  26. procedure resetdfainfo(node : tnode);
  27. procedure createdfainfo(node : tnode);
  28. implementation
  29. uses
  30. globtype,globals,
  31. verbose,
  32. cpuinfo,
  33. symdef,
  34. nutils,
  35. nbas,nflw,ncon,ninl,ncal,
  36. optbase,optutils;
  37. (*
  38. function initnodes(var n:tnode; arg: pointer) : foreachnoderesult;
  39. begin
  40. { node worth to add? }
  41. if (node_complexity(n)>1) and (tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) then
  42. begin
  43. plists(arg)^.nodelist.Add(n);
  44. plists(arg)^.locationlist.Add(@n);
  45. result:=fen_false;
  46. end
  47. else
  48. result:=fen_norecurse_false;
  49. end;
  50. *)
  51. {
  52. x:=f; read: [f]
  53. while x do read: []
  54. a:=b; read: [a,b,d] def: [a] life: read*def=[a]
  55. c:=d; read: [a,d] def: [a,c] life: read*def=[a]
  56. e:=a; read: [a] def: [a,c,e] life: read*def=[a]
  57. function f(b,d,x : type) : type;
  58. begin
  59. while x do alive: b,d,x
  60. begin
  61. a:=b; alive: b,d,x
  62. c:=d; alive: a,d,x
  63. e:=a+c; alive: a,c,x
  64. dec(x); alive: c,e,x
  65. end;
  66. result:=c+e; alive: c,e
  67. end; alive: result
  68. }
  69. type
  70. tdfainfo = record
  71. use : PDFASet;
  72. def : PDFASet;
  73. map : TIndexedNodeSet
  74. end;
  75. pdfainfo = ^tdfainfo;
  76. function AddDefUse(var n: tnode; arg: pointer): foreachnoderesult;
  77. begin
  78. case n.nodetype of
  79. loadn:
  80. begin
  81. pdfainfo(arg)^.map.Add(n);
  82. if nf_write in n.flags then
  83. DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
  84. else
  85. DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
  86. {
  87. write('Use Set: ');
  88. PrintDFASet(output,pdfainfo(arg)^.use^);
  89. write(' Def Set: ');
  90. PrintDFASet(output,pdfainfo(arg)^.def^);
  91. writeln;
  92. }
  93. end;
  94. end;
  95. result:=fen_false;
  96. end;
  97. procedure CreateLifeInfo(node : tnode;map : TIndexedNodeSet);
  98. var
  99. changed : boolean;
  100. procedure CreateInfo(node : tnode);
  101. { update life entry of a node with l, set changed if this changes
  102. life info for the node
  103. }
  104. procedure updatelifeinfo(n : tnode;l : TDFASet);
  105. var
  106. b : boolean;
  107. begin
  108. b:=DFASetNotEqual(l,n.optinfo^.life);
  109. {
  110. if b then
  111. begin
  112. printnode(output,n);
  113. printdfaset(output,l);
  114. writeln;
  115. printdfaset(output,n.optinfo^.life);
  116. writeln;
  117. end;
  118. }
  119. changed:=changed or b;
  120. node.optinfo^.life:=l;
  121. end;
  122. procedure calclife(n : tnode);
  123. var
  124. l : TDFASet;
  125. begin
  126. if assigned(n.successor) then
  127. begin
  128. {
  129. write('Successor Life: ');
  130. printdfaset(output,n.successor.optinfo^.life);
  131. writeln;
  132. write('Def.');
  133. printdfaset(output,n.optinfo^.def);
  134. writeln;
  135. }
  136. { ensure we can access optinfo }
  137. DFASetDiff(l,n.successor.optinfo^.life,n.optinfo^.def);
  138. {
  139. printdfaset(output,l);
  140. writeln;
  141. }
  142. DFASetIncludeSet(l,n.optinfo^.use);
  143. DFASetIncludeSet(l,n.optinfo^.life);
  144. end
  145. else
  146. l:=n.optinfo^.use;
  147. updatelifeinfo(n,l);
  148. end;
  149. var
  150. dfainfo : tdfainfo;
  151. l : TDFASet;
  152. begin
  153. if node=nil then
  154. exit;
  155. { ensure we've already optinfo set }
  156. node.allocoptinfo;
  157. if nf_processing in node.flags then
  158. exit;
  159. include(node.flags,nf_processing);
  160. if assigned(node.successor) then
  161. CreateInfo(node.successor);
  162. { life:=succesorlive-definition+use }
  163. case node.nodetype of
  164. whilerepeatn:
  165. begin
  166. calclife(node);
  167. if lnf_testatbegin in twhilerepeatnode(node).loopflags then
  168. begin
  169. node.allocoptinfo;
  170. if not(assigned(node.optinfo^.def)) and
  171. not(assigned(node.optinfo^.use)) then
  172. begin
  173. dfainfo.use:[email protected]^.use;
  174. dfainfo.def:[email protected]^.def;
  175. dfainfo.map:=map;
  176. foreachnodestatic(pm_postprocess,twhilerepeatnode(node).left,@AddDefUse,@dfainfo);
  177. end;
  178. calclife(node);
  179. { now iterate through the loop }
  180. CreateInfo(twhilerepeatnode(node).right);
  181. { update while node }
  182. { life:=life+use+right.life }
  183. l:=node.optinfo^.life;
  184. DFASetIncludeSet(l,node.optinfo^.use);
  185. DFASetIncludeSet(l,twhilerepeatnode(node).right.optinfo^.life);
  186. UpdateLifeInfo(node,l);
  187. { ... and a second iteration for fast convergence }
  188. CreateInfo(twhilerepeatnode(node).right);
  189. end;
  190. end;
  191. assignn:
  192. begin
  193. if not(assigned(node.optinfo^.def)) and
  194. not(assigned(node.optinfo^.use)) then
  195. begin
  196. dfainfo.use:[email protected]^.use;
  197. dfainfo.def:[email protected]^.def;
  198. dfainfo.map:=map;
  199. foreachnodestatic(pm_postprocess,node,@AddDefUse,@dfainfo);
  200. end;
  201. calclife(node);
  202. end;
  203. statementn:
  204. begin
  205. { nested statement }
  206. CreateInfo(tstatementnode(node).statement);
  207. { inherit info }
  208. node.optinfo^.life:=tstatementnode(node).statement.optinfo^.life;
  209. end;
  210. blockn:
  211. begin
  212. CreateInfo(tblocknode(node).statements);
  213. if assigned(tblocknode(node).statements) then
  214. node.optinfo^.life:=tblocknode(node).statements.optinfo^.life;
  215. end;
  216. ifn:
  217. begin
  218. { get information from cond. expression }
  219. if not(assigned(node.optinfo^.def)) and
  220. not(assigned(node.optinfo^.use)) then
  221. begin
  222. dfainfo.use:[email protected]^.use;
  223. dfainfo.def:[email protected]^.def;
  224. dfainfo.map:=map;
  225. foreachnodestatic(pm_postprocess,tifnode(node).left,@AddDefUse,@dfainfo);
  226. end;
  227. { create life info for left and right node }
  228. CreateInfo(tifnode(node).right);
  229. CreateInfo(tifnode(node).t1);
  230. { ensure that we don't remove life info }
  231. l:=node.optinfo^.life;
  232. { get life info from then branch }
  233. if assigned(tifnode(node).right) then
  234. DFASetIncludeSet(l,tifnode(node).right.optinfo^.life);
  235. { get life info from else branch }
  236. if assigned(tifnode(node).t1) then
  237. DFASetIncludeSet(l,tifnode(node).t1.optinfo^.life)
  238. else
  239. if assigned(node.successor) then
  240. DFASetIncludeSet(l,node.successor.optinfo^.life);
  241. { add use info from cond. expression }
  242. DFASetIncludeSet(l,tifnode(node).optinfo^.use);
  243. { finally, update the life info of the node }
  244. UpdateLifeInfo(node,l);
  245. end;
  246. goton:
  247. begin
  248. calclife(node);
  249. end;
  250. labeln:
  251. begin
  252. calclife(node);
  253. end;
  254. else
  255. internalerror(2007050502);
  256. end;
  257. exclude(node.flags,nf_processing);
  258. end;
  259. var
  260. runs : integer;
  261. begin
  262. runs:=0;
  263. repeat
  264. inc(runs);
  265. changed:=false;
  266. CreateInfo(node);
  267. {$ifdef DEBUG_DFA}
  268. PrintIndexedNodeSet(output,map);
  269. PrintDFAInfo(output,node);
  270. {$endif DEBUG_DFA}
  271. until not(changed);
  272. {$ifdef DEBUG_DFA}
  273. writeln('DFA solver iterations: ',runs);
  274. {$endif DEBUG_DFA}
  275. end;
  276. { reset all dfa info, this is required before creating dfa info
  277. if the tree has been changed without updating dfa }
  278. procedure resetdfainfo(node : tnode);
  279. begin
  280. end;
  281. procedure createdfainfo(node : tnode);
  282. var
  283. map : TIndexedNodeSet;
  284. begin
  285. map:=TIndexedNodeSet.Create;
  286. { add controll flow information }
  287. SetNodeSucessors(node);
  288. { now, collect life information }
  289. CreateLifeInfo(node,map);
  290. map.free;
  291. end;
  292. end.