aopt.pas 8.6 KB

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