aopt.pas 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. {
  2. Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
  3. Development Team
  4. This unit contains the interface routines between the code generator
  5. and the optimizer.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. Unit aopt;
  20. {$i fpcdefs.inc}
  21. Interface
  22. Uses
  23. aasmbase,aasmtai,aasmdata,aasmcpu,
  24. aoptobj;
  25. Type
  26. TAsmOptimizer = class(TAoptObj)
  27. { _AsmL is the PAasmOutpout list that has to be optimized }
  28. Constructor create(_AsmL: TAsmList); virtual; reintroduce;
  29. { call the necessary optimizer procedures }
  30. Procedure Optimize;
  31. Destructor destroy;override;
  32. private
  33. procedure FindLoHiLabels;
  34. Procedure BuildLabelTableAndFixRegAlloc;
  35. procedure clear;
  36. procedure pass_1;
  37. End;
  38. TAsmOptimizerClass = class of TAsmOptimizer;
  39. var
  40. casmoptimizer : TAsmOptimizerClass;
  41. procedure Optimize(AsmL:TAsmList);
  42. Implementation
  43. uses
  44. globtype, globals,
  45. verbose,
  46. aoptda,aoptcpu,aoptcpud;
  47. Constructor TAsmOptimizer.create(_AsmL: TAsmList);
  48. Begin
  49. inherited create(_asml,nil,nil,nil);
  50. {setup labeltable, always necessary}
  51. New(LabelInfo);
  52. End;
  53. procedure TAsmOptimizer.FindLoHiLabels;
  54. { Walks through the paasmlist to find the lowest and highest label number. }
  55. { Returns the last Pai object of the current block }
  56. Var LabelFound: Boolean;
  57. p: tai;
  58. Begin
  59. LabelInfo^.LowLabel := High(longint);
  60. LabelInfo^.HighLabel := 0;
  61. LabelInfo^.LabelDif := 0;
  62. LabelInfo^.LabelTable:=nil;
  63. LabelFound := False;
  64. P := BlockStart;
  65. With LabelInfo^ Do
  66. Begin
  67. While Assigned(P) And
  68. ((P.typ <> Ait_Marker) Or
  69. (tai_Marker(P).Kind <> mark_AsmBlockStart)) Do
  70. Begin
  71. If (p.typ = ait_label) and
  72. (tai_Label(p).labsym.labeltype=alt_jump) and
  73. (tai_Label(p).labsym.is_used) Then
  74. Begin
  75. LabelFound := True;
  76. If (tai_Label(p).labsym.labelnr < LowLabel) Then
  77. LowLabel := tai_Label(p).labsym.labelnr;
  78. If (tai_Label(p).labsym.labelnr > HighLabel) Then
  79. HighLabel := tai_Label(p).labsym.labelnr
  80. End;
  81. GetNextInstruction(p, p)
  82. End;
  83. blockend:=p;
  84. If LabelFound
  85. Then LabelDif := HighLabel-LowLabel+1
  86. Else LabelDif := 0
  87. End
  88. End;
  89. Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
  90. { Builds a table with the locations of the labels in the TAsmList. }
  91. { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
  92. Var p{, hp1, hp2}: tai;
  93. {UsedRegs: TRegSet;}
  94. LabelIdx : longint;
  95. Begin
  96. {UsedRegs := [];}
  97. With LabelInfo^ Do
  98. If (LabelDif <> 0) Then
  99. Begin
  100. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  101. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  102. p := BlockStart;
  103. While (P <> BlockEnd) Do
  104. Begin
  105. Case p.typ Of
  106. ait_Label:
  107. begin
  108. If tai_label(p).labsym.is_used and
  109. (tai_Label(p).labsym.labeltype=alt_jump) then
  110. begin
  111. LabelIdx:=tai_label(p).labsym.labelnr-LowLabel;
  112. if LabelIdx>int64(LabelDif) then
  113. internalerror(200604202);
  114. LabelTable^[LabelIdx].PaiObj := p;
  115. end;
  116. end;
  117. ait_regAlloc:
  118. begin
  119. {!!!!!!!!!
  120. if tai_regalloc(p).ratype=ra_alloc then
  121. Begin
  122. If Not(tai_regalloc(p).Reg in UsedRegs) Then
  123. UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
  124. Else
  125. Begin
  126. hp1 := p;
  127. hp2 := nil;
  128. While GetLastInstruction(hp1, hp1) And
  129. Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
  130. hp2:=hp1;
  131. If hp2<>nil Then
  132. Begin
  133. hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
  134. InsertLLItem(tai(hp2.previous), hp2, hp1);
  135. End;
  136. End;
  137. End
  138. else
  139. Begin
  140. UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
  141. hp1 := p;
  142. hp2 := nil;
  143. While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
  144. GetNextInstruction(hp1, hp1) And
  145. RegInInstruction(tai_regalloc(p).Reg, hp1) Do
  146. hp2 := hp1;
  147. If hp2 <> nil Then
  148. Begin
  149. hp1 := tai(p.previous);
  150. AsmL.Remove(p);
  151. InsertLLItem(hp2, tai(hp2.Next), p);
  152. p := hp1;
  153. End
  154. End
  155. };
  156. End
  157. End;
  158. P := tai(p.Next);
  159. While Assigned(p) and
  160. (p <> blockend) and
  161. (p.typ in (SkipInstr - [ait_regalloc])) Do
  162. P := tai(P.Next)
  163. End;
  164. End
  165. End;
  166. procedure tasmoptimizer.clear;
  167. begin
  168. if assigned(LabelInfo^.labeltable) then
  169. begin
  170. freemem(LabelInfo^.labeltable);
  171. LabelInfo^.labeltable := nil;
  172. end;
  173. LabelInfo^.labeldif:=0;
  174. LabelInfo^.lowlabel:=high(longint);
  175. LabelInfo^.highlabel:=0;
  176. end;
  177. procedure tasmoptimizer.pass_1;
  178. begin
  179. findlohilabels;
  180. BuildLabelTableAndFixRegAlloc;
  181. end;
  182. Procedure TAsmOptimizer.Optimize;
  183. Var
  184. HP: tai;
  185. pass: longint;
  186. Begin
  187. pass:=0;
  188. BlockStart := tai(AsmL.First);
  189. pass_1;
  190. While Assigned(BlockStart) Do
  191. Begin
  192. if pass = 0 then
  193. PrePeepHoleOpts;
  194. { Peephole optimizations }
  195. PeepHoleOptPass1;
  196. { Only perform them twice in the first pass }
  197. if pass = 0 then
  198. PeepHoleOptPass1;
  199. If (cs_opt_asmcse in current_settings.optimizerswitches) Then
  200. Begin
  201. // DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
  202. { data flow analyzer }
  203. // DFA.DoDFA;
  204. { common subexpression elimination }
  205. { CSE;}
  206. End;
  207. { more peephole optimizations }
  208. PeepHoleOptPass2;
  209. { if pass = last_pass then }
  210. PostPeepHoleOpts;
  211. { free memory }
  212. clear;
  213. { continue where we left off, BlockEnd is either the start of an }
  214. { assembler block or nil}
  215. BlockStart := BlockEnd;
  216. While Assigned(BlockStart) And
  217. (BlockStart.typ = ait_Marker) And
  218. (tai_Marker(BlockStart).Kind = mark_AsmBlockStart) Do
  219. Begin
  220. { we stopped at an assembler block, so skip it }
  221. While GetNextInstruction(BlockStart, BlockStart) And
  222. ((BlockStart.Typ <> Ait_Marker) Or
  223. (tai_Marker(Blockstart).Kind <> mark_AsmBlockEnd)) Do;
  224. { blockstart now contains a tai_marker(mark_AsmBlockEnd) }
  225. If GetNextInstruction(BlockStart, HP) And
  226. ((HP.typ <> ait_Marker) Or
  227. (Tai_Marker(HP).Kind <> mark_AsmBlockStart)) Then
  228. { There is no assembler block anymore after the current one, so }
  229. { optimize the next block of "normal" instructions }
  230. pass_1
  231. { Otherwise, skip the next assembler block }
  232. else
  233. blockStart := hp;
  234. End
  235. End;
  236. End;
  237. Destructor TAsmOptimizer.Destroy;
  238. Begin
  239. Dispose(LabelInfo)
  240. End;
  241. procedure Optimize(AsmL:TAsmList);
  242. var
  243. p : TAsmOptimizer;
  244. begin
  245. p:=casmoptimizer.Create(AsmL);
  246. p.Optimize;
  247. p.free
  248. end;
  249. end.