csopt386.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  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. TmpResult: Boolean;
  37. RegsNotYetChecked: Set Of TRegister;
  38. Counter: Byte;
  39. Function NoChangedRegInRef(oldp, newp: Pai): Boolean;
  40. Var TmpP: Pai;
  41. {checks if the first operator of newp is a reference and in that case checks
  42. whether that reference includes regs that have been changed since oldp. This
  43. to avoid wrong optimizations like
  44. movl 8(%epb), %eax movl 8(%epb), %eax
  45. movl 12(%epb), %edx movl 12(%epb), %edx
  46. movl (%eax,%edx,1), %edi movl (%eax,%edx,1), %edi
  47. pushl %edi being converted to pushl %edi
  48. movl 8(%epb), %eax movl 16(%ebp), %edx
  49. movl 16(%epb), %edx pushl %edi
  50. movl (%eax,%edx,1), %edi
  51. pushl %edi
  52. because first is checked whether %eax isn't changed (it isn't) and
  53. consequently all instructions containg %eax are removed}
  54. Begin
  55. TmpResult := True;
  56. If (Pai(oldp)^.typ = ait_instruction) Then {oldp and newp are the same instruction}
  57. Case Pai386(oldp)^.op1t Of
  58. Top_Reg:
  59. If (Reg32(TRegister(Pai386(oldp)^.op1)) in RegsNotYetChecked) Then
  60. Begin
  61. RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(oldp)^.op1))];
  62. If Assigned(newp^.previous)
  63. Then
  64. Begin
  65. TmpP := Pai(newp^.previous);
  66. While Assigned (TmpP^.previous) And
  67. PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
  68. TmpP := Pai(TmpP^.previous);
  69. TmpResult := Assigned(TmpP) And
  70. RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(oldp)^.op1)))
  71. End
  72. Else TmpResult := False;
  73. End;
  74. Top_Ref:
  75. With TReference(Pai386(oldp)^.op1^) Do
  76. Begin
  77. If (Base in RegsNotYetChecked) And
  78. (Base <> R_NO) Then
  79. Begin
  80. RegsNotYetChecked := RegsNotYetChecked - [Base];
  81. If Assigned(newp^.previous)
  82. Then
  83. Begin
  84. TmpP := Pai(newp^.previous);
  85. While Assigned (TmpP^.previous) And
  86. PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
  87. TmpP := Pai(TmpP^.previous);
  88. TmpResult := Assigned(TmpP) And
  89. RegsSameContent(oldp, TmpP, Base)
  90. End
  91. Else TmpResult := False;
  92. End;
  93. If TmpResult And
  94. (Index <> R_NO) And
  95. (Index in RegsNotYetChecked) Then
  96. Begin
  97. RegsNotYetChecked := RegsNotYetChecked - [Index];
  98. If Assigned(newp^.previous)
  99. Then
  100. Begin
  101. TmpP := Pai(newp^.previous);
  102. While Assigned (TmpP^.previous) And
  103. PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do
  104. TmpP := Pai(TmpP^.previous);
  105. TmpResult := Assigned(TmpP) And
  106. RegsSameContent(oldp, TmpP, Index)
  107. End
  108. Else TmpResult := False;
  109. End;
  110. End;
  111. End;
  112. NoChangedRegInRef := TmpResult;
  113. End;
  114. Begin {CheckSequence}
  115. Reg := Reg32(Reg);
  116. Found := 0;
  117. hp2 := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
  118. hp3 := p;
  119. EndMod := PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].StartMod;
  120. RegsNotYetChecked := [R_EAX..R_EDI];
  121. For Counter := 2 to PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods Do
  122. EndMod := Pai(EndMod^.Next);
  123. While (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
  124. InstructionsEqual(hp2, hp3) And
  125. NoChangedRegInRef(EndMod, hp3) Do
  126. Begin
  127. hp2 := Pai(hp2^.next);
  128. hp3 := Pai(hp3^.next);
  129. Inc(Found)
  130. End;
  131. If (Found <> PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods)
  132. Then
  133. Begin
  134. If ((Found+1) = PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg].NrOfMods) And
  135. Assigned(hp2) And
  136. (Pai(hp2)^.typ = ait_instruction) And
  137. (Pai386(hp2)^._operator In [A_MOV, A_MOVZX]) And
  138. (Pai386(hp2)^.op1t = top_ref) And
  139. (Pai386(hp2)^.op2t = top_reg) And
  140. Assigned(hp3) And
  141. (Pai(hp3)^.typ = ait_instruction) And
  142. (Pai386(hp3)^._operator In [A_MOV, A_MOVZX]) And
  143. (Pai386(hp3)^.op1t = top_ref) And
  144. (Pai386(hp3)^.op2t = top_reg) And
  145. (Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
  146. RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And
  147. NoChangedRegInRef(EndMod, hp3)
  148. Then
  149. If (Pai386(hp2)^._operator = A_MOV)
  150. Then
  151. Begin
  152. If (Pai386(hp2)^.Size = S_B) And
  153. (Reg8toReg32(TRegister(Pai386(hp2)^.op2)) =
  154. TRegister(Pai386(hp3)^.op2))
  155. Then
  156. Begin
  157. Pai386(hp2)^._operator := A_MOVZX;
  158. Pai386(hp2)^.op2 := Pai386(hp3)^.op2;
  159. Pai386(hp2)^.Size := S_BL;
  160. Inc(Found);
  161. CheckSequence := True;
  162. End
  163. Else
  164. Begin
  165. CheckSequence := False;
  166. If (Found > 0) Then
  167. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  168. End
  169. End
  170. Else
  171. Begin
  172. If (Pai386(hp3)^.Size = S_B) And
  173. (Reg8toReg32(TRegister(Pai386(hp3)^.op2)) =
  174. TRegister(Pai386(hp2)^.op2))
  175. Then
  176. Begin
  177. CheckSequence := True;
  178. Inc(Found)
  179. End
  180. Else
  181. Begin
  182. CheckSequence := False;
  183. If (Found > 0) Then
  184. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  185. End
  186. End
  187. Else
  188. Begin
  189. CheckSequence := False;
  190. If (found > 0) then
  191. {this is correct because we only need to turn off the CanBeRemoved flag
  192. when an instruction has already been processed by CheckSequence
  193. (otherwise CanBeRemoved can't be true, or can't have to be turned off).
  194. If it has already been processed by checkSequence and flagged to be
  195. removed, it means that it has been checked against a previous sequence
  196. and that it was equal (otherwise CheckSequence would have returned false
  197. and the instruction wouldn't have been removed). If this "If found > 0"
  198. check is left out, incorrect optimizations are performed.}
  199. Found := PPaiProp(Pai(p)^.fileinfo.line)^.Regs[Reg].NrOfMods
  200. End
  201. End
  202. Else CheckSequence := True;
  203. End; {CheckSequence}
  204. Procedure DoCSE(First, Last: Pai);
  205. {marks the instructions that can be removed by RemoveInstructs. They're not
  206. removed immediately because sometimes an instruction needs to be checked in
  207. two different sequences}
  208. Var Cnt, Cnt2: Longint;
  209. p, hp1, hp2: Pai;
  210. Begin
  211. p := First;
  212. While (p <> Pai(Last^.Next)) Do
  213. Begin
  214. Case p^.typ Of
  215. ait_label, ait_labeled_instruction:;
  216. ait_instruction:
  217. Begin
  218. Case Pai386(p)^._operator Of
  219. A_CLD: If Assigned(p^.previous) And
  220. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_NotSet) Then
  221. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  222. A_MOV, A_MOVZX, A_MOVSX:
  223. Begin
  224. Case Pai386(p)^.op1t Of
  225. { Top_Reg:
  226. Case Pai386(p)^.op2t Of
  227. Top_Reg:;
  228. Top_Ref:;
  229. End;}
  230. Top_Ref:
  231. Begin {destination is always a register in this case}
  232. With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
  233. Begin
  234. If Assigned(p^.previous) And
  235. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.
  236. Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
  237. {so we don't try to check a sequence when the register only contains a constant}
  238. If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
  239. (Cnt > 0)
  240. Then
  241. Begin
  242. hp1 := nil;
  243. {although it's perfectly ok to remove an instruction which doesn't contain
  244. the register that we've just checked (CheckSequence takes care of that),
  245. the sequence containing this other register should also be completely
  246. checked and removed, otherwise we may get situations like this:
  247. movl 12(%ebp), %edx movl 12(%ebp), %edx
  248. movl 16(%ebp), %eax movl 16(%ebp), %eax
  249. movl 8(%edx), %edx movl 8(%edx), %edx
  250. movl (%eax), eax movl (%eax), eax
  251. cmpl %eax, %edx cmpl %eax, %edx
  252. jnz l123 getting converted to jnz l123
  253. movl 12(%ebp), %edx movl 4(%eax), eax
  254. movl 16(%ebp), %eax
  255. movl 8(%edx), %edx
  256. movl 4(%eax), eax}
  257. hp2 := p;
  258. For Cnt2 := 1 to Cnt Do
  259. Begin
  260. { Note to Jonas :
  261. ait_stab_function_name is only at the begin of one function
  262. ait_stabn is only inserted in ag so you should not see any
  263. ait_stabs are only in head and tail of procs
  264. so you should no have problems with those neither !! (PM)
  265. Tell me if I am wrong
  266. If Not(Pai(p)^.typ In [ait_stabs, ait_stabn, ait_stab_function_name]) Then }
  267. Begin
  268. If (hp1 = nil) And
  269. Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
  270. Then hp1 := p;
  271. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  272. End;
  273. p := Pai(p^.next);
  274. End;
  275. If hp1 <> nil Then p := hp1;
  276. Continue;
  277. End
  278. Else
  279. If (Cnt > 0) And
  280. (PPaiProp(p^.fileinfo.line)^.CanBeRemoved) Then
  281. Begin
  282. hp2 := p;
  283. For Cnt2 := 1 to Cnt Do
  284. Begin
  285. If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
  286. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := False;
  287. p := Pai(p^.Next)
  288. End;
  289. Continue;
  290. End;
  291. End;
  292. End;
  293. Top_Const:
  294. Begin
  295. Case Pai386(p)^.op2t Of
  296. Top_Reg:
  297. Begin
  298. If Assigned(p^.previous) Then
  299. With PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
  300. If (Typ = Con_Const) And
  301. (StartMod = Pai386(p)^.op1) Then
  302. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  303. End;
  304. Top_Ref:;
  305. End;
  306. End;
  307. End;
  308. End;
  309. A_STD: If Assigned(p^.previous) And
  310. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.DirFlag = F_Set) Then
  311. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  312. A_XOR:
  313. Begin
  314. If (Pai386(p)^.op1t = top_reg) And
  315. (Pai386(p)^.op2t = top_reg) And
  316. (Pai386(p)^.op1 = Pai386(p)^.op2) And
  317. Assigned(p^.previous) And
  318. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
  319. (PPaiProp(Pai(p^.previous)^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
  320. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True
  321. End
  322. End
  323. End;
  324. End;
  325. p := Pai(p^.next);
  326. End;
  327. End;
  328. Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
  329. {Removes the marked instructions and disposes the PPaiProps of the other
  330. instructions, restoring theirline number}
  331. Var p, hp1: Pai;
  332. TmpLine, InstrCnt: Longint;
  333. Begin
  334. p := First;
  335. InstrCnt := 1;
  336. While (p <> Pai(Last^.Next)) Do
  337. If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
  338. Then
  339. Begin
  340. If (InstrCnt > NrOfPaiFast) Then
  341. Dispose(PPaiProp(p^.fileinfo.line));
  342. hp1 := Pai(p^.Next);
  343. AsmL^.Remove(p);
  344. Dispose(p, Done);
  345. p := hp1;
  346. Inc(InstrCnt)
  347. End
  348. Else
  349. Begin
  350. If (InstrCnt > NrOfPaiFast)
  351. Then
  352. Begin
  353. TmpLine := PPaiProp(p^.fileinfo.line)^.linesave;
  354. Dispose(PPaiProp(p^.fileinfo.line));
  355. p^.fileinfo.line := TmpLine;
  356. End
  357. Else p^.fileinfo.line := PPaiProp(p^.fileinfo.line)^.linesave;
  358. p := Pai(p^.Next);
  359. Inc(InstrCnt)
  360. End;
  361. If (NrOfPaiFast > 0) Then
  362. {$IfDef TP}
  363. Freemem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+1)div 2)*2))
  364. {$Else}
  365. FreeMem(PaiPropBlock, NrOfPaiFast*(((SizeOf(TPaiProp)+3)div 4)*4))
  366. {$EndIf TP}
  367. End;
  368. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  369. Begin
  370. DoCSE(First, Last);
  371. RemoveInstructs(AsmL, First, Last);
  372. End;
  373. End.
  374. {
  375. $Log$
  376. Revision 1.4 1998-08-06 19:40:27 jonas
  377. * removed $ before and after Log in comment
  378. Revision 1.3 1998/08/05 16:00:12 florian
  379. * some fixes for ansi strings
  380. * log to Log changed
  381. }