popt386.pas 74 KB

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