popt386.pas 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Floarian Klaempfl and Jonas Maebe
  4. This unit contains the peephole optimizer.
  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 POpt386;
  19. Interface
  20. Uses Aasm;
  21. Procedure PeepHoleOptPass1(AsmL: PAasmOutput);
  22. Procedure PeepHoleOptPass2(AsmL: PAasmOutput);
  23. Implementation
  24. Uses globals, systems, verbose, hcodegen
  25. {$ifdef i386}
  26. ,i386, DAOpt386
  27. {$endif i386}
  28. ;
  29. Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
  30. {updates RegsAllocated with the RegAlloc Information coming after P}
  31. Begin
  32. p := Pai(p^.next);
  33. Repeat
  34. While Assigned(p) And
  35. (p^.typ in (SkipInstr - [ait_RegAlloc, ait_RegDealloc])) Do
  36. p := Pai(p^.next);
  37. While Assigned(p) And
  38. (p^.typ in [ait_RegAlloc, ait_RegDealloc]) Do
  39. Begin
  40. Case p^.typ Of
  41. ait_RegAlloc: UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg];
  42. ait_regdealloc: UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
  43. End;
  44. p := pai(p^.next);
  45. End;
  46. Until Not(Assigned(p)) Or
  47. Not(p^.typ in SkipInstr);
  48. End;
  49. Function RegUsedAfterInstruction(Reg: TRegister; p: Pai; Var UsedRegs: TRegSet): Boolean;
  50. Begin
  51. UpdateUsedRegs(UsedRegs, p);
  52. RegUsedAfterInstruction := Reg in UsedRegs
  53. End;
  54. Procedure PeepHoleOptPass1(Asml: PAasmOutput);
  55. {First pass of peepholeoptimizations}
  56. Var
  57. p ,hp1, hp2: pai;
  58. TmpBool1, TmpBool2: Boolean;
  59. TmpRef: PReference;
  60. UsedRegs, TmpUsedRegs: TRegSet;
  61. Procedure GetFinalDestination(hp: pai_labeled);
  62. {traces sucessive jumps to their final destination and sets it, e.g.
  63. je l1 je l3
  64. <code> <code>
  65. l1: becomes l1:
  66. je l2 je l3
  67. <code> <code>
  68. l2: l2:
  69. jmp l3 jmp l3}
  70. Var p1: pai;
  71. Function SkipLabels(hp: Pai): Pai;
  72. {skips all labels and returns the next "real" instruction; it is
  73. assumed that hp is of the type ait_label}
  74. Begin
  75. While assigned(hp^.next) and
  76. (pai(hp^.next)^.typ In SkipInstr + [ait_label]) Do
  77. hp := pai(hp^.next);
  78. If assigned(hp^.next)
  79. Then SkipLabels := pai(hp^.next)
  80. Else SkipLabels := hp;
  81. End;
  82. Begin
  83. If (hp^.lab^.nb >= LoLab) and
  84. (hp^.lab^.nb <= HiLab) and {range check, necessary?}
  85. (Pointer(LTable^[hp^.lab^.nb-LoLab].PaiObj) <> Pointer(0)) Then
  86. Begin
  87. p1 := LTable^[hp^.lab^.nb-LoLab].PaiObj; {the jump's destination}
  88. p1 := SkipLabels(p1);
  89. If (pai(p1)^.typ = ait_labeled_instruction) and
  90. ((pai_labeled(p1)^._operator = A_JMP) or
  91. (pai_labeled(p1)^._operator = hp^._operator))
  92. Then
  93. Begin
  94. GetFinalDestination(pai_labeled(p1));
  95. Dec(hp^.lab^.refcount);
  96. If (hp^.lab^.refcount = 0) Then
  97. hp^.lab^.is_used := False;
  98. hp^.lab := pai_labeled(p1)^.lab;
  99. Inc(hp^.lab^.refcount);
  100. End
  101. End
  102. End;
  103. Begin
  104. P := Pai(AsmL^.First);
  105. UsedRegs := [];
  106. While Assigned(P) Do
  107. Begin
  108. UpDateUsedRegs(UsedRegs, p);
  109. Case P^.Typ Of
  110. Ait_Labeled_Instruction:
  111. Begin
  112. {the following if-block removes all code between a jmp and the next label,
  113. because it can never be executed}
  114. If (pai_labeled(p)^._operator = A_JMP) Then
  115. Begin
  116. hp1 := pai(p^.next);
  117. While GetNextInstruction(p, hp1) and
  118. (hp1^.typ <> ait_label) Do
  119. Begin
  120. AsmL^.Remove(hp1);
  121. Dispose(hp1, done);
  122. End;
  123. End;
  124. If GetNextInstruction(p, hp1) then
  125. Begin
  126. If (pai(hp1)^.typ=ait_labeled_instruction) and
  127. (pai_labeled(hp1)^._operator=A_JMP) and
  128. GetNextInstruction(hp1, hp2) And
  129. FindLabel(pai_labeled(p)^.lab, hp2)
  130. Then
  131. Begin
  132. Case pai_labeled(p)^._operator Of
  133. A_JE : pai_labeled(p)^._operator:=A_JNE;
  134. A_JNE : pai_labeled(p)^._operator:=A_JE;
  135. A_JL : pai_labeled(p)^._operator:=A_JGE;
  136. A_JG : pai_labeled(p)^._operator:=A_JLE;
  137. A_JLE : pai_labeled(p)^._operator:=A_JG;
  138. A_JGE : pai_labeled(p)^._operator:=A_JL;
  139. A_JNZ : pai_labeled(p)^._operator:=A_JZ;
  140. A_JNO : pai_labeled(p)^._operator:=A_JO;
  141. A_JZ : pai_labeled(p)^._operator:=A_JNZ;
  142. A_JS : pai_labeled(p)^._operator:=A_JNS;
  143. A_JNS : pai_labeled(p)^._operator:=A_JS;
  144. A_JO : pai_labeled(p)^._operator:=A_JNO;
  145. A_JC : pai_labeled(p)^._operator:=A_JNC;
  146. A_JNC : pai_labeled(p)^._operator:=A_JC;
  147. A_JA : pai_labeled(p)^._operator:=A_JBE;
  148. A_JAE : pai_labeled(p)^._operator:=A_JB;
  149. A_JB : pai_labeled(p)^._operator:=A_JAE;
  150. A_JBE : pai_labeled(p)^._operator:=A_JA;
  151. Else
  152. begin
  153. If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
  154. p:=pai(p^.next);
  155. continue;
  156. end;
  157. end;
  158. Dec(pai_label(hp2)^.l^.refcount);
  159. If (pai_label(hp2)^.l^.refcount = 0) Then
  160. Begin
  161. pai_label(hp2)^.l^.is_used := False;
  162. { AsmL^.remove(hp2);
  163. Dispose(hp2, done);}
  164. End;
  165. pai_labeled(p)^.lab:=pai_labeled(hp1)^.lab;
  166. Inc(pai_labeled(p)^.lab^.refcount);
  167. asml^.remove(hp1);
  168. dispose(hp1,done);
  169. If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
  170. end
  171. else
  172. Begin
  173. if FindLabel(pai_labeled(p)^.lab, hp1) then
  174. begin
  175. hp2:=pai(hp1^.next);
  176. asml^.remove(p);
  177. dispose(p,done);
  178. { If Not(pai_label(hp1)^.l^.is_used) Then
  179. Begin
  180. AsmL^.remove(hp1);
  181. Dispose(hp1, done);
  182. End;}
  183. p:=hp2;
  184. continue;
  185. end;
  186. If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
  187. end;
  188. end
  189. end;
  190. ait_instruction:
  191. Begin
  192. If (Pai386(p)^.op1t = top_ref) Then
  193. With TReference(Pai386(p)^.op1^) Do
  194. Begin
  195. If (base = R_NO) And
  196. (scalefactor = 1)
  197. Then
  198. Begin
  199. base := index;
  200. index := r_no
  201. End
  202. End;
  203. If (Pai386(p)^.op2t = top_ref) Then
  204. With TReference(Pai386(p)^.op2^) Do
  205. Begin
  206. If (base = R_NO) And
  207. (scalefactor = 1)
  208. Then
  209. Begin
  210. base := index;
  211. index := r_no
  212. End
  213. End;
  214. Case Pai386(p)^._operator Of
  215. A_AND:
  216. Begin
  217. If (Pai386(p)^.op1t = top_const) And
  218. (Pai386(p)^.op2t = top_reg) And
  219. GetNextInstruction(p, hp1) And
  220. (Pai(hp1)^.typ = ait_instruction) And
  221. (Pai386(hp1)^._operator = A_AND) And
  222. (Pai386(hp1)^.op1t = top_const) And
  223. (Pai386(hp1)^.op2t = top_reg) And
  224. (Pai386(hp1)^.op2 = Pai386(hp1)^.op2)
  225. Then
  226. {change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
  227. Begin
  228. Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) And Longint(Pai386(hp1)^.op1));
  229. AsmL^.Remove(hp1);
  230. Dispose(hp1, Done)
  231. End
  232. Else
  233. {change "and x, reg; jxx" to "test x, reg", if reg is deallocated before the
  234. jump}
  235. If (Pai386(p)^.op2t = top_reg) And
  236. GetNextInstruction(p, hp1) And
  237. (hp1^.typ = ait_labeled_instruction) And
  238. Not(TRegister(Pai386(p)^.op2) in UsedRegs)
  239. Then Pai386(p)^._operator := A_TEST;
  240. End;
  241. A_CMP:
  242. Begin
  243. If (Pai386(p)^.op1t = top_const) And
  244. (Pai386(p)^.op2t = top_reg) And
  245. (Pai386(p)^.op1 = Pointer(0)) Then
  246. {change "cmp $0, %reg" to "test %reg, %reg"}
  247. Begin
  248. Pai386(p)^._operator := A_TEST;
  249. Pai386(p)^.opxt := Top_reg+Top_reg shl 4;
  250. Pai386(p)^.op1 := Pai386(p)^.op2;
  251. End;
  252. End;
  253. A_FSTP:
  254. Begin
  255. If (Pai386(p)^.op1t = top_ref) And
  256. GetNextInstruction(p, hp1) And
  257. (Pai(hp1)^.typ = ait_instruction) And
  258. (Pai386(hp1)^._operator = A_FLD) And
  259. (Pai386(hp1)^.op1t = top_ref) And
  260. (Pai386(hp1)^.Size = Pai386(p)^.Size) And
  261. RefsEqual(TReference(Pai386(p)^.op1^), TReference(Pai386(hp1)^.op1^))
  262. Then
  263. Begin
  264. If GetNextInstruction(hp1, hp2) And
  265. (hp2^.typ = ait_instruction) And
  266. ((Pai386(hp2)^._operator = A_LEAVE) Or
  267. (Pai386(hp2)^._operator = A_RET)) And
  268. (TReference(Pai386(p)^.op1^).Base = ProcInfo.FramePointer) And
  269. (TReference(Pai386(p)^.op1^).Offset >= ProcInfo.RetOffset) And
  270. (TReference(Pai386(p)^.op1^).Index = R_NO)
  271. Then
  272. Begin
  273. AsmL^.Remove(p);
  274. AsmL^.Remove(hp1);
  275. Dispose(p, Done);
  276. Dispose(hp1, Done);
  277. p := hp2;
  278. Continue
  279. End
  280. Else
  281. {fst can't store an extended value!}
  282. If (Pai386(p)^.Size <> S_FX) Then
  283. Begin
  284. Pai386(p)^._operator := A_FST;
  285. AsmL^.Remove(hp1);
  286. Dispose(hp1, done)
  287. End
  288. End;
  289. End;
  290. A_IMUL:
  291. {changes certain "imul const, %reg"'s to lea sequences}
  292. Begin
  293. If (Pai386(p)^.op1t = Top_Const) And
  294. (Pai386(p)^.op2t = Top_Reg) And
  295. (Pai386(p)^.Size = S_L) And
  296. ((Pai386(p)^.op3t = Top_Reg) or
  297. (Pai386(p)^.op3t = Top_None)) And
  298. (aktoptprocessor < ClassP6) And
  299. (Longint(Pai386(p)^.op1) <= 12) And
  300. Not(CS_LittleSize in aktglobalswitches) And
  301. (Not(GetNextInstruction(p, hp1)) Or
  302. {GetNextInstruction(p, hp1) And}
  303. Not((Pai(hp1)^.typ = ait_labeled_instruction) And
  304. ((pai_labeled(hp1)^._operator = A_JO) or
  305. (pai_labeled(hp1)^._operator = A_JNO))))
  306. Then
  307. Begin
  308. New(TmpRef);
  309. TmpRef^.segment := R_DEFAULT_SEG;
  310. TmpRef^.symbol := nil;
  311. TmpRef^.isintvalue := false;
  312. TmpRef^.offset := 0;
  313. Case Longint(Pai386(p)^.op1) Of
  314. 3: Begin
  315. {imul 3, reg1, reg2 to
  316. lea (reg1,reg1,2), reg2
  317. imul 3, reg1 to
  318. lea (reg1,reg1,2), reg1}
  319. TmpRef^.base := TRegister(Pai386(p)^.op2);
  320. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  321. TmpRef^.ScaleFactor := 2;
  322. If (Pai386(p)^.op3t = Top_None)
  323. Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
  324. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  325. TRegister(twowords(Pai386(p)^.op2).word2)));
  326. hp1^.fileinfo := p^.fileinfo;
  327. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  328. Dispose(p, Done);
  329. p := hp1;
  330. End;
  331. 5: Begin
  332. {imul 5, reg1, reg2 to
  333. lea (reg1,reg1,4), reg2
  334. imul 5, reg1 to
  335. lea (reg1,reg1,4), reg1}
  336. TmpRef^.base := TRegister(Pai386(p)^.op2);
  337. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  338. TmpRef^.ScaleFactor := 4;
  339. If (Pai386(p)^.op3t = Top_None)
  340. Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
  341. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  342. TRegister(twowords(Pai386(p)^.op2).word2)));
  343. hp1^.fileinfo:= p^.fileinfo;
  344. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  345. Dispose(p, Done);
  346. p := hp1;
  347. End;
  348. 6: Begin
  349. {imul 6, reg1, reg2 to
  350. lea (,reg1,2), reg2
  351. lea (reg2,reg1,4), reg2
  352. imul 6, reg1 to
  353. lea (reg1,reg1,2), reg1
  354. add reg1, reg1}
  355. If (aktoptprocessor <= Class386)
  356. Then
  357. Begin
  358. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  359. If (Pai386(p)^.op3t = Top_Reg)
  360. Then
  361. Begin
  362. TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
  363. TmpRef^.ScaleFactor := 4;
  364. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  365. TRegister(twowords(Pai386(p)^.op2).word2)));
  366. End
  367. Else
  368. Begin
  369. Dispose(TmpRef);
  370. hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
  371. TRegister(Pai386(p)^.op2),TRegister(Pai386(p)^.op2)));
  372. End;
  373. hp1^.fileinfo := p^.fileinfo;
  374. InsertLLItem(AsmL,p, p^.next, hp1);
  375. New(TmpRef);
  376. TmpRef^.segment := R_DEFAULT_SEG;
  377. TmpRef^.symbol := nil;
  378. TmpRef^.isintvalue := false;
  379. TmpRef^.offset := 0;
  380. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  381. TmpRef^.ScaleFactor := 2;
  382. If (Pai386(p)^.op3t = Top_Reg)
  383. Then
  384. Begin
  385. TmpRef^.base := R_NO;
  386. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  387. TRegister(twowords(Pai386(p)^.op2).word2)));
  388. End
  389. Else
  390. Begin
  391. TmpRef^.base := TRegister(Pai386(p)^.op2);
  392. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)));
  393. End;
  394. hp1^.fileinfo := p^.fileinfo;
  395. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  396. Dispose(p, Done);
  397. p := Pai(hp1^.next);
  398. End
  399. Else Dispose(TmpRef);
  400. End;
  401. 9: Begin
  402. {imul 9, reg1, reg2 to
  403. lea (reg1,reg1,8), reg2
  404. imul 9, reg1 to
  405. lea (reg1,reg1,8), reg1}
  406. TmpRef^.base := TRegister(Pai386(p)^.op2);
  407. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  408. TmpRef^.ScaleFactor := 8;
  409. If (Pai386(p)^.op3t = Top_None)
  410. Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
  411. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  412. TRegister(twowords(Pai386(p)^.op2).word2)));
  413. hp1^.fileinfo := p^.fileinfo;
  414. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  415. Dispose(p, Done);
  416. p := hp1;
  417. End;
  418. 10: Begin
  419. {imul 10, reg1, reg2 to
  420. lea (reg1,reg1,4), reg2
  421. add reg2, reg2
  422. imul 10, reg1 to
  423. lea (reg1,reg1,4), reg1
  424. add reg1, reg1}
  425. If (aktoptprocessor <= Class386) Then
  426. Begin
  427. If (Pai386(p)^.op3t = Top_Reg)
  428. Then
  429. hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
  430. Tregister(twowords(Pai386(p)^.op2).word2),
  431. Tregister(twowords(Pai386(p)^.op2).word2)))
  432. Else hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
  433. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
  434. hp1^.fileinfo := p^.fileinfo;
  435. InsertLLItem(AsmL,p, p^.next, hp1);
  436. TmpRef^.base := TRegister(Pai386(p)^.op2);
  437. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  438. TmpRef^.ScaleFactor := 4;
  439. If (Pai386(p)^.op3t = Top_Reg)
  440. Then
  441. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  442. TRegister(twowords(Pai386(p)^.op2).word2)))
  443. Else
  444. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  445. TRegister(Pai386(p)^.op2)));
  446. hp1^.fileinfo := p^.fileinfo;
  447. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  448. Dispose(p, Done);
  449. p := Pai(hp1^.next);
  450. End
  451. Else Dispose(TmpRef);
  452. End;
  453. 12: Begin
  454. {imul 12, reg1, reg2 to
  455. lea (,reg1,4), reg2
  456. lea (,reg1,8) reg2
  457. imul 12, reg1 to
  458. lea (reg1,reg1,2), reg1
  459. lea (,reg1,4), reg1}
  460. If (aktoptprocessor <= Class386)
  461. Then
  462. Begin
  463. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  464. If (Pai386(p)^.op3t = Top_Reg)
  465. Then
  466. Begin
  467. TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
  468. TmpRef^.ScaleFactor := 8;
  469. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  470. TRegister(twowords(Pai386(p)^.op2).word2)));
  471. End
  472. Else
  473. Begin
  474. TmpRef^.base := R_NO;
  475. TmpRef^.ScaleFactor := 4;
  476. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  477. TRegister(Pai386(p)^.op2)));
  478. End;
  479. hp1^.fileinfo := p^.fileinfo;
  480. InsertLLItem(AsmL,p, p^.next, hp1);
  481. New(TmpRef);
  482. TmpRef^.segment := R_DEFAULT_SEG;
  483. TmpRef^.symbol := nil;
  484. TmpRef^.isintvalue := false;
  485. TmpRef^.offset := 0;
  486. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  487. If (Pai386(p)^.op3t = Top_Reg)
  488. Then
  489. Begin
  490. TmpRef^.base := R_NO;
  491. TmpRef^.ScaleFactor := 4;
  492. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  493. TRegister(twowords(Pai386(p)^.op2).word2)));
  494. End
  495. Else
  496. Begin
  497. TmpRef^.base := TRegister(Pai386(p)^.op2);
  498. TmpRef^.ScaleFactor := 2;
  499. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  500. TRegister(Pai386(p)^.op2)));
  501. End;
  502. hp1^.fileinfo := p^.fileinfo;
  503. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  504. Dispose(p, Done);
  505. p := Pai(hp1^.next);
  506. End
  507. Else Dispose(TmpRef);
  508. End
  509. Else Dispose(TmpRef);
  510. End;
  511. End;
  512. End;
  513. A_LEA:
  514. Begin
  515. {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
  516. If (PReference(Pai386(p)^.op1)^.Base In [R_EAX..R_EDI]) And
  517. (PReference(Pai386(p)^.op1)^.Index = R_NO) And
  518. (PReference(Pai386(p)^.op1)^.Offset = 0) And
  519. (Not(Assigned(PReference(Pai386(p)^.op1)^.Symbol))) Then
  520. Begin
  521. hp1 := New(Pai386, op_reg_reg(A_MOV, S_L,PReference(Pai386(p)^.op1)^.Base,
  522. TRegister(Pai386(p)^.op2)));
  523. hp1^.fileinfo := p^.fileinfo;
  524. InsertLLItem(AsmL,p^.previous,p^.next, hp1);
  525. Dispose(p, Done);
  526. p := hp1;
  527. Continue;
  528. End;
  529. End;
  530. A_MOV:
  531. Begin
  532. TmpUsedRegs := UsedRegs;
  533. If (Pai386(p)^.op2t = top_reg) And
  534. (TRegister(Pai386(p)^.op2) In [R_EAX, R_EBX, R_EDX, R_EDI]) And
  535. GetNextInstruction(p, hp1) And
  536. (Pai(hp1)^.typ = ait_instruction) And
  537. (Pai386(hp1)^._operator = A_MOV) And
  538. (Pai386(hp1)^.op1t = top_reg) And
  539. (Pai386(hp1)^.op1 = Pai386(p)^.op2)
  540. Then
  541. {we have "mov x, %treg; mov %treg, y}
  542. If (Pai386(hp1)^.op2t <> top_reg) Or
  543. (GetNextInstruction(hp1, hp2) And
  544. (RegUsedAfterInstruction(TRegister(Pai386(hp1)^.op2), hp1, TmpUsedRegs) or
  545. {now TmpUsedRegs contains the regalloc data after hp1}
  546. (RegInInstruction(TRegister(Pai386(hp1)^.op2), hp2))) And
  547. Not(TRegister(Pai386(hp1)^.op1) in TmpUsedRegs))
  548. Then
  549. {we've got "mov x, %treg; mov %treg, y; XXX y" (ie. y is used in
  550. the third instruction)}
  551. Case Pai386(p)^.op1t Of
  552. top_reg:
  553. {change "mov %reg, %treg; mov %treg, y"
  554. to "mov %reg, y"}
  555. Begin
  556. Pai386(hp1)^.op1 := Pai386(p)^.op1;
  557. AsmL^.Remove(p);
  558. Dispose(p, Done);
  559. p := hp1;
  560. continue;
  561. End;
  562. top_ref:
  563. If (Pai386(hp1)^.op2t = top_reg)
  564. Then
  565. {change "mov mem, %treg; mov %treg, %reg"
  566. to "mov mem, %reg"}
  567. Begin
  568. Pai386(p)^.op2 := Pai386(hp1)^.op2;
  569. AsmL^.Remove(hp1);
  570. Dispose(hp1, Done);
  571. continue;
  572. End;
  573. End
  574. Else
  575. {remove an instruction which never makes sense: we've got
  576. "mov mem, %reg1; mov %reg1, %edi" and then EDI isn't used anymore!}
  577. { Begin
  578. If (TRegister(Pai386(hp1)^.op2) = R_EDI) And
  579. Not(GetNextInstruction(hp1, hp2) And
  580. (Pai(hp2)^.typ = ait_instruction) And
  581. (Pai386(hp2)^.op2t = top_reg) And
  582. (Pai386(hp2)^.op2 = Pointer(R_ESI))) Then
  583. Begin
  584. AsmL^.Remove(hp1);
  585. Dispose(hp1, Done);
  586. Continue;
  587. End
  588. End}
  589. Else
  590. {Change "mov %reg1, %reg2; xxx %reg2, ???" to
  591. "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
  592. penalty}
  593. If (Pai386(p)^.op1t = top_reg) And
  594. (Pai386(p)^.op2t = top_reg) And
  595. GetNextInstruction(p,hp1) And
  596. (Pai(hp1)^.typ = ait_instruction) And
  597. (Pai386(hp1)^.op1t = top_reg) And
  598. (Pai386(hp1)^.op1 = Pai386(p)^.op2)
  599. Then
  600. {we have "mov %reg1, %reg2; XXX %reg2, ???"}
  601. Begin
  602. If ((Pai386(hp1)^._operator = A_OR) Or
  603. (Pai386(hp1)^._operator = A_TEST)) And
  604. (Pai386(hp1)^.op2t = top_reg) And
  605. (Pai386(hp1)^.op1 = Pai386(hp1)^.op2)
  606. Then
  607. {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
  608. Begin
  609. TmpUsedRegs := UsedRegs;
  610. If GetNextInstruction(hp1, hp2) And
  611. (hp2^.typ = ait_labeled_instruction) And
  612. Not(RegUsedAfterInstruction(TRegister(Pai386(hp1)^.op1), hp1, TmpUsedRegs))
  613. Then
  614. {change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
  615. "test %reg1, %reg1; jxx"}
  616. Begin
  617. Pai386(hp1)^.op1 := Pai386(p)^.op1;
  618. Pai386(hp1)^.op2 := Pai386(p)^.op1;
  619. AsmL^.Remove(p);
  620. Dispose(p, done);
  621. p := hp1;
  622. continue
  623. End
  624. Else
  625. {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
  626. "mov %reg1, %reg2; test/or %reg1, %reg1"}
  627. Begin
  628. Pai386(hp1)^.op1 := Pai386(p)^.op1;
  629. Pai386(hp1)^.op2 := Pai386(p)^.op1;
  630. End;
  631. End
  632. { Else
  633. If (Pai386(p^.next)^._operator
  634. In [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
  635. {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
  636. "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
  637. End
  638. Else
  639. {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
  640. x >= RetOffset) as it doesn't do anything (it writes either to a
  641. parameter or to the temporary storage room for the function
  642. result)}
  643. If GetNextInstruction(p, hp1) And
  644. (Pai(hp1)^.typ = ait_instruction)
  645. Then
  646. If ((Pai386(hp1)^._operator = A_LEAVE) Or
  647. (Pai386(hp1)^._operator = A_RET)) And
  648. (Pai386(p)^.op2t = top_ref) And
  649. (TReference(Pai386(p)^.op2^).base = ProcInfo.FramePointer) And
  650. (TReference(Pai386(p)^.op2^).offset >= ProcInfo.RetOffset) And
  651. (TReference(Pai386(p)^.op2^).index = R_NO) And
  652. (Pai386(p)^.op1t = top_reg)
  653. Then
  654. Begin
  655. AsmL^.Remove(p);
  656. Dispose(p, done);
  657. p := hp1;
  658. End
  659. Else
  660. If (Pai386(p)^.op1t = top_reg) And
  661. (Pai386(p)^.op2t = top_ref) And
  662. (Pai386(p)^.Size = Pai386(hp1)^.Size) And
  663. (Pai386(hp1)^._operator = A_CMP) And
  664. (Pai386(hp1)^.op2t = top_ref) And
  665. RefsEqual(TReference(Pai386(p)^.op2^),
  666. TReference(Pai386(hp1)^.op2^))
  667. Then
  668. {change "mov reg, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
  669. Begin
  670. Dispose(PReference(Pai386(hp1)^.op2));
  671. Pai386(hp1)^.opxt := Pai386(hp1)^.op1t + (top_reg shl 4);
  672. Pai386(hp1)^.op2 := Pai386(p)^.op1
  673. End;
  674. { Next instruction is also a MOV ? }
  675. If GetNextInstruction(p, hp1) And
  676. (pai(hp1)^.typ = ait_instruction) and
  677. (Pai386(hp1)^._operator = A_MOV)
  678. Then
  679. Begin
  680. If (Pai386(hp1)^.op1t = Pai386(p)^.op2t) and
  681. (Pai386(hp1)^.op2t = Pai386(p)^.op1t)
  682. Then
  683. {mov reg1, mem1 or mov mem1, reg1
  684. mov mem2, reg2 mov reg2, mem2}
  685. Begin
  686. If (Pai386(hp1)^.op2t = top_ref)
  687. Then
  688. TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op2^), TReference(Pai386(p)^.op1^))
  689. Else
  690. TmpBool1 := Pai386(hp1)^.op2 = Pai386(p)^.op1;
  691. If TmpBool1
  692. Then
  693. {mov reg1, mem1 or mov mem1, reg1
  694. mov mem2, reg1 mov reg2, mem1}
  695. Begin
  696. If (Pai386(hp1)^.op1t = top_ref)
  697. Then
  698. TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op1^),
  699. TReference(Pai386(p)^.op2^))
  700. Else TmpBool1 := (Pai386(hp1)^.op1 = Pai386(p)^.op2);
  701. If TmpBool1 Then
  702. { Removes the second statement from
  703. mov reg1, mem1
  704. mov mem1, reg1 }
  705. Begin
  706. AsmL^.remove(hp1);
  707. Dispose(hp1,done);
  708. End;
  709. End
  710. Else
  711. Begin
  712. If GetNextInstruction(hp1, hp2) And
  713. (Pai386(p)^.op1t = top_ref) And
  714. (Pai386(p)^.op2t = top_reg) And
  715. (Pai386(hp1)^.op1t = top_reg) And
  716. (Pai386(hp1)^.op1 = Pai386(p)^.op2) And
  717. (Pai386(hp1)^.op2t = top_ref) And
  718. (Pai(hp2)^.typ = ait_instruction) And
  719. (Pai386(hp2)^._operator = A_MOV) And
  720. (Pai386(hp2)^.op2t = top_reg) And
  721. (Pai386(hp2)^.op1t = top_ref) And
  722. RefsEqual(TReference(Pai386(hp2)^.op1^),
  723. TReference(Pai386(hp1)^.op2^))
  724. Then
  725. If (TRegister(Pai386(p)^.op2) = R_EDI)
  726. Then
  727. { mov mem1, reg1
  728. mov reg1, mem2
  729. mov mem2, reg2
  730. to:
  731. mov mem1, reg2
  732. mov reg2, mem2}
  733. Begin
  734. Pai386(p)^.op2 := Pai386(hp2)^.op2;
  735. Pai386(hp1)^.op1 := Pai386(hp2)^.op2;
  736. AsmL^.Remove(hp2);
  737. Dispose(hp2,Done);
  738. End
  739. Else
  740. { mov mem1, reg1
  741. mov reg1, mem2
  742. mov mem2, reg2
  743. to:
  744. mov mem1, reg1
  745. mov mem1, reg2
  746. mov reg1, mem2}
  747. Begin
  748. Pai386(hp1)^.opxt := top_ref + top_reg shl 4;
  749. Pai386(hp1)^.op1 := Pai386(hp1)^.op2; {move the treference}
  750. TReference(Pai386(hp1)^.op1^) := TReference(Pai386(p)^.op1^);
  751. If Assigned(TReference(Pai386(p)^.op1^).Symbol) Then
  752. Begin
  753. New(TReference(Pai386(hp1)^.op1^).Symbol);
  754. TReference(Pai386(hp1)^.op1^).Symbol^ :=
  755. TReference(Pai386(p)^.op1^).Symbol^;
  756. End;
  757. Pai386(hp1)^.op2 := Pai386(hp2)^.op2;
  758. Pai386(hp2)^.opxt := top_reg + top_ref shl 4;
  759. Pai386(hp2)^.op2 := Pai386(hp2)^.op1;
  760. Pai386(hp2)^.op1 := Pai386(p)^.op2;
  761. End;
  762. End;
  763. End
  764. Else
  765. (* {movl [mem1],reg1
  766. movl [mem1],reg2
  767. to:
  768. movl [mem1],reg1
  769. movl reg1,reg2 }
  770. If (Pai386(p)^.op1t = top_ref) and
  771. (Pai386(p)^.op2t = top_reg) and
  772. (Pai386(hp1)^.op1t = top_ref) and
  773. (Pai386(hp1)^.op2t = top_reg) and
  774. (Pai386(p)^.size = Pai386(hp1)^.size) and
  775. RefsEqual(TReference(Pai386(p)^.op1^),TReference(Pai386(hp1)^.op1^)) and
  776. (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).base) and
  777. (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).index) then
  778. Begin
  779. Dispose(PReference(Pai386(hp1)^.op1));
  780. Pai386(hp1)^.op1:=Pai386(p)^.op2;
  781. Pai386(hp1)^.opxt:=Top_reg+Top_reg shl 4;
  782. End
  783. Else*)
  784. { movl const1,[mem1]
  785. movl [mem1],reg1
  786. to:
  787. movl const1,reg1
  788. movl reg1,[mem1] }
  789. If (Pai386(p)^.op1t = top_const) and
  790. (Pai386(p)^.op2t = top_ref) and
  791. (Pai386(hp1)^.op1t = top_ref) and
  792. (Pai386(hp1)^.op2t = top_reg) and
  793. (Pai386(p)^.size = Pai386(hp1)^.size) and
  794. RefsEqual(TReference(Pai386(hp1)^.op1^),TReference(Pai386(p)^.op2^)) then
  795. Begin
  796. Pai386(hp1)^.op1:=Pai386(hp1)^.op2;
  797. Pai386(hp1)^.op2:=Pai386(p)^.op2;
  798. Pai386(hp1)^.opxt:=Top_reg+Top_ref shl 4;
  799. Pai386(p)^.op2:=Pai386(hp1)^.op1;
  800. Pai386(p)^.opxt:=Top_const+(top_reg shl 4);
  801. End
  802. End;
  803. {changes "mov $0, %reg" into "xor %reg, %reg"}
  804. If (Pai386(p)^.op1t = Top_Const) And
  805. (Pai386(p)^.op1 = Pointer(0)) And
  806. (Pai386(p)^.op2t = Top_Reg)
  807. Then
  808. Begin
  809. Pai386(p)^._operator := A_XOR;
  810. Pai386(p)^.opxt := Top_Reg+Top_reg shl 4;
  811. Pai386(p)^.op1 := Pai386(p)^.op2;
  812. End;
  813. End;
  814. A_MOVZX:
  815. Begin
  816. {removes superfluous And's after movzx's}
  817. If (Pai386(p)^.op2t = top_reg) And
  818. GetNextInstruction(p, hp1) And
  819. (Pai(hp1)^.typ = ait_instruction) And
  820. (Pai386(hp1)^._operator = A_AND) And
  821. (Pai386(hp1)^.op1t = top_const) And
  822. (Pai386(hp1)^.op2t = top_reg) And
  823. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  824. Then
  825. Case Pai386(p)^.Size Of
  826. S_BL, S_BW:
  827. If (Longint(Pai386(hp1)^.op1) = $ff)
  828. Then
  829. Begin
  830. AsmL^.Remove(hp1);
  831. Dispose(hp1, Done);
  832. End;
  833. S_WL:
  834. If (Longint(Pai386(hp1)^.op1) = $ffff)
  835. Then
  836. Begin
  837. AsmL^.Remove(hp1);
  838. Dispose(hp1, Done);
  839. End;
  840. End;
  841. {changes some movzx constructs to faster synonims (all examples
  842. are given with eax/ax, but are also valid for other registers)}
  843. If (Pai386(p)^.op2t = top_reg) Then
  844. If (Pai386(p)^.op1t = top_reg)
  845. Then
  846. Case Pai386(p)^.size of
  847. S_BW:
  848. Begin
  849. If (TRegister(Pai386(p)^.op1) = Reg16ToReg8(TRegister(Pai386(p)^.op2))) And
  850. Not(CS_LittleSize In aktglobalswitches)
  851. Then
  852. {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
  853. Begin
  854. Pai386(p)^._operator := A_AND;
  855. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  856. Longint(Pai386(p)^.op1) := $ff;
  857. Pai386(p)^.Size := S_W
  858. End
  859. Else
  860. If GetNextInstruction(p, hp1) And
  861. (Pai(hp1)^.typ = ait_instruction) And
  862. (Pai386(hp1)^._operator = A_AND) And
  863. (Pai386(hp1)^.op1t = top_const) And
  864. (Pai386(hp1)^.op2t = top_reg) And
  865. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  866. Then
  867. {Change "movzbw %reg1, %reg2; andw $const, %reg2"
  868. to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
  869. Begin
  870. Pai386(p)^._operator := A_MOV;
  871. Pai386(p)^.Size := S_W;
  872. Pai386(p)^.op1 := Pointer(Reg8ToReg16(TRegister(Pai386(p)^.op1)));
  873. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
  874. End;
  875. End;
  876. S_BL:
  877. Begin
  878. If (TRegister(Pai386(p)^.op1) = Reg32ToReg8(TRegister(Pai386(p)^.op2))) And
  879. Not(CS_LittleSize in aktglobalswitches)
  880. Then
  881. {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
  882. Begin
  883. Pai386(p)^._operator := A_AND;
  884. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  885. Longint(Pai386(p)^.op1) := $ff;
  886. Pai386(p)^.Size := S_L;
  887. End
  888. Else
  889. If GetNextInstruction(p, hp1) And
  890. (Pai(hp1)^.typ = ait_instruction) And
  891. (Pai386(hp1)^._operator = A_AND) And
  892. (Pai386(hp1)^.op1t = top_const) And
  893. (Pai386(hp1)^.op2t = top_reg) And
  894. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  895. Then
  896. {Change "movzbl %reg1, %reg2; andl $const, %reg2"
  897. to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
  898. Begin
  899. Pai386(p)^._operator := A_MOV;
  900. Pai386(p)^.Size := S_L;
  901. Pai386(p)^.op1 := Pointer(Reg8ToReg32(TRegister(Pai386(p)^.op1)));
  902. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
  903. End
  904. End;
  905. S_WL:
  906. Begin
  907. If (TRegister(Pai386(p)^.op1) = Reg32ToReg16(TRegister(Pai386(p)^.op2))) And
  908. Not(CS_LittleSize In aktglobalswitches)
  909. Then
  910. {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
  911. Begin
  912. Pai386(p)^._operator := A_AND;
  913. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  914. Longint(Pai386(p)^.op1) := $ffff;
  915. Pai386(p)^.Size := S_L
  916. End
  917. Else
  918. If GetNextInstruction(p, hp1) And
  919. (Pai(hp1)^.typ = ait_instruction) And
  920. (Pai386(hp1)^._operator = A_AND) And
  921. (Pai386(hp1)^.op1t = top_const) And
  922. (Pai386(hp1)^.op2t = top_reg) And
  923. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  924. Then
  925. {Change "movzwl %reg1, %reg2; andl $const, %reg2"
  926. to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
  927. Begin
  928. Pai386(p)^._operator := A_MOV;
  929. Pai386(p)^.Size := S_L;
  930. Pai386(p)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(p)^.op1)));
  931. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ffff);
  932. End;
  933. End;
  934. End
  935. Else
  936. If (Pai386(p)^.op1t = top_ref) Then
  937. Begin
  938. If GetNextInstruction(p, hp1) And
  939. (Pai(hp1)^.typ = ait_instruction) And
  940. (Pai386(hp1)^._operator = A_AND) And
  941. (Pai386(hp1)^.op1t = Top_Const) And
  942. (Pai386(hp1)^.op2t = Top_Reg) And
  943. (Pai386(hp1)^.op2 = Pai386(p)^.op2) Then
  944. Begin
  945. Pai386(p)^._operator := A_MOV;
  946. Case Pai386(p)^.Size Of
  947. S_BL:
  948. Begin
  949. Pai386(p)^.Size := S_L;
  950. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  951. And $ff);
  952. End;
  953. S_WL:
  954. Begin
  955. Pai386(p)^.Size := S_L;
  956. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  957. And $ffff);
  958. End;
  959. S_BW:
  960. Begin
  961. Pai386(p)^.Size := S_W;
  962. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  963. And $ff);
  964. End;
  965. End;
  966. End;
  967. End;
  968. End;
  969. A_POP:
  970. Begin
  971. if (Pai386(p)^.op1t = top_reg) And
  972. GetNextInstruction(p, hp1) And
  973. (pai(hp1)^.typ=ait_instruction) and
  974. (Pai386(hp1)^._operator=A_PUSH) and
  975. (Pai386(hp1)^.op1t = top_reg) And
  976. (Pai386(hp1)^.op1=Pai386(p)^.op1) then
  977. If (Not(cs_regalloc in aktglobalswitches)) Then
  978. Begin
  979. hp2:=pai(hp1^.next);
  980. asml^.remove(p);
  981. asml^.remove(hp1);
  982. dispose(p,done);
  983. dispose(hp1,done);
  984. p:=hp2;
  985. continue
  986. End
  987. Else
  988. Begin
  989. Pai386(p)^._operator := A_MOV;
  990. Pai386(p)^.op2 := Pai386(p)^.op1;
  991. Pai386(p)^.opxt := top_ref + top_reg shl 4;
  992. New(TmpRef);
  993. TmpRef^.segment := R_DEFAULT_SEG;
  994. TmpRef^.base := R_ESP;
  995. TmpRef^.index := R_NO;
  996. TmpRef^.scalefactor := 1;
  997. TmpRef^.symbol := nil;
  998. TmpRef^.isintvalue := false;
  999. TmpRef^.offset := 0;
  1000. Pai386(p)^.op1 := Pointer(TmpRef);
  1001. hp1 := Pai(p^.next);
  1002. AsmL^.Remove(hp1);
  1003. Dispose(hp1, Done)
  1004. End
  1005. end;
  1006. A_PUSH:
  1007. Begin
  1008. If (Pai386(p)^.size = S_W) And
  1009. (Pai386(p)^.op1t = Top_Const) And
  1010. GetNextInstruction(p, hp1) And
  1011. (Pai(hp1)^.typ = ait_instruction) And
  1012. (Pai386(hp1)^._operator = A_PUSH) And
  1013. (Pai386(hp1)^.op1t = Top_Const) And
  1014. (Pai386(hp1)^.size = S_W) Then
  1015. Begin
  1016. Pai386(p)^.Size := S_L;
  1017. Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) shl 16 + Longint(Pai386(hp1)^.op1));
  1018. AsmL^.Remove(hp1);
  1019. Dispose(hp1, Done)
  1020. End;
  1021. End;
  1022. A_SHL, A_SAL:
  1023. Begin
  1024. If (Pai386(p)^.op1t = Top_Const) And
  1025. (Pai386(p)^.op2t = Top_Reg) And
  1026. (Pai386(p)^.Size = S_L) And
  1027. (Longint(Pai386(p)^.op1) <= 3)
  1028. {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
  1029. Then
  1030. Begin
  1031. TmpBool1 := True; {should we check the next instruction?}
  1032. TmpBool2 := False; {have we found an add/sub which could be
  1033. integrated in the lea?}
  1034. New(TmpRef);
  1035. TmpRef^.segment := R_DEFAULT_SEG;
  1036. TmpRef^.base := R_NO;
  1037. TmpRef^.index := TRegister(Pai386(p)^.op2);
  1038. TmpRef^.scalefactor := 1 shl Longint(Pai386(p)^.op1);
  1039. TmpRef^.symbol := nil;
  1040. TmpRef^.isintvalue := false;
  1041. TmpRef^.offset := 0;
  1042. While TmpBool1 And
  1043. GetNextInstruction(p, hp1) And
  1044. (Pai(hp1)^.typ = ait_instruction) And
  1045. ((Pai386(hp1)^._operator = A_ADD) Or
  1046. (Pai386(hp1)^._operator = A_SUB)) And
  1047. (Pai386(hp1)^.op2t = Top_Reg) And
  1048. (Pai386(hp1)^.op2 = Pai386(p)^.op2) Do
  1049. Begin
  1050. TmpBool1 := False;
  1051. If (Pai386(hp1)^.op1t = Top_Const)
  1052. Then
  1053. Begin
  1054. TmpBool1 := True;
  1055. TmpBool2 := True;
  1056. If Pai386(hp1)^._operator = A_ADD
  1057. Then Inc(TmpRef^.offset, Longint(Pai386(hp1)^.op1))
  1058. Else Dec(TmpRef^.offset, Longint(Pai386(hp1)^.op1));
  1059. AsmL^.Remove(hp1);
  1060. Dispose(hp1, Done);
  1061. End
  1062. Else
  1063. If (Pai386(hp1)^.op1t = Top_Reg) And
  1064. (Pai386(hp1)^._operator = A_ADD) And
  1065. (TmpRef^.base = R_NO) Then
  1066. Begin
  1067. TmpBool1 := True;
  1068. TmpBool2 := True;
  1069. TmpRef^.base := TRegister(Pai386(hp1)^.op1);
  1070. AsmL^.Remove(hp1);
  1071. Dispose(hp1, Done);
  1072. End;
  1073. End;
  1074. If TmpBool2 Or
  1075. ((aktoptprocessor < ClassP6) And
  1076. (Longint(Pai386(p)^.op1) <= 3) And
  1077. Not(CS_LittleSize in aktglobalswitches))
  1078. Then
  1079. Begin
  1080. If Not(TmpBool2) And
  1081. (Longint(Pai386(p)^.op1) = 1)
  1082. Then
  1083. Begin
  1084. Dispose(TmpRef);
  1085. hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
  1086. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)))
  1087. End
  1088. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  1089. TRegister(Pai386(p)^.op2)));
  1090. hp1^.fileinfo := p^.fileinfo;
  1091. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  1092. Dispose(p, Done);
  1093. p := hp1;
  1094. End;
  1095. End
  1096. Else
  1097. If (aktoptprocessor < ClassP6) And
  1098. (Pai386(p)^.op1t = top_const) And
  1099. (Pai386(p)^.op2t = top_reg) Then
  1100. If (Longint(Pai386(p)^.op1) = 1)
  1101. Then
  1102. {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
  1103. but faster on a 486, and pairable in both U and V pipes on the Pentium
  1104. (unlike shl, which is only pairable in the U pipe)}
  1105. Begin
  1106. hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
  1107. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
  1108. hp1^.fileinfo := p^.fileinfo;
  1109. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  1110. Dispose(p, done);
  1111. p := hp1;
  1112. End
  1113. Else If (Pai386(p)^.size = S_L) and
  1114. (Longint(Pai386(p)^.op1) <= 3) Then
  1115. {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
  1116. "shl $3, %reg" to "lea (,%reg,8), %reg}
  1117. Begin
  1118. New(TmpRef);
  1119. TmpRef^.segment := R_DEFAULT_SEG;
  1120. TmpRef^.base := R_NO;
  1121. TmpRef^.index := TRegister(Pai386(p)^.op2);
  1122. TmpRef^.scalefactor := 1 shl Longint(Pai386(p)^.op1);
  1123. TmpRef^.symbol := nil;
  1124. TmpRef^.isintvalue := false;
  1125. TmpRef^.offset := 0;
  1126. hp1 := new(Pai386,op_ref_reg(A_LEA,S_L,TmpRef, TRegister(Pai386(p)^.op2)));
  1127. hp1^.fileinfo := p^.fileinfo;
  1128. InsertLLItem(AsmL,p^.previous, p^.next, hp1);
  1129. Dispose(p, done);
  1130. p := hp1;
  1131. End
  1132. End;
  1133. A_SAR, A_SHR:
  1134. {changes the code sequence
  1135. shr/sar const1, %reg
  1136. shl const2, %reg
  1137. to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
  1138. Begin
  1139. If GetNextInstruction(p, hp1) And
  1140. (pai(hp1)^.typ = ait_instruction) and
  1141. (Pai386(hp1)^._operator = A_SHL) and
  1142. (Pai386(p)^.op1t = top_const) and
  1143. (Pai386(hp1)^.op1t = top_const)
  1144. Then
  1145. If (Longint(Pai386(p)^.op1) > Longint(Pai386(hp1)^.op1)) And
  1146. (Pai386(p)^.op2t = Top_reg) And
  1147. Not(CS_LittleSize In aktglobalswitches) And
  1148. ((Pai386(p)^.Size = S_B) Or
  1149. (Pai386(p)^.Size = S_L))
  1150. Then
  1151. Begin
  1152. Dec(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
  1153. Pai386(hp1)^._operator := A_And;
  1154. Pai386(hp1)^.op1 := Pointer(1 shl Longint(Pai386(hp1)^.op1)-1);
  1155. If (Pai386(p)^.Size = S_L)
  1156. Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
  1157. Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1158. End
  1159. Else
  1160. If (Longint(Pai386(p)^.op1) < Longint(Pai386(hp1)^.op1)) And
  1161. (Pai386(p)^.op2t = Top_reg) And
  1162. Not(CS_LittleSize In aktglobalswitches) And
  1163. ((Pai386(p)^.Size = S_B) Or
  1164. (Pai386(p)^.Size = S_L))
  1165. Then
  1166. Begin
  1167. Dec(Longint(Pai386(hp1)^.op1), Longint(Pai386(p)^.op1));
  1168. Pai386(p)^._operator := A_And;
  1169. Pai386(p)^.op1 := Pointer(1 shl Longint(Pai386(p)^.op1)-1);
  1170. If (Pai386(p)^.Size = S_L)
  1171. Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
  1172. Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1173. End
  1174. Else
  1175. Begin
  1176. Pai386(p)^._operator := A_And;
  1177. Pai386(p)^.op1 := Pointer(1 shl Longint(Pai386(p)^.op1)-1);
  1178. Case Pai386(p)^.Size Of
  1179. S_B: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1180. S_W: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffff);
  1181. S_L: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor
  1182. $ffffffff);
  1183. End;
  1184. AsmL^.remove(hp1);
  1185. dispose(hp1, done);
  1186. End;
  1187. End;
  1188. A_SUB:
  1189. {change "subl $2, %esp; pushw x" to "pushl x"}
  1190. Begin
  1191. If (Pai386(p)^.op1t = top_const) And
  1192. (Longint(Pai386(p)^.op1) = 2) And
  1193. (Pai386(p)^.op2t = top_reg) And
  1194. (TRegister(Pai386(p)^.op2) = R_ESP)
  1195. Then
  1196. Begin
  1197. hp1 := Pai(p^.next);
  1198. While Assigned(hp1) And
  1199. (Pai(hp1)^.typ In [ait_instruction]+SkipInstr) And
  1200. Not((Pai(hp1)^.typ = ait_instruction) And
  1201. ((Pai386(hp1)^._operator = A_PUSH) or
  1202. ((Pai386(hp1)^._operator = A_MOV) And
  1203. (Pai386(hp1)^.op2t = top_ref) And
  1204. (TReference(Pai386(hp1)^.op2^).base = R_ESP)))) do
  1205. hp1 := Pai(hp1^.next);
  1206. If Assigned(hp1) And
  1207. (Pai(hp1)^.typ = ait_instruction) And
  1208. (Pai386(hp1)^._operator = A_PUSH) And
  1209. (Pai386(hp1)^.Size = S_W)
  1210. Then
  1211. Begin
  1212. Pai386(hp1)^.size := S_L;
  1213. If (Pai386(hp1)^.op1t = top_reg) Then
  1214. Pai386(hp1)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(hp1)^.op1)));
  1215. hp1 := Pai(p^.next);
  1216. AsmL^.Remove(p);
  1217. Dispose(p, Done);
  1218. p := hp1;
  1219. Continue
  1220. End
  1221. Else
  1222. If GetLastInstruction(p, hp1) And
  1223. (Pai(hp1)^.typ = ait_instruction) And
  1224. (Pai386(hp1)^._operator = A_SUB) And
  1225. (Pai386(hp1)^.op1t = top_const) And
  1226. (Pai386(hp1)^.op2t = top_reg) And
  1227. (TRegister(Pai386(hp1)^.Op2) = R_ESP)
  1228. Then
  1229. Begin
  1230. Inc(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
  1231. AsmL^.Remove(hp1);
  1232. Dispose(hp1, Done);
  1233. End;
  1234. End;
  1235. End;
  1236. A_TEST, A_OR:
  1237. {removes the line marked with (x) from the sequence
  1238. And/or/xor/add/sub/... $x, %y
  1239. test/or %y, %y (x)
  1240. j(n)z _Label
  1241. as the first instruction already adjusts the ZF}
  1242. Begin
  1243. If (Pai386(p)^.op1 = Pai386(p)^.op2) And
  1244. GetLastInstruction(p, hp1) And
  1245. (pai(hp1)^.typ = ait_instruction) Then
  1246. Case Pai386(hp1)^._operator Of
  1247. A_ADD, A_SUB, A_OR, A_XOR, A_AND, A_SHL, A_SHR:
  1248. Begin
  1249. If (Pai386(hp1)^.op2 = Pai386(p)^.op1) Then
  1250. Begin
  1251. hp1 := pai(p^.next);
  1252. asml^.remove(p);
  1253. dispose(p, done);
  1254. p := pai(hp1);
  1255. continue
  1256. End;
  1257. End;
  1258. A_DEC, A_INC, A_NEG:
  1259. Begin
  1260. If (Pai386(hp1)^.op1 = Pai386(p)^.op1) Then
  1261. Begin
  1262. hp1 := pai(p^.next);
  1263. asml^.remove(p);
  1264. dispose(p, done);
  1265. p := pai(hp1);
  1266. continue
  1267. End;
  1268. End
  1269. End;
  1270. End;
  1271. End;
  1272. End;
  1273. { ait_label:
  1274. Begin
  1275. If Not(Pai_Label(p)^.l^.is_used)
  1276. Then
  1277. Begin
  1278. hp1 := Pai(p^.next);
  1279. AsmL^.Remove(p);
  1280. Dispose(p, Done);
  1281. p := hp1;
  1282. Continue
  1283. End;
  1284. End;}
  1285. End;
  1286. p:=pai(p^.next);
  1287. end;
  1288. end;
  1289. Procedure PeepHoleOptPass2(AsmL: PAasmOutput);
  1290. var
  1291. p,hp1 : pai;
  1292. Begin
  1293. P := Pai(AsmL^.First);
  1294. While Assigned(p) Do
  1295. Begin
  1296. Case P^.Typ Of
  1297. Ait_Instruction:
  1298. Begin
  1299. Case Pai386(p)^._operator Of
  1300. A_MOVZX:
  1301. Begin
  1302. If (Pai386(p)^.op2t = top_reg) Then
  1303. If (Pai386(p)^.op1t = top_reg)
  1304. Then
  1305. Case Pai386(p)^.size of
  1306. S_BL:
  1307. Begin
  1308. If IsGP32Reg(TRegister(Pai386(p)^.op2)) And
  1309. Not(CS_LittleSize in aktglobalswitches) And
  1310. (aktoptprocessor = ClassP5)
  1311. Then
  1312. {Change "movzbl %reg1, %reg2" to
  1313. "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
  1314. PentiumMMX}
  1315. Begin
  1316. hp1 := New(Pai386, op_reg_reg(A_XOR, S_L,
  1317. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
  1318. hp1^.fileinfo := p^.fileinfo;
  1319. InsertLLItem(AsmL,p^.previous, p, hp1);
  1320. Pai386(p)^._operator := A_MOV;
  1321. Pai386(p)^.size := S_B;
  1322. Pai386(p)^.op2 :=
  1323. Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
  1324. { Jonas
  1325. InsertLLItem(AsmL,p, p^.next, hp2);
  1326. I think you forgot to delete this line PM }
  1327. End;
  1328. End;
  1329. End
  1330. Else
  1331. If (Pai386(p)^.op1t = top_ref) And
  1332. (PReference(Pai386(p)^.op1)^.base <> TRegister(Pai386(p)^.op2)) And
  1333. (PReference(Pai386(p)^.op1)^.index <> TRegister(Pai386(p)^.op2)) And
  1334. Not(CS_LittleSize in aktglobalswitches) And
  1335. IsGP32Reg(TRegister(Pai386(p)^.op2)) And
  1336. (aktoptprocessor = ClassP5) And
  1337. (Pai386(p)^.Size = S_BL)
  1338. Then
  1339. {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
  1340. Pentium and PentiumMMX}
  1341. Begin
  1342. hp1 := New(Pai386,op_reg_reg(A_XOR, S_L, TRegister(Pai386(p)^.op2),
  1343. TRegister(Pai386(p)^.op2)));
  1344. hp1^.fileinfo := p^.fileinfo;
  1345. Pai386(p)^._operator := A_MOV;
  1346. Pai386(p)^.size := S_B;
  1347. Pai386(p)^.op2 := Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
  1348. InsertLLItem(AsmL,p^.previous, p, hp1);
  1349. End;
  1350. End;
  1351. End;
  1352. End;
  1353. End;
  1354. p := Pai(p^.next)
  1355. End;
  1356. End;
  1357. End.
  1358. {
  1359. $Log$
  1360. Revision 1.14 1998-09-20 17:11:51 jonas
  1361. * released REGALLOC
  1362. Revision 1.13 1998/09/16 18:00:00 jonas
  1363. * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc
  1364. Revision 1.12 1998/09/15 14:05:22 jonas
  1365. * fixed optimizer incompatibilities with freelabel code in psub
  1366. Revision 1.11 1998/08/28 10:57:02 peter
  1367. * removed warnings
  1368. Revision 1.10 1998/08/27 15:17:50 florian
  1369. * reinstated Jonas' bugfix
  1370. Revision 1.9 1998/08/25 16:58:59 pierre
  1371. * removed a line that add no sense and
  1372. introduce garbage in the asmlist
  1373. (uninitialized data !)
  1374. Revision 1.7 1998/08/19 16:07:53 jonas
  1375. * changed optimizer switches + cleanup of DestroyRefs in daopt386.pas
  1376. Revision 1.6 1998/08/10 14:50:14 peter
  1377. + localswitches, moduleswitches, globalswitches splitting
  1378. Revision 1.5 1998/08/06 19:40:28 jonas
  1379. * removed $ before and after Log in comment
  1380. Revision 1.4 1998/08/05 16:27:17 jonas
  1381. * fstp/fld bugfix (fstt does not exist)
  1382. Revision 1.3 1998/08/05 16:00:15 florian
  1383. * some fixes for ansi strings
  1384. * log to Log changed
  1385. }