aopt.pas 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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, aoptda, aoptcs, aoptpeep, aoptcpu;
  23. Type
  24. TAsmOptimizer = Object
  25. { the PAasmOutput list this optimizer instance works on }
  26. AsmL: PAasmOutput;
  27. { The labeltable contains the addresses of the Pai objects that are }
  28. { labels }
  29. LabelInfo: PLabelInfo;
  30. { Start and end of the block that is currently being optimized, }
  31. { initialized by InitDFA }
  32. BlockStart, BlockEnd: Pai;
  33. { _AsmL is the PAasmOutpout list that has to be optimized }
  34. Constructor Init(_AsmL: PAasmOutput);
  35. { call the necessary optimizer procedures }
  36. Procedure Optimize;
  37. Destructor Done;
  38. private
  39. Function FindLoHiLabels: Pai;
  40. End;
  41. Implementation
  42. Constructor TAsmOptimizer.Init(_AsmL: PAasmOutput);
  43. Begin
  44. AsmL := _AsmL;
  45. End;
  46. Function TAsmOptimizer.FindLoHiLabels: Pai;
  47. { Walks through the paasmlist to find the lowest and highest label number. }
  48. { Returns the last Pai object of the current block }
  49. Var LabelFound: Boolean;
  50. P: Pai;
  51. Begin
  52. LabelFound := False;
  53. P := BlockStart;
  54. While Assigned(P) And
  55. ((P^.typ <> Ait_Marker) Or
  56. (Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
  57. Begin
  58. If (Pai(p)^.typ = ait_label) Then
  59. If (Pai_Label(p)^.l^.is_used)
  60. 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. Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
  76. { Builds a table with the locations of the labels in the paasmoutput. }
  77. { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
  78. Var p, hp1, hp2: Pai;
  79. UsedRegs: TRegSet;
  80. Begin
  81. UsedRegs := [];
  82. With LabelInfo Do
  83. If (LabelDif <> 0) Then
  84. Begin
  85. GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
  86. FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
  87. p := BlockStart;
  88. While (P <> BlockEnd) Do
  89. Begin
  90. Case p^.typ Of
  91. ait_Label:
  92. If Pai_Label(p)^.l^.is_used Then
  93. LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
  94. ait_regAlloc:
  95. begin
  96. if PairegAlloc(p)^.Allocation then
  97. Begin
  98. If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
  99. UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
  100. Else
  101. Begin
  102. hp1 := p;
  103. hp2 := nil;
  104. While GetLastInstruction(hp1, hp1) And
  105. Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
  106. hp2 := hp1;
  107. If hp2 <> nil Then
  108. Begin
  109. hp1 := New(PaiRegAlloc, DeAlloc(PaiRegAlloc(p)^.Reg));
  110. InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp1);
  111. End;
  112. End;
  113. End
  114. else
  115. Begin
  116. UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
  117. hp1 := p;
  118. hp2 := nil;
  119. While Not(FindRegAlloc(PaiRegAlloc(p)^.Reg, Pai(hp1^.Next))) And
  120. GetNextInstruction(hp1, hp1) And
  121. RegInInstruction(PaiRegAlloc(p)^.Reg, hp1) Do
  122. hp2 := hp1;
  123. If hp2 <> nil Then
  124. Begin
  125. hp1 := Pai(p^.previous);
  126. AsmL^.Remove(p);
  127. InsertLLItem(AsmL, hp2, Pai(hp2^.Next), p);
  128. p := hp1;
  129. End;
  130. End;
  131. end;
  132. End;
  133. P := Pai(p^.Next);
  134. While Assigned(p) And
  135. (p^.typ in (SkipInstr - [ait_regalloc])) Do
  136. P := Pai(P^.Next);
  137. End;
  138. End;
  139. Procedure TAsmOptimizer.Optimize;
  140. Var HP: Pai;
  141. AsmDFA: TAsmDFA;
  142. Begin
  143. {setup labeltable, always necessary}
  144. BlockStart := Pai(AsmL^.First);
  145. {Blockend now either contains an ait_marker with Kind = AsmBlockStart, or nil}
  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. BuilLabelTableAndFixRegAlloc;
  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. { data flow analyzer }
  159. DFAPass2;
  160. { common subexpression elimination }
  161. CSE;
  162. End;
  163. { more peephole optimizations }
  164. PeepHoleOptPass2;
  165. {dispose labeltabel}
  166. If Assigned(LabelInfo.LabelTable) Then
  167. Begin
  168. Dispose(LabelInfo.LabelTable);
  169. LabelInfo := Nil
  170. End;
  171. { continue where we left off, BlockEnd is either the start of an }
  172. { assembler block or nil}
  173. BlockStart := BlockEnd;
  174. While Assigned(BlockStart) And
  175. (BlockStart^.typ = ait_Marker) And
  176. (Pai_Marker(BlockStart)^.Kind = AsmBlockStart) Do
  177. Begin
  178. { we stopped at an assembler block, so skip it }
  179. While GetNextInstruction(BlockStart, BlockStart) And
  180. ((BlockStart^.Typ <> Ait_Marker) Or
  181. (Pai_Marker(Blockstart)^.Kind <> AsmBlockEnd)) Do;
  182. { blockstart now contains a pai_marker(asmblockend) }
  183. If Not(GetNextInstruction(BlockStart, HP) And
  184. ((HP^.typ <> ait_Marker) Or
  185. (Pai_Marker(HP)^.Kind <> AsmBlockStart)
  186. )
  187. ) Then
  188. {skip the next assembler block }
  189. BlockStart := HP;
  190. { otherwise there is no assembler block anymore after the current }
  191. { one, so optimize the next block of "normal" instructions }
  192. End
  193. End
  194. End;
  195. Destructor TAsmOptimizer.Done;
  196. Begin
  197. End;
  198. {Virtual methods, most have to be overridden by processor dependent methods}
  199. {
  200. $Log$
  201. Revision 1.2 1999-08-09 14:07:22 jonas
  202. commit.msg
  203. Revision 1.1 1999/08/08 13:24:50 jonas
  204. + added copyright header/GNU license info
  205. * made the assembler optimizer almost completely OOP
  206. * some code style clean up and extra comments
  207. * moved from the new/aopt to the /new and /new/i386 dirs
  208. }