aoptcpud.pas 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Jonas Maebe, member of the Free Pascal
  4. Development Team
  5. This unit contains the processor specific implementation of the
  6. assembler optimizer data flow analyzer.
  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 aoptcpud;
  21. Interface
  22. uses Aasm, cpubase, AoptCpub, AoptObj, AoptDA;
  23. Type
  24. PAOptDFACpu = ^TAOptDFACpu;
  25. TAOptDFACpu = Object(TAOptDFA)
  26. { uses the same constructor as TAoptDFA = constructor from TAoptObj }
  27. { handles the processor dependent dataflow analizing }
  28. Procedure CpuDFA(p: PInstr); Virtual;
  29. Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
  30. Function RegReadByInstr(Reg: TRegister; p: Pai): Boolean; Virtual;
  31. End;
  32. Implementation
  33. uses cpuinfo;
  34. Procedure TAOptDFACpu.CpuDFA(p: PInstr);
  35. { Analyzes the Data Flow of an assembler list. Analyses the reg contents }
  36. { for the instructions between blockstart and blockend. Returns the last pai }
  37. { which has been processed }
  38. Var CurProp: PPaiProp;
  39. InstrProp: TInsProp;
  40. TmpRef: TReference;
  41. Cnt: Byte;
  42. Begin
  43. CurProp := PPaiProp(p^.OptInfo);
  44. Case p^.Opcode Of
  45. A_DIV, A_IDIV, A_MUL:
  46. Begin
  47. CurProp^.ReadOp(p^.oper[0]);
  48. CurProp^.ReadReg(R_EAX);
  49. If (p^.OpCode = A_IDIV) or
  50. (p^.OpCode = A_DIV) Then
  51. CurProp^.ReadReg(R_EDX);
  52. CurProp^.DestroyReg(R_EAX, InstrSinceLastMod)
  53. End;
  54. A_IMUL:
  55. Begin
  56. CurProp^.ReadOp(p^.oper[0]);
  57. CurProp^.ReadOp(p^.oper[1]);
  58. If (p^.oper[2].typ = top_none) Then
  59. If (p^.oper[1].typ = top_none) Then
  60. Begin
  61. CurProp^.ReadReg(R_EAX);
  62. CurProp^.DestroyReg(R_EAX, InstrSinceLastMod);
  63. CurProp^.DestroyReg(R_EDX, InstrSinceLastMod)
  64. End
  65. Else
  66. {$ifdef arithopt}
  67. CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod)
  68. {$else arithopt}
  69. CurProp^.DestroyOp(p^.oper[1], InstrSinceLastMod)
  70. {$endif arithopt}
  71. Else
  72. {$ifdef arithopt}
  73. CurProp^.ModifyOp(p^.oper[2], InstrSinceLastMod);
  74. {$else arithopt}
  75. CurProp^.DestroyOp(p^.oper[2], InstrsinceLastMod);
  76. {$endif arithopt}
  77. End;
  78. A_XOR:
  79. Begin
  80. CurProp^.ReadOp(p^.oper[0]);
  81. CurProp^.ReadOp(p^.oper[1]);
  82. If (p^.oper[0].typ = top_reg) And
  83. (p^.oper[1].typ = top_reg) And
  84. (p^.oper[0].reg = p^.oper[1].reg) Then
  85. Begin
  86. CurProp^.DestroyReg(p^.oper[0].reg, InstrSinceLastMod);
  87. CurProp^.Regs[RegMaxSize(p^.oper[0].reg)].typ := Con_Const;
  88. CurProp^.Regs[RegMaxSize(p^.oper[0].reg)].StartMod := Pointer(0)
  89. End
  90. Else
  91. {$Ifdef ArithOpt}
  92. CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod);
  93. {$Else ArithOpt}
  94. CurProp^.DestroyOp(p^.oper[1], InstrSinceLastMod);
  95. {$EndIf ArithOpt}
  96. End
  97. Else
  98. Begin
  99. InstrProp := InsProp[p^.OpCode];
  100. Cnt := 1;
  101. While (Cnt <= MaxCh) And
  102. (InstrProp.Ch[Cnt] <> Ch_None) Do
  103. Begin
  104. Case InstrProp.Ch[Cnt] Of
  105. Ch_REAX..Ch_REDI:
  106. CurProp^.ReadReg(TCh2Reg(InstrProp.Ch[Cnt]));
  107. Ch_WEAX..Ch_RWEDI:
  108. Begin
  109. If (InstrProp.Ch[Cnt] >= Ch_RWEAX) Then
  110. CurProp^.ReadReg(TCh2Reg(InstrProp.Ch[Cnt]));
  111. CurProp^.DestroyReg(TCh2Reg(InstrProp.Ch[Cnt]),InstrSinceLastMod);
  112. End;
  113. {$ifdef arithopt}
  114. Ch_MEAX..Ch_MEDI:
  115. CurProp^.ModifyReg(TCh2Reg(InstrProp.Ch[Cnt]), InstrSinceLastMod);
  116. {$endif arithopt}
  117. Ch_CDirFlag: CurProp^.CondRegs.ClearFlag(DirFlag);
  118. Ch_SDirFlag: CurProp^.CondRegs.SetFlag(DirFlag);
  119. Ch_Rop1: CurProp^.ReadOp(p^.oper[0]);
  120. Ch_Rop2: CurProp^.ReadOp(p^.oper[1]);
  121. Ch_Rop3: CurProp^.ReadOp(p^.oper[2]);
  122. Ch_Wop1..Ch_RWop1:
  123. Begin
  124. If (InstrProp.Ch[Cnt] = Ch_RWop1) Then
  125. CurProp^.ReadOp(p^.oper[0]);
  126. CurProp^.DestroyOp(p^.oper[0], InstrSinceLastMod);
  127. End;
  128. {$ifdef arithopt}
  129. Ch_Mop1:
  130. CurProp^.ModifyOp(p^.oper[0], InstrSinceLastMod);
  131. {$endif arithopt}
  132. Ch_Wop2..Ch_RWop2:
  133. Begin
  134. If (InstrProp.Ch[Cnt] = Ch_RWop2) Then
  135. CurProp^.ReadOp(p^.oper[1]);
  136. CurProp^.DestroyOp(p^.oper[1], InstrSinceLastMod);
  137. End;
  138. {$ifdef arithopt}
  139. Ch_Mop2:
  140. CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod);
  141. {$endif arithopt}
  142. Ch_Wop3..Ch_RWop3:
  143. Begin
  144. If (InstrProp.Ch[Cnt] = Ch_RWop3) Then
  145. CurProp^.ReadOp(p^.oper[2]);
  146. CurProp^.DestroyOp(p^.oper[2], InstrSinceLastMod);
  147. End;
  148. {$ifdef arithopt}
  149. Ch_Mop3:
  150. CurProp^.ModifyOp(p^.oper[2], InstrSinceLastMod);
  151. {$endif arithopt}
  152. Ch_WMemEDI:
  153. Begin
  154. CurProp^.ReadReg(R_EDI);
  155. FillChar(TmpRef, SizeOf(TmpRef), 0);
  156. TmpRef.Base := R_EDI;
  157. CurProp^.DestroyRefs(TmpRef, R_NO, InstrSinceLastMod)
  158. End;
  159. Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:;
  160. Else CurProp^.DestroyAllRegs(InstrSinceLastMod)
  161. End;
  162. Inc(Cnt)
  163. End
  164. End
  165. End
  166. End;
  167. Function TAOptDFACpu.RegReadByInstr(Reg: TRegister; p: Pai): Boolean;
  168. Var Cnt: AWord;
  169. InstrProp: TInsProp;
  170. TmpResult: Boolean;
  171. Begin
  172. TmpResult := False;
  173. If (p^.typ = ait_instruction) Then
  174. Case PInstr(p)^.opcode of
  175. A_IMUL:
  176. With PInstr(p)^ Do
  177. TmpResult :=
  178. RegInOp(Reg,oper[0]) or
  179. RegInOp(Reg,oper[1]) or
  180. ((ops = 1) and
  181. (reg = R_EAX));
  182. A_DIV, A_IDIV, A_MUL:
  183. With PInstr(p)^ Do
  184. TmpResult :=
  185. RegInOp(Reg,oper[0]) or
  186. (Reg = R_EAX) or
  187. ((Reg = R_EDX) and
  188. ((opcode = A_DIV) or
  189. (opcode = A_IDIV)) and
  190. (opsize = S_L))
  191. Else
  192. Begin
  193. Cnt := 1;
  194. InstrProp := InsProp[PInstr(p)^.OpCode];
  195. While (Cnt <= MaxCh) And
  196. (InstrProp.Ch[Cnt] <> Ch_None) And
  197. Not(TmpResult) Do
  198. Begin
  199. Case InstrProp.Ch[Cnt] Of
  200. Ch_REAX..Ch_REDI,Ch_RWEAX..Ch_RWEDI
  201. {$ifdef arithopt}
  202. ,Ch_MEAX..Ch_MEDI
  203. {$endif arithopt}:
  204. TmpResult := Reg = TCh2Reg(InstrProp.Ch[Cnt]);
  205. Ch_ROp1,Ch_RWOp1{$ifdef arithopt},Ch_Mop1{$endif arithopt}:
  206. TmpResult := RegInOp(Reg,PInstr(p)^.oper[0]);
  207. Ch_ROp2,Ch_RWOp2{$ifdef arithopt},Ch_Mop2{$endif arithopt}:
  208. TmpResult := RegInOp(Reg,PInstr(p)^.oper[1]);
  209. Ch_ROp3,Ch_RWOp3{$ifdef arithopt},Ch_Mop3{$endif arithopt}:
  210. TmpResult := RegInOp(Reg,PInstr(p)^.oper[2]);
  211. Ch_WOp1: TmpResult := (PInstr(p)^.oper[0].typ = top_ref) And
  212. RegInRef(Reg,PInstr(p)^.oper[0].ref^);
  213. Ch_WOp2: TmpResult := (PInstr(p)^.oper[1].typ = top_ref) And
  214. RegInRef(Reg,PInstr(p)^.oper[1].ref^);
  215. Ch_WOp3: TmpResult := (PInstr(p)^.oper[2].typ = top_ref) And
  216. RegInRef(Reg,PInstr(p)^.oper[2].ref^);
  217. Ch_WMemEDI: TmpResult := (Reg = R_EDI);
  218. Ch_FPU: TmpResult := Reg in [R_ST..R_ST7,R_MM0..R_MM7]
  219. End;
  220. Inc(Cnt)
  221. End
  222. End
  223. End;
  224. RegReadByInstr := TmpResult
  225. End;
  226. Function TAOptDFACpu.TCh2Reg(Ch: TInsChange): TRegister;
  227. Begin
  228. If (Ch <= Ch_REDI) Then
  229. TCh2Reg := TRegister(Byte(Ch))
  230. Else
  231. If (Ch <= Ch_WEDI) Then
  232. TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_REDI))
  233. Else
  234. If (Ch <= Ch_RWEDI) Then
  235. TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_WEDI))
  236. Else
  237. If (Ch <= Ch_MEDI) Then
  238. TCh2Reg := TRegister(Byte(Ch) - Byte(Ch_RWEDI))
  239. End;
  240. End.
  241. {
  242. $Log$
  243. Revision 1.5 2000-01-07 01:14:57 peter
  244. * updated copyright to 2000
  245. Revision 1.4 1999/11/09 22:57:09 peter
  246. * compiles again both i386,alpha both with optimizer
  247. Revision 1.3 1999/09/08 15:01:31 jonas
  248. * some small changes so the noew optimizer is again compilable
  249. Revision 1.2 1999/08/18 14:32:26 jonas
  250. + compilable!
  251. + dataflow analyzer finished
  252. + start of CSE units
  253. + aoptbase which contains a base object for all optimizer objects
  254. * some constants and type definitions moved around to avoid circular
  255. dependencies
  256. * moved some methods from base objects to specialized objects because
  257. they're not used anywhere else
  258. Revision 1.1 1999/08/11 14:22:56 jonas
  259. + first version, added TAsmDFACpu object and CpuDFA method
  260. }