csopt386.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  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(NewP)^.typ = ait_instruction) Then
  57. Case Pai386(NewP)^.op1t Of
  58. Top_Reg:
  59. If (Reg32(TRegister(Pai386(NewP)^.op1)) in RegsNotYetChecked) Then
  60. Begin
  61. RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(NewP)^.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(Newp)^.op1)))
  67. End;
  68. Top_Ref:
  69. With TReference(Pai386(NewP)^.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. If (hp2^.typ = ait_instruction) And
  114. (Pai386(hp2)^._operator in [a_mov, a_movsx, a_movzx]) And
  115. (Pai386(hp2)^.op2t = top_reg)
  116. Then RegsNotYetChecked := RegsNotYetChecked -
  117. [Reg32(TRegister(Pai386(hp2)^.op2))];
  118. GetNextInstruction(hp2, hp2);
  119. GetNextInstruction(hp3, hp3);
  120. Inc(Found)
  121. End;
  122. If (Found <> Counter)
  123. Then
  124. {hack to be able to optimize
  125. mov (mem), reg
  126. mov (reg), reg
  127. mov (reg), reg [*]
  128. test reg, reg and the oposite (where the marked instructions are
  129. jne l1 switched)
  130. mov (mem), reg
  131. mov (reg), reg
  132. movzx (reg), reg [*]}
  133. Begin
  134. If ((Found+1) = Counter) 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 and thus 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. If (p^.typ in SkipInstr) Then
  213. GetNextInstruction(p, p);
  214. First := p;
  215. While Assigned(p) Do
  216. Begin
  217. Case p^.typ Of
  218. ait_label, ait_labeled_instruction:;
  219. ait_instruction:
  220. Begin
  221. Case Pai386(p)^._operator Of
  222. A_CLD: If GetLastInstruction(p, hp1) And
  223. (PPaiProp(hp1^.fileinfo.line)^.DirFlag = F_NotSet) Then
  224. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  225. A_MOV, A_MOVZX, A_MOVSX:
  226. Begin
  227. Case Pai386(p)^.op1t Of
  228. { Top_Reg:
  229. Case Pai386(p)^.op2t Of
  230. Top_Reg:;
  231. Top_Ref:;
  232. End;}
  233. Top_Ref:
  234. Begin {destination is always a register in this case}
  235. With PPaiProp(p^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op2))] Do
  236. Begin
  237. If GetLastInstruction(p, hp1) And
  238. (PPaiProp(hp1^.fileinfo.line)^.
  239. Regs[Reg32(TRegister(Pai386(p)^.op2))].typ = con_ref) Then
  240. {so we don't try to check a sequence when the register only contains a constant}
  241. If CheckSequence(p, TRegister(Pai386(p)^.op2), Cnt) And
  242. (Cnt > 0)
  243. Then
  244. Begin
  245. hp1 := nil;
  246. {although it's perfectly ok to remove an instruction which doesn't contain
  247. the register that we've just checked (CheckSequence takes care of that),
  248. the sequence containing this other register should also be completely
  249. checked and removed, otherwise we may get situations like this:
  250. movl 12(%ebp), %edx movl 12(%ebp), %edx
  251. movl 16(%ebp), %eax movl 16(%ebp), %eax
  252. movl 8(%edx), %edx movl 8(%edx), %edx
  253. movl (%eax), eax movl (%eax), eax
  254. cmpl %eax, %edx cmpl %eax, %edx
  255. jnz l123 getting converted to jnz l123
  256. movl 12(%ebp), %edx movl 4(%eax), eax
  257. movl 16(%ebp), %eax
  258. movl 8(%edx), %edx
  259. movl 4(%eax), eax}
  260. hp2 := p;
  261. Cnt2 := 1;
  262. While Cnt2 <= Cnt Do
  263. Begin
  264. If (hp1 = nil) And
  265. Not(RegInInstruction(Tregister(Pai386(hp2)^.op2), p))
  266. Then hp1 := p;
  267. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  268. Inc(Cnt2);
  269. GetNextInstruction(p, p);
  270. End;
  271. If hp1 <> nil Then p := hp1;
  272. Continue;
  273. End
  274. Else
  275. If (Cnt > 0) And
  276. (PPaiProp(p^.fileinfo.line)^.CanBeRemoved) Then
  277. Begin
  278. hp2 := p;
  279. Cnt2 := 1;
  280. While Cnt2 <= Cnt Do
  281. Begin
  282. If RegInInstruction(Tregister(Pai386(hp2)^.op2), p)
  283. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := False;
  284. Inc(Cnt2);
  285. GetNextInstruction(p, p);
  286. End;
  287. Continue;
  288. End;
  289. End;
  290. End;
  291. Top_Const:
  292. Begin
  293. Case Pai386(p)^.op2t Of
  294. Top_Reg:
  295. Begin
  296. If GetLastInstruction(p, hp1) Then
  297. With PPaiProp(hp1^.fileinfo.line)^.Regs[Reg32(TRegister(Pai386(p)^.op2))] Do
  298. If (Typ = Con_Const) And
  299. (StartMod = Pai386(p)^.op1) Then
  300. PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True;
  301. End;
  302. { Top_Ref:;}
  303. End;
  304. End;
  305. End;
  306. End;
  307. A_STD: If GetLastInstruction(p, hp1) And
  308. (PPaiProp(hp1^.fileinfo.line)^.DirFlag = F_Set) Then
  309. PPaiProp(Pai(p)^.fileinfo.line)^.CanBeRemoved := True;
  310. A_XOR:
  311. Begin
  312. If (Pai386(p)^.op1t = top_reg) And
  313. (Pai386(p)^.op2t = top_reg) And
  314. (Pai386(p)^.op1 = Pai386(p)^.op2) And
  315. GetLastInstruction(p, hp1) And
  316. (PPaiProp(hp1^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].typ = con_const) And
  317. (PPaiProp(hp1^.fileinfo.line)^.Regs[Reg32(Tregister(Pai386(p)^.op1))].StartMod = Pointer(0))
  318. Then PPaiProp(p^.fileinfo.line)^.CanBeRemoved := True
  319. End
  320. End
  321. End;
  322. End;
  323. GetNextInstruction(p, p);
  324. End;
  325. End;
  326. Procedure RemoveInstructs(AsmL: PAasmOutput; First, Last: Pai);
  327. {Removes the marked instructions and disposes the PPaiProps of the other
  328. instructions, restoring theirline number}
  329. Var p, hp1: Pai;
  330. TmpLine, InstrCnt: Longint;
  331. Begin
  332. p := First;
  333. If (p^.typ in SkipInstr) Then
  334. GetNextInstruction(p, p);
  335. InstrCnt := 1;
  336. While Assigned(p) Do
  337. If PPaiProp(p^.fileinfo.line)^.CanBeRemoved
  338. Then
  339. Begin
  340. {$IfDef TP}
  341. Dispose(PPaiProp(p^.fileinfo.line));
  342. {$EndIf}
  343. GetNextInstruction(p, hp1);
  344. AsmL^.Remove(p);
  345. Dispose(p, Done);
  346. p := hp1;
  347. Inc(InstrCnt)
  348. End
  349. Else
  350. Begin
  351. {$IfDef TP}
  352. TmpLine := PPaiProp(p^.fileinfo.line)^.linesave;
  353. Dispose(PPaiProp(p^.fileinfo.line));
  354. p^.fileinfo.line := TmpLine;
  355. {$Else TP}
  356. p^.fileinfo.line := PPaiProp(p^.fileinfo.line)^.linesave;
  357. {$EndIf TP}
  358. GetNextInstruction(p, p);
  359. Inc(InstrCnt)
  360. End;
  361. {$IfNDef TP}
  362. FreeMem(PaiPropBlock, NrOfPaiObjs*(((SizeOf(TPaiProp)+3)div 4)*4))
  363. {$EndIf TP}
  364. End;
  365. Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
  366. Begin
  367. DoCSE(First, Last);
  368. RemoveInstructs(AsmL, First, Last);
  369. End;
  370. End.
  371. {
  372. $Log$
  373. Revision 1.6 1998-09-17 21:54:21 jonas
  374. * big error (with little consequences) corrected in NoChangedRegInRef
  375. Revision 1.5 1998/09/16 17:59:59 jonas
  376. * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc
  377. Revision 1.4 1998/08/06 19:40:27 jonas
  378. * removed $ before and after Log in comment
  379. Revision 1.3 1998/08/05 16:00:12 florian
  380. * some fixes for ansi strings
  381. * log to Log changed
  382. }