aopt.pas 9.0 KB

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