csopt386.pas 16 KB

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