csopt386.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. {
  2. $Id$
  3. Copyright (c) 1997-98 by Jonas Maebe
  4. This unit contains the common subexpression elimination procedure.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. Unit CSOpt386;
  19. Interface
  20. Uses aasm;
  21. {Procedure CSOpt386(First, Last: Pai);}
  22. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  23. Implementation
  24. Uses CObjects, verbose
  25. {$ifdef i386}
  26. ,i386, DAOpt386
  27. {$endif i386}
  28. ;
  29. Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean;
  30. {checks whether the current instruction sequence (starting with p) and the
  31. one between StartMod and EndMod of Reg are the same. If so, the number of
  32. instructions that match is stored in Found and true is returned, otherwise
  33. Found holds the number of instructions between StartMod and EndMod and false
  34. is returned}
  35. Var hp2, hp3, EndMod: Pai;
  36. Counter: Byte;
  37. Begin {CheckSequence}
  38. Reg := Reg32(Reg);
  39. Found := 0;
  40. hp3 := p;
  41. While GetLastInstruction(hp3, hp3) And
  42. PPAiProp(hp3^.fileinfo.line)^.CanBeRemoved Do;
  43. hp2 := PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].StartMod;
  44. EndMod := hp2;
  45. If (PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods = 1)
  46. Then Counter := 1
  47. Else
  48. For Counter := 2 to PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods Do
  49. GetNextInstruction(EndMod, EndMod);
  50. hp3 := p;
  51. While (Found <> Counter) And
  52. InstructionsEqual(hp2, hp3) Do
  53. Begin
  54. GetNextInstruction(hp2, hp2);
  55. GetNextInstruction(hp3, hp3);
  56. Inc(Found)
  57. End;
  58. If (Found <> Counter)
  59. Then
  60. Begin
  61. If ((Found+1) = Counter) And
  62. Assigned(hp2) And
  63. (Pai(hp2)^.typ = ait_instruction) And
  64. (Pai386(hp2)^._operator In [A_MOV, A_MOVZX]) And
  65. (Pai386(hp2)^.op1t = top_ref) And
  66. (Pai386(hp2)^.op2t = top_reg) And
  67. Assigned(hp3) And
  68. (Pai(hp3)^.typ = ait_instruction) And
  69. (Pai386(hp3)^._operator In [A_MOV, A_MOVZX]) And
  70. (Pai386(hp3)^.op1t = top_ref) And
  71. (Pai386(hp3)^.op2t = top_reg) And
  72. (Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
  73. RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^))
  74. Then
  75. {hack to be able to optimize
  76. mov (mem), reg
  77. mov (reg), reg
  78. mov (reg), reg [*]
  79. test reg, reg and the oposite (where the marked instructions are
  80. jne l1 switched)
  81. mov (mem), reg
  82. mov (reg), reg
  83. movzx (reg), reg [*]}
  84. If (Pai386(hp2)^._operator = A_MOV)
  85. Then
  86. Begin
  87. If (Pai386(hp2)^.Size = S_B) And
  88. (Reg8toReg32(TRegister(Pai386(hp2)^.op2)) =
  89. TRegister(Pai386(hp3)^.op2))
  90. Then
  91. Begin
  92. Pai386(hp2)^._operator := A_MOVZX;
  93. Pai386(hp2)^.op2 := Pai386(hp3)^.op2;
  94. Pai386(hp2)^.Size := S_BL;
  95. Inc(Found);
  96. CheckSequence := True;
  97. End
  98. Else
  99. Begin
  100. CheckSequence := False;
  101. If (Found > 0) Then
  102. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  103. End
  104. End
  105. Else
  106. Begin
  107. If (Pai386(hp3)^.Size = S_B) And
  108. (Reg8toReg32(TRegister(Pai386(hp3)^.op2)) =
  109. TRegister(Pai386(hp2)^.op2))
  110. Then
  111. Begin
  112. CheckSequence := True;
  113. Inc(Found)
  114. End
  115. Else
  116. Begin
  117. CheckSequence := False;
  118. If (Found > 0) Then
  119. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  120. End
  121. End
  122. Else
  123. Begin
  124. CheckSequence := False;
  125. If (found > 0) then
  126. {this is correct because we only need to turn off the CanBeRemoved flag
  127. when an instruction has already been processed by CheckSequence
  128. (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
  129. If it has already been processed by CheckSequence and flagged to be
  130. removed, it means that it has been checked against a previous sequence
  131. and that it was equal (otherwise CheckSequence would have returned false
  132. and the instruction wouldn't have been removed). If this "If found > 0"
  133. check is left out, incorrect optimizations are performed.}
  134. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  135. End
  136. End
  137. Else CheckSequence := True;
  138. End; {CheckSequence}
  139. Procedure DoCSE(First, Last: Pai);
  140. {marks the instructions that can be removed by RemoveInstructs. They're not
  141. removed immediately because sometimes an instruction needs to be checked in
  142. two different sequences}
  143. Var Cnt, Cnt2: Longint;
  144. p, hp1, hp2: Pai;
  145. Begin
  146. p := First;
  147. If (p^.typ in SkipInstr) Then
  148. GetNextInstruction(p, p);
  149. First := p;
  150. While Assigned(p) Do
  151. Begin
  152. Case p^.typ Of
  153. ait_label, ait_labeled_instruction:;
  154. ait_instruction:
  155. Begin
  156. Case Pai386(p)^._operator Of
  157. A_CLD: If GetLastInstruction(p, hp1) And
  158. (PPaiProp(hp1^.fileinfo.line)^.DirFlag = F_NotSet) Then
  159. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  160. A_MOV, A_MOVZX, A_MOVSX:
  161. Begin
  162. Case Pai386(p)^.op1t Of
  163. { Top_Reg:
  164. Case Pai386(p)^.op2t Of
  165. Top_Reg:;
  166. Top_Ref:;
  167. End;}
  168. Top_Ref:
  169. Begin {destination is always a register in this case}
  170. With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
  171. Begin
  172. If GetLastInstruction(p, hp1) And
  173. (PPaiProp(hp1^.fileinfo.line)^.
  174. Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
  175. {so we don't try to check a sequence when the register only contains a constant}
  176. If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
  177. (Cnt > 0)
  178. Then
  179. Begin
  180. hp1 := nil;
  181. {although it's perfectly ok to remove an instruction which doesn't contain
  182. the register that we've just checked (CheckSequence takes care of that),
  183. the sequence containing this other register should also be completely
  184. checked and removed, otherwise we may get situations like this:
  185. movl 12(%ebp), %edx movl 12(%ebp), %edx
  186. movl 16(%ebp), %eax movl 16(%ebp), %eax
  187. movl 8(%edx), %edx movl 8(%edx), %edx
  188. movl (%eax), eax movl (%eax), eax
  189. cmpl %eax, %edx cmpl %eax, %edx
  190. jnz l123 getting converted to jnz l123
  191. movl 12(%ebp), %edx movl 4(%eax), eax
  192. movl 16(%ebp), %eax
  193. movl 8(%edx), %edx
  194. movl 4(%eax), eax}
  195. hp2 := p;
  196. Cnt2 := 1;
  197. While Cnt2 <= Cnt Do
  198. Begin
  199. If (hp1 = nil) And
  200. Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
  201. Then hp1 := p;
  202. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  203. Inc(Cnt2);
  204. GetNextInstruction(p, p);
  205. End;
  206. If hp1 <> nil Then p := hp1;
  207. Continue;
  208. End
  209. Else
  210. If (Cnt > 0) And
  211. (PPaiProp(p^.fileinfo.line)^.CanBeRemoved) Then
  212. Begin
  213. hp2 := p;
  214. Cnt2 := 1;
  215. While Cnt2 <= Cnt Do
  216. Begin
  217. If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
  218. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := False;
  219. Inc(Cnt2);
  220. GetNextInstruction(p, p);
  221. End;
  222. Continue;
  223. End;
  224. End;
  225. End;
  226. Top_Const:
  227. Begin
  228. Case Pai386(p)^.op2t Of
  229. Top_Reg:
  230. Begin
  231. If GetLastInstruction(p, hp1) Then
  232. With PPaiProp(hp1^.fileinfo.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
  233. If (Typ = Con_Const) And
  234. (StartMod = Pai386(p)^.op1) Then
  235. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  236. End;
  237. { Top_Ref:;}
  238. End;
  239. End;
  240. End;
  241. End;
  242. A_STD: If GetLastInstruction(p, hp1) And
  243. (PPaiProp(hp1^.fileinfo.line)^.DirFlag = F_Set) Then
  244. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  245. A_XOR:
  246. Begin
  247. If (Pai386(p)^.op1t = top_reg) And
  248. (Pai386(p)^.op2t = top_reg) And
  249. (Pai386(p)^.op1 = Pai386(p)^.op2) And
  250. GetLastInstruction(p, hp1) And
  251. (PPaiProp(hp1^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
  252. (PPaiProp(hp1^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
  253. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True
  254. End
  255. End
  256. End;
  257. End;
  258. GetNextInstruction(p, p);
  259. End;
  260. End;
  261. Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
  262. {Removes the marked instructions and disposes the PPaiProps of the other
  263. instructions, restoring theirline number}
  264. Var p, hp1: Pai;
  265. {$IfDef TP}
  266. TmpLine: Longint;
  267. {$EndIf TP}
  268. InstrCnt: Longint;
  269. Begin
  270. p := First;
  271. If (p^.typ in SkipInstr) Then
  272. GetNextInstruction(p, p);
  273. InstrCnt := 1;
  274. While Assigned(p) Do
  275. If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
  276. Then
  277. Begin
  278. {$IfDef TP}
  279. Dispose(PPaiProp(p^.fileinfo.line));
  280. {$EndIf}
  281. GetNextInstruction(p, hp1);
  282. AsmL^.Remove(p);
  283. Dispose(p, Done);
  284. p := hp1;
  285. Inc(InstrCnt)
  286. End
  287. Else
  288. Begin
  289. {$IfDef TP}
  290. TmpLine := PPaiProp(p^.fileinfo.line)^.linesave;
  291. Dispose(PPaiProp(p^.fileinfo.line));
  292. p^.fileinfo.line := TmpLine;
  293. {$Else TP}
  294. p^.fileinfo.line := PPaiProp(p^.fileinfo.line)^.linesave;
  295. {$EndIf TP}
  296. GetNextInstruction(p, p);
  297. Inc(InstrCnt)
  298. End;
  299. {$IfNDef TP}
  300. FreeMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4))
  301. {$EndIf TP}
  302. End;
  303. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  304. Begin
  305. DoCSE(First, Last);
  306. RemoveInstructs(AsmL, First, Last);
  307. End;
  308. End.
  309. {
  310. $Log$
  311. Revision 1.8 1998-09-21 08:45:09 pierre
  312. + added vmt_offset in tobjectdef.write for fututre use
  313. (first steps to have objects without vmt if no virtual !!)
  314. + added fpu_used field for tabstractprocdef :
  315. sets this level to 2 if the functions return with value in FPU
  316. (is then set to correct value at parsing of implementation)
  317. THIS MIGHT refuse some code with FPU expression too complex
  318. that were accepted before and even in some cases
  319. that don't overflow in fact
  320. ( like if f : float; is a forward that finally in implementation
  321. only uses one fpu register !!)
  322. Nevertheless I think that it will improve security on
  323. FPU operations !!
  324. * most other changes only for UseBrowser code
  325. (added symtable references for record and objects)
  326. local switch for refs to args and local of each function
  327. (static symtable still missing)
  328. UseBrowser still not stable and probably broken by
  329. the definition hash array !!
  330. Revision 1.7 1998/09/20 17:12:35 jonas
  331. * small fix for uncertain optimizations & more cleaning up
  332. Revision 1.5 1998/09/16 17:59:59 jonas
  333. * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc
  334. Revision 1.4 1998/08/06 19:40:27 jonas
  335. * removed $ before and after Log in comment
  336. Revision 1.3 1998/08/05 16:00:12 florian
  337. * some fixes for ansi strings
  338. * log to Log changed
  339. }