aopt.pas 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. {
  2. $Id$
  3. Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
  4. Development Team
  5. This unit contains the interface routines between the code generator
  6. and the optimizer.
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. Unit aopt;
  21. {$i fpcdefs.inc}
  22. Interface
  23. Uses
  24. aasmbase,aasmtai,aasmcpu,
  25. aoptobj;
  26. Type
  27. TAsmOptimizer = class(TAoptObj)
  28. { _AsmL is the PAasmOutpout list that has to be optimized }
  29. Constructor create(_AsmL: taasmoutput);
  30. { call the necessary optimizer procedures }
  31. Procedure Optimize;
  32. Destructor destroy;override;
  33. private
  34. procedure FindLoHiLabels;
  35. Procedure BuildLabelTableAndFixRegAlloc;
  36. procedure clear;
  37. procedure pass_1;
  38. End;
  39. var
  40. casmoptimizer : class of tasmoptimizer;
  41. procedure Optimize(AsmL:taasmoutput);
  42. Implementation
  43. uses
  44. globtype, globals,
  45. aoptda,aoptcpu,aoptcpud;
  46. Constructor TAsmOptimizer.create(_AsmL: taasmoutput);
  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, prev: 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. prev := p;
  65. With LabelInfo^ Do
  66. Begin
  67. While Assigned(P) And
  68. ((P.typ <> Ait_Marker) Or
  69. (tai_Marker(P).Kind <> AsmBlockStart)) Do
  70. Begin
  71. If (p.typ = ait_label) Then
  72. If (tai_Label(p).l.is_used) Then
  73. Begin
  74. LabelFound := True;
  75. If (tai_Label(p).l.labelnr < LowLabel) Then
  76. LowLabel := tai_Label(p).l.labelnr;
  77. If (tai_Label(p).l.labelnr > HighLabel) Then
  78. HighLabel := tai_Label(p).l.labelnr
  79. End;
  80. prev := p;
  81. GetNextInstruction(p, p)
  82. End;
  83. if (prev.typ = ait_marker) and
  84. (tai_marker(prev).kind = asmblockstart) then
  85. blockend := prev
  86. else blockend := nil;
  87. If LabelFound
  88. Then LabelDif := HighLabel-LowLabel+1
  89. Else LabelDif := 0
  90. End
  91. End;
  92. Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
  93. { Builds a table with the locations of the labels in the taasmoutput. }
  94. { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
  95. Var p, hp1, hp2: tai;
  96. UsedRegs: TRegSet;
  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. If tai_label(p).l.is_used Then
  110. LabelTable^[tai_label(p).l.labelnr-LowLabel].PaiObj := p;
  111. ait_regAlloc:
  112. begin
  113. {!!!!!!!!!
  114. if tai_regalloc(p).ratype=ra_alloc then
  115. Begin
  116. If Not(tai_regalloc(p).Reg in UsedRegs) Then
  117. UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
  118. Else
  119. Begin
  120. hp1 := p;
  121. hp2 := nil;
  122. While GetLastInstruction(hp1, hp1) And
  123. Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
  124. hp2:=hp1;
  125. If hp2<>nil Then
  126. Begin
  127. hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
  128. InsertLLItem(tai(hp2.previous), hp2, hp1);
  129. End;
  130. End;
  131. End
  132. else
  133. Begin
  134. UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
  135. hp1 := p;
  136. hp2 := nil;
  137. While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
  138. GetNextInstruction(hp1, hp1) And
  139. RegInInstruction(tai_regalloc(p).Reg, hp1) Do
  140. hp2 := hp1;
  141. If hp2 <> nil Then
  142. Begin
  143. hp1 := tai(p.previous);
  144. AsmL.Remove(p);
  145. InsertLLItem(hp2, tai(hp2.Next), p);
  146. p := hp1;
  147. End
  148. End
  149. };
  150. End
  151. End;
  152. P := tai(p.Next);
  153. While Assigned(p) and
  154. (p <> blockend) and
  155. (p.typ in (SkipInstr - [ait_regalloc])) Do
  156. P := tai(P.Next)
  157. End;
  158. End
  159. End;
  160. procedure tasmoptimizer.clear;
  161. begin
  162. if LabelInfo^.labeldif <> 0 then
  163. begin
  164. freemem(LabelInfo^.labeltable);
  165. LabelInfo^.labeltable := nil;
  166. end;
  167. end;
  168. procedure tasmoptimizer.pass_1;
  169. begin
  170. findlohilabels;
  171. BuildLabelTableAndFixRegAlloc;
  172. end;
  173. Procedure TAsmOptimizer.Optimize;
  174. Var
  175. HP: tai;
  176. pass: longint;
  177. Begin
  178. pass:=0;
  179. BlockStart := tai(AsmL.First);
  180. pass_1;
  181. While Assigned(BlockStart) Do
  182. Begin
  183. if pass = 0 then
  184. PrePeepHoleOpts;
  185. { Peephole optimizations }
  186. PeepHoleOptPass1;
  187. { Only perform them twice in the first pass }
  188. if pass = 0 then
  189. PeepHoleOptPass1;
  190. If (cs_slowoptimize in aktglobalswitches) Then
  191. Begin
  192. // DFA:=TAOptDFACpu.Create(AsmL,BlockStart,BlockEnd,LabelInfo);
  193. { data flow analyzer }
  194. // DFA.DoDFA;
  195. { common subexpression elimination }
  196. { CSE;}
  197. End;
  198. { more peephole optimizations }
  199. { PeepHoleOptPass2;}
  200. { free memory }
  201. clear;
  202. { continue where we left off, BlockEnd is either the start of an }
  203. { assembler block or nil}
  204. BlockStart := BlockEnd;
  205. While Assigned(BlockStart) And
  206. (BlockStart.typ = ait_Marker) And
  207. (tai_Marker(BlockStart).Kind = AsmBlockStart) Do
  208. Begin
  209. { we stopped at an assembler block, so skip it }
  210. While GetNextInstruction(BlockStart, BlockStart) And
  211. ((BlockStart.Typ <> Ait_Marker) Or
  212. (tai_Marker(Blockstart).Kind <> AsmBlockEnd)) Do;
  213. { blockstart now contains a tai_marker(asmblockend) }
  214. If GetNextInstruction(BlockStart, HP) And
  215. ((HP.typ <> ait_Marker) Or
  216. (Tai_Marker(HP).Kind <> AsmBlockStart)) Then
  217. { There is no assembler block anymore after the current one, so }
  218. { optimize the next block of "normal" instructions }
  219. pass_1
  220. { Otherwise, skip the next assembler block }
  221. else
  222. blockStart := hp;
  223. End
  224. End;
  225. End;
  226. Destructor TAsmOptimizer.Destroy;
  227. Begin
  228. Dispose(LabelInfo)
  229. End;
  230. procedure Optimize(AsmL:taasmoutput);
  231. var
  232. p : TAsmOptimizer;
  233. begin
  234. p:=casmoptimizer.Create(AsmL);
  235. p.Optimize;
  236. p.free
  237. end;
  238. begin
  239. casmoptimizer:=TAsmOptimizer;
  240. end.
  241. {Virtual methods, most have to be overridden by processor dependent methods}
  242. {
  243. $Log$
  244. Revision 1.10 2005-02-26 01:26:59 jonas
  245. * fixed generic jumps optimizer and enabled it for ppc (the label table
  246. was not being initialised -> getfinaldestination always failed, which
  247. caused wrong optimizations in some cases)
  248. * changed the inverse_cond into a function, because tasmcond is a record
  249. on ppc
  250. + added a compare_conditions() function for the same reason
  251. Revision 1.9 2005/02/14 17:13:06 peter
  252. * truncate log
  253. }