2
0

aopt.pas 9.7 KB

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