aopt.pas 8.1 KB

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