popt386.pas 81 KB

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