popt386.pas 81 KB

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