optutils.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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,last : 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. { returns true, if n is a valid node and has life info }
  40. function has_life_info(n : tnode) : boolean;
  41. implementation
  42. uses
  43. verbose,
  44. optbase,
  45. ncal,nbas,nflw,nutils,nset,ncon;
  46. function TIndexedNodeSet.Add(node : tnode) : boolean;
  47. var
  48. i : Integer;
  49. p : tnode;
  50. begin
  51. node.allocoptinfo;
  52. p:=Includes(node);
  53. if assigned(p) then
  54. begin
  55. result:=false;
  56. node.optinfo^.index:=p.optinfo^.index;
  57. end
  58. else
  59. begin
  60. i:=inherited Add(node);
  61. node.optinfo^.index:=i;
  62. result:=true;
  63. end
  64. end;
  65. function TIndexedNodeSet.Includes(node : tnode) : tnode;
  66. var
  67. i : longint;
  68. begin
  69. for i:=0 to Count-1 do
  70. if tnode(List^[i]).isequal(node) then
  71. begin
  72. result:=tnode(List^[i]);
  73. exit;
  74. end;
  75. result:=nil;
  76. end;
  77. function TIndexedNodeSet.Remove(node : tnode) : boolean;
  78. var
  79. p : tnode;
  80. begin
  81. result:=false;
  82. p:=Includes(node);
  83. if assigned(p) then
  84. begin
  85. if inherited Remove(p)<>-1 then
  86. result:=true;
  87. end;
  88. end;
  89. procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
  90. var
  91. i : integer;
  92. begin
  93. for i:=0 to s.count-1 do
  94. begin
  95. writeln(f,'=============================== Node ',i,' ===============================');
  96. printnode(f,tnode(s[i]));
  97. writeln(f);
  98. end;
  99. end;
  100. function PrintNodeDFA(var n: tnode; arg: pointer): foreachnoderesult;
  101. begin
  102. if assigned(n.optinfo) and ((n.optinfo^.life<>nil) or (n.optinfo^.use<>nil) or (n.optinfo^.def<>nil)) then
  103. begin
  104. write(text(arg^),nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,') Life: ');
  105. PrintDFASet(text(arg^),n.optinfo^.life);
  106. write(text(arg^),' Def: ');
  107. PrintDFASet(text(arg^),n.optinfo^.def);
  108. write(text(arg^),' Use: ');
  109. PrintDFASet(text(arg^),n.optinfo^.use);
  110. if assigned(n.successor) then
  111. write(text(arg^),' Successor: ',nodetype2str[n.successor.nodetype],'(',n.successor.fileinfo.line,',',n.successor.fileinfo.column,')')
  112. else
  113. write(text(arg^),' Successor: nil');
  114. write(text(arg^),' DefSum: ');
  115. PrintDFASet(text(arg^),n.optinfo^.defsum);
  116. writeln(text(arg^));
  117. end;
  118. result:=fen_false;
  119. end;
  120. procedure PrintDFAInfo(var f : text;p : tnode);
  121. begin
  122. foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
  123. end;
  124. procedure SetNodeSucessors(p,last : tnode);
  125. var
  126. Continuestack : TFPList;
  127. Breakstack : TFPList;
  128. { sets the successor nodes of a node tree block
  129. returns the first node of the tree if it's a controll flow node }
  130. function DoSet(p : tnode;succ : tnode) : tnode;
  131. var
  132. hp1,hp2 : tnode;
  133. i : longint;
  134. begin
  135. result:=nil;
  136. if p=nil then
  137. exit;
  138. case p.nodetype of
  139. statementn:
  140. begin
  141. hp1:=p;
  142. result:=p;
  143. while assigned(hp1) do
  144. begin
  145. { does another statement follow? }
  146. if assigned(tstatementnode(hp1).next) then
  147. begin
  148. hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
  149. if assigned(hp2) then
  150. tstatementnode(hp1).successor:=hp2
  151. else
  152. tstatementnode(hp1).successor:=tstatementnode(hp1).next;
  153. end
  154. else
  155. begin
  156. hp2:=DoSet(tstatementnode(hp1).statement,succ);
  157. if assigned(hp2) then
  158. tstatementnode(hp1).successor:=hp2
  159. else
  160. tstatementnode(hp1).successor:=succ;
  161. end;
  162. hp1:=tstatementnode(hp1).next;
  163. end;
  164. end;
  165. blockn:
  166. begin
  167. result:=p;
  168. DoSet(tblocknode(p).statements,succ);
  169. if assigned(tblocknode(p).statements) then
  170. p.successor:=tblocknode(p).statements
  171. else
  172. p.successor:=succ;
  173. end;
  174. forn:
  175. begin
  176. Breakstack.Add(succ);
  177. Continuestack.Add(p);
  178. result:=p;
  179. { the successor of the last node of the for body is the dummy loop iteration node
  180. it allows the dfa to inject needed life information into the loop }
  181. tfornode(p).loopiteration:=cnothingnode.create;
  182. DoSet(tfornode(p).t2,tfornode(p).loopiteration);
  183. p.successor:=succ;
  184. Breakstack.Delete(Breakstack.Count-1);
  185. Continuestack.Delete(Continuestack.Count-1);
  186. end;
  187. breakn:
  188. begin
  189. result:=p;
  190. p.successor:=tnode(Breakstack.Last);
  191. end;
  192. continuen:
  193. begin
  194. result:=p;
  195. p.successor:=tnode(Continuestack.Last);
  196. end;
  197. whilerepeatn:
  198. begin
  199. Breakstack.Add(succ);
  200. Continuestack.Add(p);
  201. result:=p;
  202. { the successor of the last node of the while/repeat body is the while node itself }
  203. DoSet(twhilerepeatnode(p).right,p);
  204. p.successor:=succ;
  205. { special case: we do not do a dyn. dfa, but we should handle endless loops }
  206. if is_constboolnode(twhilerepeatnode(p).left) then
  207. begin
  208. if ((lnf_testatbegin in twhilerepeatnode(p).loopflags) and
  209. getbooleanvalue(twhilerepeatnode(p).left)) or (not(lnf_testatbegin in twhilerepeatnode(p).loopflags) and
  210. not(getbooleanvalue(twhilerepeatnode(p).left))) then
  211. p.successor:=nil;
  212. end;
  213. Breakstack.Delete(Breakstack.Count-1);
  214. Continuestack.Delete(Continuestack.Count-1);
  215. end;
  216. ifn:
  217. begin
  218. result:=p;
  219. DoSet(tifnode(p).right,succ);
  220. DoSet(tifnode(p).t1,succ);
  221. p.successor:=succ;
  222. end;
  223. labeln:
  224. begin
  225. result:=p;
  226. if assigned(tlabelnode(p).left) then
  227. begin
  228. DoSet(tlabelnode(p).left,succ);
  229. p.successor:=tlabelnode(p).left;
  230. end
  231. else
  232. p.successor:=succ;
  233. end;
  234. assignn:
  235. begin
  236. result:=p;
  237. p.successor:=succ;
  238. end;
  239. goton:
  240. begin
  241. result:=p;
  242. if not(assigned(tgotonode(p).labelnode)) then
  243. internalerror(2007050701);
  244. p.successor:=tgotonode(p).labelnode;
  245. end;
  246. exitn:
  247. begin
  248. result:=p;
  249. p.successor:=nil;
  250. end;
  251. casen:
  252. begin
  253. result:=p;
  254. DoSet(tcasenode(p).elseblock,succ);
  255. for i:=0 to tcasenode(p).blocks.count-1 do
  256. DoSet(pcaseblock(tcasenode(p).blocks[i])^.statement,succ);
  257. p.successor:=succ;
  258. end;
  259. calln:
  260. begin
  261. { not sure if this is enough (FK) }
  262. result:=p;
  263. if not(cnf_call_never_returns in tcallnode(p).callnodeflags) then
  264. p.successor:=succ;
  265. end;
  266. inlinen:
  267. begin
  268. { not sure if this is enough (FK) }
  269. result:=p;
  270. p.successor:=succ;
  271. end;
  272. loadn,
  273. tempcreaten,
  274. tempdeleten,
  275. nothingn:
  276. begin
  277. result:=p;
  278. p.successor:=succ;
  279. end;
  280. raisen:
  281. begin
  282. result:=p;
  283. { raise never returns }
  284. p.successor:=nil;
  285. end;
  286. withn,
  287. tryexceptn,
  288. tryfinallyn,
  289. onn:
  290. internalerror(2007050501);
  291. end;
  292. end;
  293. begin
  294. Breakstack:=TFPList.Create;
  295. Continuestack:=TFPList.Create;
  296. DoSet(p,last);
  297. Continuestack.Free;
  298. Breakstack.Free;
  299. end;
  300. var
  301. sum : TDFASet;
  302. function adddef(var n: tnode; arg: pointer): foreachnoderesult;
  303. begin
  304. if assigned(n.optinfo) then
  305. DFASetIncludeSet(sum,n.optinfo^.def);
  306. Result:=fen_false;
  307. end;
  308. procedure CalcDefSum(p : tnode);
  309. begin
  310. p.allocoptinfo;
  311. if not assigned(p.optinfo^.defsum) then
  312. begin
  313. sum:=nil;
  314. foreachnodestatic(pm_postprocess,p,@adddef,nil);
  315. p.optinfo^.defsum:=sum;
  316. end;
  317. end;
  318. function has_life_info(n : tnode) : boolean;
  319. begin
  320. result:=assigned(n) and assigned(n.optinfo) and
  321. assigned(n.optinfo^.life);
  322. end;
  323. end.