aopt.pas 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. var
  39. casmoptimizer : class of tasmoptimizer;
  40. procedure Optimize(AsmL:TAsmList);
  41. Implementation
  42. uses
  43. globtype, globals,
  44. verbose,
  45. aoptda,aoptcpu,aoptcpud;
  46. Constructor TAsmOptimizer.create(_AsmL: TAsmList);
  47. Begin
  48. inherited create(_asml,nil,nil,nil);
  49. {setup labeltable, always necessary}
  50. New(LabelInfo);
  51. End;
  52. procedure TAsmOptimizer.FindLoHiLabels;
  53. { Walks through the paasmlist to find the lowest and highest label number. }
  54. { Returns the last Pai object of the current block }
  55. Var LabelFound: Boolean;
  56. p: tai;
  57. Begin
  58. LabelInfo^.LowLabel := High(AWord);
  59. LabelInfo^.HighLabel := 0;
  60. LabelInfo^.LabelDif := 0;
  61. LabelInfo^.LabelTable:=nil;
  62. LabelFound := False;
  63. P := BlockStart;
  64. With LabelInfo^ Do
  65. Begin
  66. While Assigned(P) And
  67. ((P.typ <> Ait_Marker) Or
  68. (tai_Marker(P).Kind <> mark_AsmBlockStart)) Do
  69. Begin
  70. If (p.typ = ait_label) and
  71. (tai_Label(p).labsym.labeltype=alt_jump) and
  72. (tai_Label(p).labsym.is_used) Then
  73. Begin
  74. LabelFound := True;
  75. If (tai_Label(p).labsym.labelnr < int64(LowLabel)) Then
  76. LowLabel := tai_Label(p).labsym.labelnr;
  77. If (tai_Label(p).labsym.labelnr > int64(HighLabel)) Then
  78. HighLabel := tai_Label(p).labsym.labelnr
  79. End;
  80. GetNextInstruction(p, p)
  81. End;
  82. blockend:=p;
  83. If LabelFound
  84. Then LabelDif := HighLabel-LowLabel+1
  85. Else LabelDif := 0
  86. End
  87. End;
  88. Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
  89. { Builds a table with the locations of the labels in the TAsmList. }
  90. { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
  91. Var p{, hp1, hp2}: tai;
  92. {UsedRegs: TRegSet;}
  93. LabelIdx : longint;
  94. Begin
  95. {UsedRegs := [];}
  96. With LabelInfo^ Do
  97. If (LabelDif <> 0) Then
  98. Begin
  99. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  100. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  101. p := BlockStart;
  102. While (P <> BlockEnd) Do
  103. Begin
  104. Case p.typ Of
  105. ait_Label:
  106. begin
  107. If tai_label(p).labsym.is_used and
  108. (tai_Label(p).labsym.labeltype=alt_jump) then
  109. begin
  110. LabelIdx:=tai_label(p).labsym.labelnr-LowLabel;
  111. if LabelIdx>int64(LabelDif) then
  112. internalerror(200604202);
  113. LabelTable^[LabelIdx].PaiObj := p;
  114. end;
  115. end;
  116. ait_regAlloc:
  117. begin
  118. {!!!!!!!!!
  119. if tai_regalloc(p).ratype=ra_alloc then
  120. Begin
  121. If Not(tai_regalloc(p).Reg in UsedRegs) Then
  122. UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
  123. Else
  124. Begin
  125. hp1 := p;
  126. hp2 := nil;
  127. While GetLastInstruction(hp1, hp1) And
  128. Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
  129. hp2:=hp1;
  130. If hp2<>nil Then
  131. Begin
  132. hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
  133. InsertLLItem(tai(hp2.previous), hp2, hp1);
  134. End;
  135. End;
  136. End
  137. else
  138. Begin
  139. UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
  140. hp1 := p;
  141. hp2 := nil;
  142. While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
  143. GetNextInstruction(hp1, hp1) And
  144. RegInInstruction(tai_regalloc(p).Reg, hp1) Do
  145. hp2 := hp1;
  146. If hp2 <> nil Then
  147. Begin
  148. hp1 := tai(p.previous);
  149. AsmL.Remove(p);
  150. InsertLLItem(hp2, tai(hp2.Next), p);
  151. p := hp1;
  152. End
  153. End
  154. };
  155. End
  156. End;
  157. P := tai(p.Next);
  158. While Assigned(p) and
  159. (p <> blockend) and
  160. (p.typ in (SkipInstr - [ait_regalloc])) Do
  161. P := tai(P.Next)
  162. End;
  163. End
  164. End;
  165. procedure tasmoptimizer.clear;
  166. begin
  167. if assigned(LabelInfo^.labeltable) then
  168. begin
  169. freemem(LabelInfo^.labeltable);
  170. LabelInfo^.labeltable := nil;
  171. end;
  172. LabelInfo^.labeldif:=0;
  173. LabelInfo^.lowlabel:=high(AWord);
  174. LabelInfo^.highlabel:=0;
  175. end;
  176. procedure tasmoptimizer.pass_1;
  177. begin
  178. findlohilabels;
  179. BuildLabelTableAndFixRegAlloc;
  180. end;
  181. Procedure TAsmOptimizer.Optimize;
  182. Var
  183. HP: tai;
  184. pass: longint;
  185. Begin
  186. pass:=0;
  187. BlockStart := tai(AsmL.First);
  188. pass_1;
  189. While Assigned(BlockStart) Do
  190. Begin
  191. if pass = 0 then
  192. PrePeepHoleOpts;
  193. { Peephole optimizations }
  194. PeepHoleOptPass1;
  195. { Only perform them twice in the first pass }
  196. if pass = 0 then
  197. PeepHoleOptPass1;
  198. If (cs_opt_asmcse in current_settings.optimizerswitches) Then
  199. Begin
  200. // DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
  201. { data flow analyzer }
  202. // DFA.DoDFA;
  203. { common subexpression elimination }
  204. { CSE;}
  205. End;
  206. { more peephole optimizations }
  207. PeepHoleOptPass2;
  208. { if pass = last_pass then }
  209. PostPeepHoleOpts;
  210. { free memory }
  211. clear;
  212. { continue where we left off, BlockEnd is either the start of an }
  213. { assembler block or nil}
  214. BlockStart := BlockEnd;
  215. While Assigned(BlockStart) And
  216. (BlockStart.typ = ait_Marker) And
  217. (tai_Marker(BlockStart).Kind = mark_AsmBlockStart) Do
  218. Begin
  219. { we stopped at an assembler block, so skip it }
  220. While GetNextInstruction(BlockStart, BlockStart) And
  221. ((BlockStart.Typ <> Ait_Marker) Or
  222. (tai_Marker(Blockstart).Kind <> mark_AsmBlockEnd)) Do;
  223. { blockstart now contains a tai_marker(mark_AsmBlockEnd) }
  224. If GetNextInstruction(BlockStart, HP) And
  225. ((HP.typ <> ait_Marker) Or
  226. (Tai_Marker(HP).Kind <> mark_AsmBlockStart)) Then
  227. { There is no assembler block anymore after the current one, so }
  228. { optimize the next block of "normal" instructions }
  229. pass_1
  230. { Otherwise, skip the next assembler block }
  231. else
  232. blockStart := hp;
  233. End
  234. End;
  235. End;
  236. Destructor TAsmOptimizer.Destroy;
  237. Begin
  238. Dispose(LabelInfo)
  239. End;
  240. procedure Optimize(AsmL:TAsmList);
  241. var
  242. p : TAsmOptimizer;
  243. begin
  244. p:=casmoptimizer.Create(AsmL);
  245. p.Optimize;
  246. p.free
  247. end;
  248. end.