aoptcpud.pas 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. {
  2. $Id $
  3. Copyright (c) 1999 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: TChange): 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: TAsmInstrucProp;
  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 := AsmInstr[p^.OpCode];
  100. Cnt := 1;
  101. While (Cnt <= MaxCh) And
  102. (InstrProp.Ch[Cnt] <> C_None) Do
  103. Begin
  104. Case InstrProp.Ch[Cnt] Of
  105. C_REAX..C_REDI:
  106. CurProp^.ReadReg(TCh2Reg(InstrProp.Ch[Cnt]));
  107. C_WEAX..C_RWEDI:
  108. Begin
  109. If (InstrProp.Ch[Cnt] >= C_RWEAX) Then
  110. CurProp^.ReadReg(TCh2Reg(InstrProp.Ch[Cnt]));
  111. CurProp^.DestroyReg(TCh2Reg(InstrProp.Ch[Cnt]),InstrSinceLastMod);
  112. End;
  113. {$ifdef arithopt}
  114. C_MEAX..C_MEDI:
  115. CurProp^.ModifyReg(TCh2Reg(InstrProp.Ch[Cnt]), InstrSinceLastMod);
  116. {$endif arithopt}
  117. C_CDirFlag: CurProp^.CondRegs.ClearFlag(DirFlag);
  118. C_SDirFlag: CurProp^.CondRegs.SetFlag(DirFlag);
  119. C_Rop1: CurProp^.ReadOp(p^.oper[0]);
  120. C_Rop2: CurProp^.ReadOp(p^.oper[1]);
  121. C_Rop3: CurProp^.ReadOp(p^.oper[2]);
  122. C_Wop1..C_RWop1:
  123. Begin
  124. If (InstrProp.Ch[Cnt] = C_RWop1) Then
  125. CurProp^.ReadOp(p^.oper[0]);
  126. CurProp^.DestroyOp(p^.oper[0], InstrSinceLastMod);
  127. End;
  128. {$ifdef arithopt}
  129. C_Mop1:
  130. CurProp^.ModifyOp(p^.oper[0], InstrSinceLastMod);
  131. {$endif arithopt}
  132. C_Wop2..C_RWop2:
  133. Begin
  134. If (InstrProp.Ch[Cnt] = C_RWop2) Then
  135. CurProp^.ReadOp(p^.oper[1]);
  136. CurProp^.DestroyOp(p^.oper[1], InstrSinceLastMod);
  137. End;
  138. {$ifdef arithopt}
  139. C_Mop2:
  140. CurProp^.ModifyOp(p^.oper[1], InstrSinceLastMod);
  141. {$endif arithopt}
  142. C_Wop3..C_RWop3:
  143. Begin
  144. If (InstrProp.Ch[Cnt] = C_RWop3) Then
  145. CurProp^.ReadOp(p^.oper[2]);
  146. CurProp^.DestroyOp(p^.oper[2], InstrSinceLastMod);
  147. End;
  148. {$ifdef arithopt}
  149. C_Mop3:
  150. CurProp^.ModifyOp(p^.oper[2], InstrSinceLastMod);
  151. {$endif arithopt}
  152. C_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. C_RFlags, C_WFlags, C_RWFlags, C_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: TAsmInstrucProp;
  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 := AsmInstr[PInstr(p)^.OpCode];
  195. While (Cnt <= MaxCh) And
  196. (InstrProp.Ch[Cnt] <> C_None) And
  197. Not(TmpResult) Do
  198. Begin
  199. Case InstrProp.Ch[Cnt] Of
  200. C_REAX..C_REDI,C_RWEAX..C_RWEDI
  201. {$ifdef arithopt}
  202. ,C_MEAX..C_MEDI
  203. {$endif arithopt}:
  204. TmpResult := Reg = TCh2Reg(InstrProp.Ch[Cnt]);
  205. C_ROp1,C_RWOp1{$ifdef arithopt},C_Mop1{$endif arithopt}:
  206. TmpResult := RegInOp(Reg,PInstr(p)^.oper[0]);
  207. C_ROp2,C_RWOp2{$ifdef arithopt},C_Mop2{$endif arithopt}:
  208. TmpResult := RegInOp(Reg,PInstr(p)^.oper[1]);
  209. C_ROp3,C_RWOp3{$ifdef arithopt},C_Mop3{$endif arithopt}:
  210. TmpResult := RegInOp(Reg,PInstr(p)^.oper[2]);
  211. C_WOp1: TmpResult := (PInstr(p)^.oper[0].typ = top_ref) And
  212. RegInRef(Reg,PInstr(p)^.oper[0].ref^);
  213. C_WOp2: TmpResult := (PInstr(p)^.oper[1].typ = top_ref) And
  214. RegInRef(Reg,PInstr(p)^.oper[1].ref^);
  215. C_WOp3: TmpResult := (PInstr(p)^.oper[2].typ = top_ref) And
  216. RegInRef(Reg,PInstr(p)^.oper[2].ref^);
  217. C_WMemEDI: TmpResult := (Reg = R_EDI);
  218. C_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: TChange): TRegister;
  227. Begin
  228. If (Ch <= C_REDI) Then
  229. TCh2Reg := TRegister(Byte(Ch))
  230. Else
  231. If (Ch <= C_WEDI) Then
  232. TCh2Reg := TRegister(Byte(Ch) - Byte(C_REDI))
  233. Else
  234. If (Ch <= C_RWEDI) Then
  235. TCh2Reg := TRegister(Byte(Ch) - Byte(C_WEDI))
  236. Else
  237. If (Ch <= C_MEDI) Then
  238. TCh2Reg := TRegister(Byte(Ch) - Byte(C_RWEDI))
  239. End;
  240. End.
  241. {
  242. $Log$
  243. Revision 1.3 1999-09-08 15:01:31 jonas
  244. * some small changes so the noew optimizer is again compilable
  245. Revision 1.2 1999/08/18 14:32:26 jonas
  246. + compilable!
  247. + dataflow analyzer finished
  248. + start of CSE units
  249. + aoptbase which contains a base object for all optimizer objects
  250. * some constants and type definitions moved around to avoid circular
  251. dependencies
  252. * moved some methods from base objects to specialized objects because
  253. they're not used anywhere else
  254. Revision 1.1 1999/08/11 14:22:56 jonas
  255. + first version, added TAsmDFACpu object and CpuDFA method
  256. }