optutils.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. {
  2. Helper routines for the optimizer
  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. unit optutils;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,
  22. node;
  23. type
  24. { this implementation should be really improved,
  25. its purpose is to find equal nodes }
  26. TIndexedNodeSet = class(TFPList)
  27. function Add(node : tnode) : boolean;
  28. function Includes(node : tnode) : tnode;
  29. function Remove(node : tnode) : boolean;
  30. end;
  31. procedure SetNodeSucessors(p : tnode);
  32. procedure PrintDFAInfo(var f : text;p : tnode);
  33. procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
  34. { determines the optinfo.defsum field for the given node
  35. this field contains a sum of all expressions defined by
  36. all child expressions reachable through p
  37. }
  38. procedure CalcDefSum(p : tnode);
  39. implementation
  40. uses
  41. verbose,
  42. optbase,
  43. nbas,nflw,nutils,nset;
  44. function TIndexedNodeSet.Add(node : tnode) : boolean;
  45. var
  46. i : Integer;
  47. p : tnode;
  48. begin
  49. node.allocoptinfo;
  50. p:=Includes(node);
  51. if assigned(p) then
  52. begin
  53. result:=false;
  54. node.optinfo^.index:=p.optinfo^.index;
  55. end
  56. else
  57. begin
  58. i:=inherited Add(node);
  59. node.optinfo^.index:=i;
  60. result:=true;
  61. end
  62. end;
  63. function TIndexedNodeSet.Includes(node : tnode) : tnode;
  64. var
  65. i : longint;
  66. begin
  67. for i:=0 to Count-1 do
  68. if tnode(List^[i]).isequal(node) then
  69. begin
  70. result:=tnode(List^[i]);
  71. exit;
  72. end;
  73. result:=nil;
  74. end;
  75. function TIndexedNodeSet.Remove(node : tnode) : boolean;
  76. var
  77. p : tnode;
  78. begin
  79. result:=false;
  80. p:=Includes(node);
  81. if assigned(p) then
  82. begin
  83. if inherited Remove(p)<>-1 then
  84. result:=true;
  85. end;
  86. end;
  87. procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
  88. var
  89. i : integer;
  90. begin
  91. for i:=0 to s.count-1 do
  92. begin
  93. writeln(f,'=============================== Node ',i,' ===============================');
  94. printnode(f,tnode(s[i]));
  95. writeln(f);
  96. end;
  97. end;
  98. function PrintNodeDFA(var n: tnode; arg: pointer): foreachnoderesult;
  99. begin
  100. if assigned(n.optinfo) and ((n.optinfo^.life<>nil) or (n.optinfo^.use<>nil) or (n.optinfo^.def<>nil)) then
  101. begin
  102. write(text(arg^),nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,') Life: ');
  103. PrintDFASet(text(arg^),n.optinfo^.life);
  104. write(text(arg^),' Def: ');
  105. PrintDFASet(text(arg^),n.optinfo^.def);
  106. write(text(arg^),' Use: ');
  107. PrintDFASet(text(arg^),n.optinfo^.use);
  108. writeln(text(arg^));
  109. end;
  110. result:=fen_false;
  111. end;
  112. procedure PrintDFAInfo(var f : text;p : tnode);
  113. begin
  114. foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
  115. end;
  116. procedure SetNodeSucessors(p : tnode);
  117. var
  118. Continuestack : TFPList;
  119. Breakstack : TFPList;
  120. { sets the successor nodes of a node tree block
  121. returns the first node of the tree if it's a controll flow node }
  122. function DoSet(p : tnode;succ : tnode) : tnode;
  123. var
  124. hp1,hp2 : tnode;
  125. i : longint;
  126. begin
  127. result:=nil;
  128. if p=nil then
  129. exit;
  130. case p.nodetype of
  131. statementn:
  132. begin
  133. hp1:=p;
  134. result:=p;
  135. while assigned(hp1) do
  136. begin
  137. { does another statement follow? }
  138. if assigned(tstatementnode(hp1).next) then
  139. begin
  140. hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
  141. if assigned(hp2) then
  142. tstatementnode(hp1).successor:=hp2
  143. else
  144. tstatementnode(hp1).successor:=tstatementnode(hp1).next;
  145. end
  146. else
  147. begin
  148. hp2:=DoSet(tstatementnode(hp1).statement,succ);
  149. if assigned(hp2) then
  150. tstatementnode(hp1).successor:=hp2
  151. else
  152. tstatementnode(hp1).successor:=succ;
  153. end;
  154. hp1:=tstatementnode(hp1).next;
  155. end;
  156. end;
  157. blockn:
  158. begin
  159. result:=p;
  160. DoSet(tblocknode(p).statements,succ);
  161. p.successor:=succ;
  162. end;
  163. forn:
  164. begin
  165. Breakstack.Add(succ);
  166. Continuestack.Add(p);
  167. result:=p;
  168. { the successor of the last node of the for body is the for node itself }
  169. DoSet(tfornode(p).t2,p);
  170. Breakstack.Delete(Breakstack.Count-1);
  171. Continuestack.Delete(Continuestack.Count-1);
  172. p.successor:=succ;
  173. end;
  174. breakn:
  175. begin
  176. result:=p;
  177. p.successor:=tnode(Breakstack.Last);
  178. end;
  179. continuen:
  180. begin
  181. result:=p;
  182. p.successor:=tnode(Continuestack.Last);
  183. end;
  184. whilerepeatn:
  185. begin
  186. Breakstack.Add(succ);
  187. Continuestack.Add(p);
  188. result:=p;
  189. { the successor of the last node of the while body is the while node itself }
  190. DoSet(twhilerepeatnode(p).right,p);
  191. p.successor:=succ;
  192. Breakstack.Delete(Breakstack.Count-1);
  193. Continuestack.Delete(Continuestack.Count-1);
  194. end;
  195. ifn:
  196. begin
  197. result:=p;
  198. DoSet(tifnode(p).right,succ);
  199. DoSet(tifnode(p).t1,succ);
  200. p.successor:=succ;
  201. end;
  202. labeln:
  203. begin
  204. result:=p;
  205. if assigned(tlabelnode(p).left) then
  206. begin
  207. DoSet(tlabelnode(p).left,succ);
  208. p.successor:=tlabelnode(p).left;
  209. end
  210. else
  211. p.successor:=succ;
  212. end;
  213. assignn:
  214. begin
  215. result:=p;
  216. p.successor:=succ;
  217. end;
  218. goton:
  219. begin
  220. result:=p;
  221. if not(assigned(tgotonode(p).labelnode)) then
  222. internalerror(2007050701);
  223. p.successor:=tgotonode(p).labelnode;
  224. end;
  225. exitn:
  226. begin
  227. result:=p;
  228. p.successor:=nil;
  229. end;
  230. casen:
  231. begin
  232. result:=p;
  233. DoSet(tcasenode(p).elseblock,succ);
  234. for i:=0 to tcasenode(p).blocks.count-1 do
  235. DoSet(pcaseblock(tcasenode(p).blocks[i])^.statement,succ);
  236. p.successor:=succ;
  237. end;
  238. calln:
  239. begin
  240. { not sure if this is enough (FK) }
  241. result:=p;
  242. p.successor:=succ;
  243. end;
  244. inlinen:
  245. begin
  246. { not sure if this is enough (FK) }
  247. result:=p;
  248. p.successor:=succ;
  249. end;
  250. tempcreaten,
  251. tempdeleten,
  252. nothingn:
  253. begin
  254. result:=p;
  255. p.successor:=succ;
  256. end;
  257. raisen:
  258. begin
  259. result:=p;
  260. { raise never returns }
  261. p.successor:=nil;
  262. end;
  263. withn,
  264. tryexceptn,
  265. tryfinallyn,
  266. onn:
  267. internalerror(2007050501);
  268. end;
  269. end;
  270. begin
  271. Breakstack:=TFPList.Create;
  272. Continuestack:=TFPList.Create;
  273. DoSet(p,nil);
  274. Continuestack.Free;
  275. Breakstack.Free;
  276. end;
  277. var
  278. sum : TDFASet;
  279. function adddef(var n: tnode; arg: pointer): foreachnoderesult;
  280. begin
  281. if assigned(n.optinfo) then
  282. DFASetIncludeSet(sum,n.optinfo^.def);
  283. Result:=fen_false;
  284. end;
  285. procedure CalcDefSum(p : tnode);
  286. begin
  287. p.allocoptinfo;
  288. if not assigned(p.optinfo^.defsum) then
  289. begin
  290. sum:=nil;
  291. foreachnodestatic(pm_postprocess,p,@adddef,nil);
  292. p.optinfo^.defsum:=sum;
  293. end;
  294. end;
  295. end.