optcse.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. {
  2. Common subexpression elimination on base blocks
  3. Copyright (c) 2005 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 optcse;
  18. {$i fpcdefs.inc}
  19. { $define csedebug}
  20. interface
  21. uses
  22. node;
  23. function do_optcse(var rootnode : tnode) : tnode;
  24. implementation
  25. uses
  26. globtype,
  27. cclasses,
  28. nutils,
  29. nbas,nld,
  30. pass_1,
  31. symtype,symdef;
  32. const
  33. cseinvariant : set of tnodetype = [loadn,addn,muln,subn,divn,slashn,modn,andn,orn,xorn,notn,vecn,
  34. derefn,equaln,unequaln,ltn,gtn,lten,gten,typeconvn,subscriptn];
  35. function searchsubdomain(var n:tnode; arg: pointer) : foreachnoderesult;
  36. begin
  37. if not(n.nodetype in cseinvariant) then
  38. begin
  39. pboolean(arg)^:=false;
  40. result:=fen_norecurse_true;
  41. end
  42. else
  43. result:=fen_true;
  44. end;
  45. type
  46. tlists = record
  47. nodelist : tfplist;
  48. locationlist : tfplist;
  49. end;
  50. plists = ^tlists;
  51. pnode = ^tnode;
  52. function collectnodes(var n:tnode; arg: pointer) : foreachnoderesult;
  53. begin
  54. { node worth to add? }
  55. if (node_complexity(n)>1) and (tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) then
  56. begin
  57. plists(arg)^.nodelist.Add(n);
  58. plists(arg)^.locationlist.Add(@n);
  59. result:=fen_false;
  60. end
  61. else
  62. result:=fen_norecurse_false;
  63. end;
  64. function searchcsedomain(var n: tnode; arg: pointer) : foreachnoderesult;
  65. var
  66. csedomain : boolean;
  67. lists : tlists;
  68. templist : tfplist;
  69. i,j : longint;
  70. def : tstoreddef;
  71. nodes : tblocknode;
  72. creates,
  73. statements : tstatementnode;
  74. hp : ttempcreatenode;
  75. begin
  76. result:=fen_false;
  77. if n.nodetype in cseinvariant then
  78. begin
  79. csedomain:=true;
  80. foreachnodestatic(pm_postprocess,n,@searchsubdomain,@csedomain);
  81. { found a cse domain }
  82. if csedomain then
  83. begin
  84. statements:=nil;
  85. result:=fen_norecurse_true;
  86. {$ifdef csedebug}
  87. writeln('============ cse domain ==================');
  88. printnode(output,n);
  89. {$endif csedebug}
  90. lists.nodelist:=tfplist.create;
  91. lists.locationlist:=tfplist.create;
  92. foreachnodestatic(pm_postprocess,n,@collectnodes,@lists);
  93. templist:=tfplist.create;
  94. templist.count:=lists.nodelist.count;
  95. { this is poorly coded, just comparing every node with all other nodes }
  96. for i:=0 to lists.nodelist.count-1 do
  97. for j:=i+1 to lists.nodelist.count-1 do
  98. begin
  99. if tnode(lists.nodelist[i]).isequal(tnode(lists.nodelist[j])) then
  100. begin
  101. if not(assigned(statements)) then
  102. begin
  103. nodes:=internalstatements(statements);
  104. addstatement(statements,internalstatements(creates));
  105. end;
  106. {$ifdef csedebug}
  107. writeln(' ==== ');
  108. printnode(output,tnode(lists.nodelist[i]));
  109. writeln(' equals ');
  110. printnode(output,tnode(lists.nodelist[j]));
  111. writeln(' ==== ');
  112. {$endif csedebug}
  113. def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
  114. if assigned(templist[i]) then
  115. begin
  116. templist[j]:=templist[i];
  117. pnode(lists.locationlist[j])^.free;
  118. pnode(lists.locationlist[j])^:=ctemprefnode.create(ttempcreatenode(templist[j]));
  119. do_firstpass(pnode(lists.locationlist[j])^);
  120. end
  121. else
  122. begin
  123. templist[i]:=ctempcreatenode.create(def,def.size,tt_persistent,
  124. def.is_intregable or def.is_fpuregable);
  125. addstatement(creates,tnode(templist[i]));
  126. { properties can't be passed by var }
  127. hp:=ttempcreatenode(templist[i]);
  128. do_firstpass(tnode(hp));
  129. addstatement(statements,cassignmentnode.create(ctemprefnode.create(ttempcreatenode(templist[i])),
  130. tnode(lists.nodelist[i])));
  131. pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[i]));
  132. do_firstpass(pnode(lists.locationlist[i])^);
  133. templist[j]:=templist[i];
  134. pnode(lists.locationlist[j])^.free;
  135. pnode(lists.locationlist[j])^:=ctemprefnode.create(ttempcreatenode(templist[j]));
  136. do_firstpass(pnode(lists.locationlist[j])^);
  137. {$ifdef csedebug}
  138. printnode(output,statements);
  139. {$endif csedebug}
  140. end;
  141. end;
  142. end;
  143. if assigned(statements) then
  144. begin
  145. addstatement(statements,n);
  146. n:=nodes;
  147. do_firstpass(n);
  148. {$ifdef csedebug}
  149. printnode(output,nodes);
  150. {$endif csedebug}
  151. end;
  152. {$ifdef csedebug}
  153. writeln('nodes: ',lists.nodelist.count);
  154. writeln('==========================================');
  155. {$endif csedebug}
  156. lists.nodelist.free;
  157. lists.locationlist.free;
  158. templist.free;
  159. end
  160. end;
  161. end;
  162. function do_optcse(var rootnode : tnode) : tnode;
  163. begin
  164. foreachnodestatic(pm_postprocess,rootnode,@searchcsedomain,nil);
  165. result:=nil;
  166. (*
  167. { create a linear list of nodes }
  168. { create hash values }
  169. { sort by hash values, taking care of nf_csebarrier and keeping the
  170. original order of the nodes }
  171. { compare nodes with equal hash values }
  172. { search barrier }
  173. for i:=0 to nodelist.length-1 do
  174. begin
  175. { and then search backward so we get always the largest equal trees }
  176. j:=i+1;
  177. { collect equal nodes }
  178. while (j<=nodelist.length-1) and
  179. nodelist[i].docompare(nodelist[j]) do
  180. inc(j);
  181. dec(j);
  182. if j>i then
  183. begin
  184. { cse found }
  185. { create temp. location }
  186. { replace first node by
  187. - temp. creation
  188. - expression calculation
  189. - assignment of expression to temp. }
  190. tempnode:=ctempcreatenode.create(nodelist[i].resultdef,nodelist[i].resultdef.size,tt_persistent,
  191. nodelist[i].resultdef.is_intregable or nodelist[i].resultdef.is_fpuregable);
  192. addstatement(createstatement,tempnode);
  193. addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
  194. caddrnode.create_internal(para.left)));
  195. para.left := ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),para.left.resultdef);
  196. addstatement(deletestatement,ctempdeletenode.create(tempnode));
  197. { replace next nodes by loading the temp. reference }
  198. { replace last node by loading the temp. reference and
  199. delete the temp. }
  200. end;
  201. end;
  202. *)
  203. end;
  204. end.