aopt.pas 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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. Interface
  22. Uses Aasmbase,aasmtai,aasmcpu, cobjects, aoptobj, aoptcpud, aoptcpub {aoptcs, aoptpeep} ;
  23. Type
  24. PAsmOptimizer = ^TAsmOptimizer;
  25. TAsmOptimizer = Object(TAoptObj)
  26. { _AsmL is the PAasmOutpout list that has to be optimized }
  27. Constructor Init(_AsmL: PAasmOutput);
  28. { call the necessary optimizer procedures }
  29. Procedure Optimize;
  30. Destructor Done;
  31. private
  32. Function FindLoHiLabels: Pai;
  33. Procedure BuildLabelTableAndFixRegAlloc;
  34. End;
  35. procedure Optimize(AsmL:Paasmoutput);
  36. Implementation
  37. uses cpuinfo, globtype, globals;
  38. Constructor TAsmOptimizer.Init(_AsmL: PAasmOutput);
  39. Begin
  40. AsmL := _AsmL;
  41. {setup labeltable, always necessary}
  42. New(LabelInfo);
  43. LabelInfo^.LowLabel := High(AWord);
  44. LabelInfo^.HighLabel := 0;
  45. LabelInfo^.LabelDif := 0;
  46. End;
  47. Function TAsmOptimizer.FindLoHiLabels: Pai;
  48. { Walks through the paasmlist to find the lowest and highest label number. }
  49. { Returns the last Pai object of the current block }
  50. Var LabelFound: Boolean;
  51. P: Pai;
  52. Begin
  53. LabelFound := False;
  54. P := BlockStart;
  55. With LabelInfo^ Do
  56. Begin
  57. While Assigned(P) And
  58. ((P^.typ <> Ait_Marker) Or
  59. (Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
  60. Begin
  61. If (Pai(p)^.typ = ait_label) Then
  62. If (Pai_Label(p)^.l^.is_used) Then
  63. Begin
  64. LabelFound := True;
  65. If (Pai_Label(p)^.l^.labelnr < LowLabel) Then
  66. LowLabel := Pai_Label(p)^.l^.labelnr;
  67. If (Pai_Label(p)^.l^.labelnr > HighLabel) Then
  68. HighLabel := Pai_Label(p)^.l^.labelnr
  69. End;
  70. GetNextInstruction(p, p)
  71. End;
  72. FindLoHiLabels := p;
  73. If LabelFound
  74. Then LabelDif := HighLabel-LowLabel+1
  75. Else LabelDif := 0
  76. End
  77. End;
  78. Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
  79. { Builds a table with the locations of the labels in the paasmoutput. }
  80. { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
  81. Var p, hp1, hp2: Pai;
  82. UsedRegs: TRegSet;
  83. Begin
  84. UsedRegs := [];
  85. With LabelInfo^ Do
  86. If (LabelDif <> 0) Then
  87. Begin
  88. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  89. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  90. p := BlockStart;
  91. While (P <> BlockEnd) Do
  92. Begin
  93. Case p^.typ Of
  94. ait_Label:
  95. If Pai_Label(p)^.l^.is_used Then
  96. LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
  97. ait_regAlloc:
  98. begin
  99. if PairegAlloc(p)^.Allocation then
  100. Begin
  101. If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
  102. UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
  103. Else
  104. Begin
  105. hp1 := p;
  106. hp2 := nil;
  107. While GetLastInstruction(hp1, hp1) And
  108. Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
  109. hp2 := hp1;
  110. If hp2 <> nil Then
  111. Begin
  112. hp1 := New(PaiRegAlloc, DeAlloc(PaiRegAlloc(p)^.Reg));
  113. InsertLLItem(Pai(hp2^.previous), hp2, hp1);
  114. End;
  115. End;
  116. End
  117. else
  118. Begin
  119. UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
  120. hp1 := p;
  121. hp2 := nil;
  122. While Not(FindRegAlloc(PaiRegAlloc(p)^.Reg, Pai(hp1^.Next))) And
  123. GetNextInstruction(hp1, hp1) And
  124. RegInInstruction(PaiRegAlloc(p)^.Reg, hp1) Do
  125. hp2 := hp1;
  126. If hp2 <> nil Then
  127. Begin
  128. hp1 := Pai(p^.previous);
  129. AsmL^.Remove(p);
  130. InsertLLItem(hp2, Pai(hp2^.Next), p);
  131. p := hp1;
  132. End
  133. End
  134. End
  135. End
  136. End;
  137. P := Pai(p^.Next);
  138. While Assigned(p) And
  139. (p^.typ in (SkipInstr - [ait_regalloc])) Do
  140. P := Pai(P^.Next)
  141. End
  142. End;
  143. Procedure TAsmOptimizer.Optimize;
  144. Var HP: Pai;
  145. DFA: PAOptDFACpu;
  146. Begin
  147. BlockStart := Pai(AsmL^.First);
  148. While Assigned(BlockStart) Do
  149. Begin
  150. { Initialize BlockEnd and the LabelInfo (low and high label) }
  151. BlockEnd := FindLoHiLabels;
  152. { initialize the LabelInfo (labeltable) and fix the regalloc info }
  153. BuildLabelTableAndFixRegAlloc;
  154. { peephole optimizations, twice because you can't do them all in one }
  155. { pass }
  156. { PeepHoleOptPass1;
  157. PeepHoleOptPass1;}
  158. If (cs_slowoptimize in aktglobalswitches) Then
  159. Begin
  160. New(DFA,Init(AsmL,BlockStart,BlockEnd,LabelInfo));
  161. { data flow analyzer }
  162. DFA^.DoDFA;
  163. { common subexpression elimination }
  164. { CSE;}
  165. End;
  166. { more peephole optimizations }
  167. { PeepHoleOptPass2;}
  168. {dispose labeltabel}
  169. If Assigned(LabelInfo^.LabelTable) Then
  170. Begin
  171. Dispose(LabelInfo^.LabelTable);
  172. LabelInfo := Nil
  173. End;
  174. { continue where we left off, BlockEnd is either the start of an }
  175. { assembler block or nil}
  176. BlockStart := BlockEnd;
  177. While Assigned(BlockStart) And
  178. (BlockStart^.typ = ait_Marker) And
  179. (Pai_Marker(BlockStart)^.Kind = AsmBlockStart) Do
  180. Begin
  181. { we stopped at an assembler block, so skip it }
  182. While GetNextInstruction(BlockStart, BlockStart) And
  183. ((BlockStart^.Typ <> Ait_Marker) Or
  184. (Pai_Marker(Blockstart)^.Kind <> AsmBlockEnd)) Do;
  185. { blockstart now contains a pai_marker(asmblockend) }
  186. If Not(GetNextInstruction(BlockStart, HP) And
  187. ((HP^.typ <> ait_Marker) Or
  188. (Pai_Marker(HP)^.Kind <> AsmBlockStart)
  189. )
  190. ) Then
  191. {skip the next assembler block }
  192. BlockStart := HP;
  193. { otherwise there is no assembler block anymore after the current }
  194. { one, so optimize the next block of "normal" instructions }
  195. End
  196. End;
  197. End;
  198. Destructor TAsmOptimizer.Done;
  199. Begin
  200. Dispose(LabelInfo)
  201. End;
  202. procedure Optimize(AsmL:Paasmoutput);
  203. var
  204. p : PAsmOptimizer;
  205. begin
  206. new(p,Init(AsmL));
  207. p^.Optimize;
  208. dispose(p,Done);
  209. end;
  210. End.
  211. {Virtual methods, most have to be overridden by processor dependent methods}
  212. {
  213. $Log$
  214. Revision 1.5 2002-07-01 18:46:21 peter
  215. * internal linker
  216. * reorganized aasm layer
  217. Revision 1.4 2002/05/18 13:34:05 peter
  218. * readded missing revisions
  219. Revision 1.3 2002/05/16 19:46:34 carl
  220. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  221. + try to fix temp allocation (still in ifdef)
  222. + generic constructor calls
  223. + start of tassembler / tmodulebase class cleanup
  224. }