aopt386.pas 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl and Jonas Maebe
  4. This unit does optimizations on the assembler code for i386+
  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 aopt386;
  19. interface
  20. uses aasm;
  21. { does simple optimizations like jumps and remove pop/pushes }
  22. procedure peepholeopt(asml : paasmoutput);
  23. implementation
  24. uses
  25. cobjects,globals,symtable,strings,verbose,hcodegen
  26. {$ifdef i386}
  27. ,i386
  28. ,cgi386
  29. {$else}
  30. {$endif}
  31. ;
  32. {ait_* types which don't result in executable code or which don't
  33. influence the way the program runs/behaves}
  34. Const SkipInstr = [ait_comment,ait_stabs, ait_stabn, ait_stab_function_name
  35. {$ifdef regalloc}
  36. ,ait_regalloc, ait_regdealloc
  37. {$endif regalloc}
  38. ];
  39. Type
  40. {$ifdef tp}
  41. TLabelTable = Array[0..10000] Of Pai;
  42. {$else}
  43. TLabelTable = Array[0..2500000] Of Pai;
  44. {$endif}
  45. PLabelTable = ^TLabelTable;
  46. twowords=record
  47. word1,word2:word;
  48. end;
  49. Var LoLab, HiLab, LabDif: Longint;
  50. LTable: PLabelTable;
  51. Function RefsEqual(const r1,r2 : treference) : boolean;
  52. begin
  53. if r1.isintvalue
  54. then RefsEqual:=r2.isintvalue and (r1.offset=r2.offset)
  55. else if (r1.offset=r2.offset) and (r1.base=r2.base) and
  56. (r1.index=r2.index) and (r1.segment=r2.segment) and
  57. (r1.scalefactor=r2.scalefactor)
  58. then
  59. begin
  60. if assigned(r1.symbol)
  61. then RefsEqual:=assigned(r2.symbol) and (r1.symbol^=r2.symbol^)
  62. else RefsEqual:=not(assigned(r2.symbol));
  63. end
  64. Else RefsEqual := False;
  65. end;
  66. Function Reg32(Reg: TRegister): TRegister;
  67. {Returns the 32 bit component of Reg if it exists, otherwise Reg is returned}
  68. Begin
  69. Reg32 := Reg;
  70. If (Reg >= R_AX)
  71. Then
  72. If (Reg <= R_DI)
  73. Then Reg32 := Reg16ToReg32(Reg)
  74. Else
  75. If (Reg <= R_BL)
  76. Then Reg32 := Reg8toReg32(Reg);
  77. End;
  78. Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
  79. Begin {checks whether Ref contains a reference to Reg}
  80. Reg := Reg32(Reg);
  81. RegInRef := (Ref.Base = Reg) Or (Ref.Index = Reg)
  82. End;
  83. Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
  84. {checks if Reg is used by the instruction p1}
  85. Var TmpResult: Boolean;
  86. Begin
  87. TmpResult := False;
  88. If (Pai(p1)^.typ = ait_instruction) Then
  89. Begin
  90. Case Pai386(p1)^.op1t Of
  91. Top_Reg: TmpResult := Reg = TRegister(Pai386(p1)^.op1);
  92. Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op1^))
  93. End;
  94. If Not(TmpResult) Then
  95. Case Pai386(p1)^.op2t Of
  96. Top_Reg:
  97. if Pai386(p1)^.op3t<>Top_reg
  98. then TmpResult := Reg = TRegister(Pai386(p1)^.op2)
  99. else TmpResult := longint(Reg) = twowords(Pai386(p1)^.op2).word1;
  100. Top_Ref: TmpResult := RegInRef(Reg, TReference(Pai386(p1)^.op2^))
  101. End;
  102. If Not(TmpResult) Then
  103. Case Pai386(p1)^.op3t Of
  104. Top_Reg: TmpResult := longint(Reg) =twowords(Pai386(p1)^.op2).word2;
  105. Top_none:;
  106. else
  107. internalerror($Da);
  108. End
  109. End;
  110. RegInInstruction := TmpResult
  111. End;
  112. {$i aopt386.inc}
  113. {aopt386.inc contains the reloading optimizer}
  114. Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
  115. {skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the
  116. next pai object in Next. Returns false if there isn't any}
  117. Begin
  118. GetNextInstruction := False;
  119. Current := Pai(Current^.Next);
  120. While Assigned(Current) And
  121. (Pai(Current)^.typ In SkipInstr) Do
  122. Current := Pai(Current^.Next);
  123. If Assigned(Current)
  124. Then
  125. Begin
  126. Next := Current;
  127. GetNextInstruction := True;
  128. End;
  129. End;
  130. Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
  131. {skips ait_regalloc, ait_regdealloc and ait_stab* objects and puts the
  132. last pai object in Last. Returns false if there isn't any}
  133. Begin
  134. GetLastInstruction := False;
  135. Current := Pai(Current^.Last);
  136. While Assigned(Current) And
  137. (Pai(Current)^.typ In SkipInstr) Do
  138. Current := Pai(Current^.Last);
  139. If Assigned(Current)
  140. Then
  141. Begin
  142. Last := Current;
  143. GetLastInstruction := True;
  144. End;
  145. End;
  146. Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
  147. {searches for the specified label starting from hp as long as the
  148. encountered instructions are labels, to be able to optimize constructs like
  149. jne l2 jmp l2
  150. jmp l3 and l1:
  151. l1: l2:
  152. l2:}
  153. Var TempP: Pai;
  154. Begin
  155. TempP := hp;
  156. While Assigned(TempP) and
  157. (pai(TempP)^.typ In SkipInstr + [ait_label]) Do
  158. If (pai_label(TempP)^.l <> L)
  159. Then TempP := Pai(TempP^.next)
  160. Else
  161. Begin
  162. hp := TempP;
  163. FindLabel := True;
  164. exit
  165. End;
  166. FindLabel := False
  167. End;
  168. Function PowerOf2(L: Longint): Longint;
  169. Var Counter, TempVal: Longint;
  170. Begin
  171. TempVal := 1;
  172. For Counter := 1 to L Do
  173. TempVal := TempVal * 2;
  174. PowerOf2 := TempVal;
  175. End;
  176. Procedure DoOptimize(asml : paasmoutput);
  177. var
  178. p,hp1,hp2 : pai;
  179. TmpBool1, TmpBool2: Boolean;
  180. TmpRef: PReference;
  181. RegsUsed: Set of TRegister;
  182. { inserts new_one between prev and foll }
  183. Procedure InsertLLItem(prev, foll, new_one: PLinkedList_Item);
  184. Begin
  185. If Assigned(prev)
  186. Then
  187. If Assigned(foll)
  188. Then
  189. Begin
  190. If Assigned(new_one) Then
  191. Begin
  192. new_one^.last := prev;
  193. new_one^.next := foll;
  194. prev^.next := new_one;
  195. foll^.last := new_one;
  196. End;
  197. End
  198. Else AsmL^.Concat(new_one)
  199. Else If Assigned(Foll) Then AsmL^.Insert(new_one)
  200. End;
  201. Procedure GetFinalDestination(hp: pai_labeled);
  202. {traces sucessive jumps to their final destination and sets it, e.g.
  203. je l1 je l3
  204. <code> <code>
  205. l1: becomes l1:
  206. je l2 je l3
  207. <code> <code>
  208. l2: l2:
  209. jmp l3 jmp l3}
  210. Var p1: pai;
  211. Function SkipLabels(hp: Pai): Pai;
  212. {skips all labels and returns the next "real" instruction; it is
  213. assumed that hp is of the type ait_label}
  214. Begin
  215. While assigned(hp^.next) and
  216. (pai(hp^.next)^.typ In SkipInstr + [ait_label]) Do
  217. hp := pai(hp^.next);
  218. If assigned(hp^.next)
  219. Then SkipLabels := pai(hp^.next)
  220. Else SkipLabels := hp;
  221. End;
  222. Begin
  223. If (hp^.lab^.nb >= LoLab) and
  224. (hp^.lab^.nb <= HiLab) and {range check, necessary?}
  225. (Pointer(LTable^[hp^.lab^.nb-LoLab]) <> Pointer(0)) Then
  226. Begin
  227. p1 := LTable^[hp^.lab^.nb-LoLab]; {the jump's destination}
  228. p1 := SkipLabels(p1);
  229. If (pai(p1)^.typ = ait_labeled_instruction) and
  230. ((pai_labeled(p1)^._operator = A_JMP) or
  231. (pai_labeled(p1)^._operator = hp^._operator))
  232. Then
  233. Begin
  234. GetFinalDestination(pai_labeled(p1));
  235. Dec(hp^.lab^.refcount);
  236. If (hp^.lab^.refcount = 0) Then
  237. hp^.lab^.is_used := False;
  238. hp^.lab := pai_labeled(p1)^.lab;
  239. Inc(hp^.lab^.refcount);
  240. End
  241. End
  242. End;
  243. Function IsGP32Reg(Reg: TRegister): Boolean;
  244. {Checks if the register is a 32 bit general purpose register}
  245. Begin
  246. If (Reg >= R_EAX) and (Reg <= R_EBX)
  247. Then IsGP32Reg := True
  248. Else IsGP32reg := False
  249. End;
  250. begin
  251. p:=pai(asml^.first);
  252. RegsUsed := [];
  253. while assigned(p) do
  254. begin
  255. Case p^.typ Of
  256. ait_labeled_instruction:
  257. begin
  258. {the following if-block removes all code between a jmp and the next label,
  259. because it can never be executed}
  260. If (pai_labeled(p)^._operator = A_JMP) Then
  261. Begin
  262. hp1 := pai(p^.next);
  263. While Assigned(hp1) and (hp1^.typ <> ait_label) Do
  264. Begin
  265. AsmL^.Remove(hp1);
  266. Dispose(hp1, done);
  267. hp1 := pai(p^.next);
  268. End;
  269. End;
  270. if GetNextInstruction(p, hp1) then
  271. begin
  272. { hp2 := pai(p^.next^.next);}
  273. if (pai(hp1)^.typ=ait_labeled_instruction) and
  274. (pai_labeled(hp1)^._operator=A_JMP) and
  275. GetNextInstruction(hp1, hp2) And
  276. FindLabel(pai_labeled(p)^.lab, hp2)
  277. then
  278. begin
  279. case pai_labeled(p)^._operator of
  280. A_JE : pai_labeled(p)^._operator:=A_JNE;
  281. A_JNE : pai_labeled(p)^._operator:=A_JE;
  282. A_JL : pai_labeled(p)^._operator:=A_JGE;
  283. A_JG : pai_labeled(p)^._operator:=A_JLE;
  284. A_JLE : pai_labeled(p)^._operator:=A_JG;
  285. A_JGE : pai_labeled(p)^._operator:=A_JL;
  286. A_JNZ : pai_labeled(p)^._operator:=A_JZ;
  287. A_JNO : pai_labeled(p)^._operator:=A_JO;
  288. A_JZ : pai_labeled(p)^._operator:=A_JNZ;
  289. A_JS : pai_labeled(p)^._operator:=A_JNS;
  290. A_JNS : pai_labeled(p)^._operator:=A_JS;
  291. A_JO : pai_labeled(p)^._operator:=A_JNO;
  292. A_JC : pai_labeled(p)^._operator:=A_JNC;
  293. A_JNC : pai_labeled(p)^._operator:=A_JC;
  294. A_JA : pai_labeled(p)^._operator:=A_JBE;
  295. A_JAE : pai_labeled(p)^._operator:=A_JB;
  296. A_JB : pai_labeled(p)^._operator:=A_JAE;
  297. A_JBE : pai_labeled(p)^._operator:=A_JA;
  298. else
  299. begin
  300. If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
  301. p:=pai(p^.next);
  302. continue;
  303. end;
  304. end;
  305. Dec(pai_label(hp2)^.l^.refcount);
  306. If (pai_label(hp2)^.l^.refcount = 0) Then
  307. Begin
  308. pai_label(hp2)^.l^.is_used := False;
  309. AsmL^.remove(hp2);
  310. Dispose(hp2, done);
  311. End;
  312. pai_labeled(p)^.lab:=pai_labeled(hp1)^.lab;
  313. Inc(pai_labeled(p)^.lab^.refcount);
  314. { hp1:=pai(p^.next);}
  315. asml^.remove(hp1);
  316. dispose(hp1,done);
  317. If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
  318. end
  319. else
  320. Begin
  321. { hp2:=pai(p^.next);}
  322. if FindLabel(pai_labeled(p)^.lab, hp1) then
  323. begin
  324. hp2:=pai(hp1^.next);
  325. asml^.remove(p);
  326. dispose(p,done);
  327. If Not(pai_label(hp1)^.l^.is_used) Then
  328. Begin
  329. AsmL^.remove(hp1);
  330. Dispose(hp1, done);
  331. End;
  332. p:=hp2;
  333. continue;
  334. end;
  335. If (LabDif <> 0) Then GetFinalDestination(pai_labeled(p));
  336. end;
  337. end
  338. end;
  339. ait_instruction:
  340. Begin
  341. If (Pai386(p)^.op1t = top_ref) Then
  342. With TReference(Pai386(p)^.op1^) Do
  343. Begin
  344. If (base = R_NO) And
  345. (scalefactor = 1)
  346. Then
  347. Begin
  348. base := index;
  349. index := r_no
  350. End
  351. End;
  352. If (Pai386(p)^.op2t = top_ref) Then
  353. With TReference(Pai386(p)^.op2^) Do
  354. Begin
  355. If (base = R_NO) And
  356. (scalefactor = 1)
  357. Then
  358. Begin
  359. base := index;
  360. index := r_no
  361. End
  362. End;
  363. Case Pai386(p)^._operator Of
  364. A_AND:
  365. Begin
  366. If (Pai386(p)^.op1t = top_const) And
  367. (Pai386(p)^.op2t = top_reg) And
  368. { Assigned(p^.next) And}
  369. GetNextInstruction(p, hp1) And
  370. (Pai(hp1)^.typ = ait_instruction) And
  371. (Pai386(hp1)^._operator = A_AND) And
  372. (Pai386(hp1)^.op1t = top_const) And
  373. (Pai386(hp1)^.op2t = top_reg) And
  374. (Pai386(hp1)^.op2 = Pai386(hp1)^.op2)
  375. Then
  376. {change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
  377. Begin
  378. Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) And Longint(Pai386(hp1)^.op1));
  379. { hp1 := Pai(p^.next);}
  380. AsmL^.Remove(hp1);
  381. Dispose(hp1, Done)
  382. End;
  383. {
  384. Else
  385. If (Pai386(p)^.op2t = top_reg) And
  386. Assigned(p^.next) And
  387. (Pai(p^.next)^.typ = ait_labeled_instruction)
  388. Then Pai386(p)^._operator := A_TEST;
  389. change "and x, reg; jxx" to "test x, reg
  390. }
  391. End;
  392. A_CMP:
  393. Begin
  394. If (Pai386(p)^.op1t = top_const) And
  395. (Pai386(p)^.op2t = top_reg) And
  396. (Pai386(p)^.op1 = Pointer(0)) Then
  397. {change "cmp $0, %reg" to "test %reg, %reg"}
  398. Begin
  399. Pai386(p)^._operator := A_TEST;
  400. Pai386(p)^.opxt := Top_reg+Top_reg shl 4;
  401. Pai386(p)^.op1 := Pai386(p)^.op2;
  402. End;
  403. End;
  404. A_FSTP:
  405. Begin
  406. If (Pai386(p)^.op1t = top_ref) And
  407. { Assigned(p^.next) And}
  408. GetNextInstruction(p, hp1) And
  409. (Pai(hp1)^.typ = ait_instruction) And
  410. (Pai386(hp1)^._operator = A_FLD) And
  411. (Pai386(hp1)^.op1t = top_ref) And
  412. (Pai386(p)^.Size = Pai386(p)^.Size) And
  413. RefsEqual(TReference(Pai386(p)^.op1^), TReference(Pai386(hp1)^.op1^))
  414. Then
  415. Begin
  416. { hp1 := pai(p^.next^.next);}
  417. If {Assigned(hp1) And}
  418. GetNextInstruction(hp1, hp2) And
  419. (hp2^.typ = ait_instruction) And
  420. ((Pai386(hp2)^._operator = A_LEAVE) Or
  421. (Pai386(hp2)^._operator = A_RET)) And
  422. (TReference(Pai386(p)^.op1^).Base = ProcInfo.FramePointer) And
  423. (TReference(Pai386(p)^.op1^).Offset >= ProcInfo.RetOffset) And
  424. (TReference(Pai386(p)^.op1^).Index = R_NO)
  425. Then
  426. Begin
  427. { hp2 := Pai(p^.next);}
  428. AsmL^.Remove(p);
  429. AsmL^.Remove(hp1);
  430. Dispose(p, Done);
  431. Dispose(hp1, Done);
  432. p := hp2;
  433. Continue
  434. End
  435. Else
  436. Begin
  437. Pai386(p)^._operator := A_FST;
  438. { hp1 := Pai(p^.next);}
  439. AsmL^.Remove(hp1);
  440. Dispose(hp1, done)
  441. End
  442. End;
  443. End;
  444. A_IMUL:
  445. {changes certain "imul const, %reg"'s to lea sequences}
  446. Begin
  447. If (Pai386(p)^.op1t = Top_Const) And
  448. (Pai386(p)^.op2t = Top_Reg) And
  449. (Pai386(p)^.Size = S_L) And
  450. ((Pai386(p)^.op3t = Top_Reg) or
  451. (Pai386(p)^.op3t = Top_None)) And
  452. (Opt_Processors < PentiumPro) And
  453. (Longint(Pai386(p)^.op1) <= 12) And
  454. Not(CS_LittleSize in AktSwitches) And
  455. (Not(GetNextInstruction(p, hp1)) Or
  456. {GetNextInstruction(p, hp1) And}
  457. Not((Pai(hp1)^.typ = ait_labeled_instruction) And
  458. ((pai_labeled(hp1)^._operator = A_JO) or
  459. (pai_labeled(hp1)^._operator = A_JNO))))
  460. Then
  461. Begin
  462. New(TmpRef);
  463. TmpRef^.segment := R_DEFAULT_SEG;
  464. TmpRef^.symbol := nil;
  465. TmpRef^.isintvalue := false;
  466. TmpRef^.offset := 0;
  467. Case Longint(Pai386(p)^.op1) Of
  468. 3: Begin
  469. {imul 3, reg1, reg2 to
  470. lea (reg1,reg1,2), reg2
  471. imul 3, reg1 to
  472. lea (reg1,reg1,2), reg1}
  473. TmpRef^.base := TRegister(Pai386(p)^.op2);
  474. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  475. TmpRef^.ScaleFactor := 2;
  476. If (Pai386(p)^.op3t = Top_None)
  477. Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
  478. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  479. TRegister(twowords(Pai386(p)^.op2).word2)));
  480. hp1^.line := p^.line;
  481. InsertLLItem(p^.last, p^.next, hp1);
  482. Dispose(p, Done);
  483. p := hp1;
  484. End;
  485. 5: Begin
  486. {imul 5, reg1, reg2 to
  487. lea (reg1,reg1,4), reg2
  488. imul 5, reg1 to
  489. lea (reg1,reg1,4), reg1}
  490. TmpRef^.base := TRegister(Pai386(p)^.op2);
  491. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  492. TmpRef^.ScaleFactor := 4;
  493. If (Pai386(p)^.op3t = Top_None)
  494. Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
  495. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  496. TRegister(twowords(Pai386(p)^.op2).word2)));
  497. hp1^.line:= p^.line;
  498. InsertLLItem(p^.last, p^.next, hp1);
  499. Dispose(p, Done);
  500. p := hp1;
  501. End;
  502. 6: Begin
  503. {imul 6, reg1, reg2 to
  504. lea (,reg1,2), reg2
  505. lea (reg2,reg1,4), reg2
  506. imul 6, reg1 to
  507. lea (reg1,reg1,2), reg1
  508. add reg1, reg1}
  509. If (Opt_Processors <= i486)
  510. Then
  511. Begin
  512. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  513. If (Pai386(p)^.op3t = Top_Reg)
  514. Then
  515. Begin
  516. TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
  517. TmpRef^.ScaleFactor := 4;
  518. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  519. TRegister(twowords(Pai386(p)^.op2).word2)));
  520. End
  521. Else
  522. Begin
  523. Dispose(TmpRef);
  524. hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
  525. TRegister(Pai386(p)^.op2),TRegister(Pai386(p)^.op2)));
  526. End;
  527. hp1^.line := p^.line;
  528. InsertLLItem(p, p^.next, hp1);
  529. New(TmpRef);
  530. TmpRef^.segment := R_DEFAULT_SEG;
  531. TmpRef^.symbol := nil;
  532. TmpRef^.isintvalue := false;
  533. TmpRef^.offset := 0;
  534. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  535. TmpRef^.ScaleFactor := 2;
  536. If (Pai386(p)^.op3t = Top_Reg)
  537. Then
  538. Begin
  539. TmpRef^.base := R_NO;
  540. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  541. TRegister(twowords(Pai386(p)^.op2).word2)));
  542. End
  543. Else
  544. Begin
  545. TmpRef^.base := TRegister(Pai386(p)^.op2);
  546. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)));
  547. End;
  548. hp1^.line := p^.line;
  549. InsertLLItem(p^.last, p^.next, hp1);
  550. Dispose(p, Done);
  551. p := Pai(hp1^.next);
  552. End
  553. Else Dispose(TmpRef);
  554. End;
  555. 9: Begin
  556. {imul 9, reg1, reg2 to
  557. lea (reg1,reg1,8), reg2
  558. imul 9, reg1 to
  559. lea (reg1,reg1,8), reg1}
  560. TmpRef^.base := TRegister(Pai386(p)^.op2);
  561. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  562. TmpRef^.ScaleFactor := 8;
  563. If (Pai386(p)^.op3t = Top_None)
  564. Then hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef, TRegister(Pai386(p)^.op2)))
  565. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  566. TRegister(twowords(Pai386(p)^.op2).word2)));
  567. hp1^.line := p^.line;
  568. InsertLLItem(p^.last, p^.next, hp1);
  569. Dispose(p, Done);
  570. p := hp1;
  571. End;
  572. 10: Begin
  573. {imul 10, reg1, reg2 to
  574. lea (reg1,reg1,4), reg2
  575. add reg2, reg2
  576. imul 10, reg1 to
  577. lea (reg1,reg1,4), reg1
  578. add reg1, reg1}
  579. If (Opt_Processors <= i486) Then
  580. Begin
  581. If (Pai386(p)^.op3t = Top_Reg)
  582. Then
  583. hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
  584. Tregister(twowords(Pai386(p)^.op2).word2),
  585. Tregister(twowords(Pai386(p)^.op2).word2)))
  586. Else hp1 := New(Pai386, op_reg_reg(A_ADD, S_L,
  587. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
  588. hp1^.line := p^.line;
  589. InsertLLItem(p, p^.next, hp1);
  590. TmpRef^.base := TRegister(Pai386(p)^.op2);
  591. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  592. TmpRef^.ScaleFactor := 4;
  593. If (Pai386(p)^.op3t = Top_Reg)
  594. Then
  595. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  596. TRegister(twowords(Pai386(p)^.op2).word2)))
  597. Else
  598. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  599. TRegister(Pai386(p)^.op2)));
  600. hp1^.line := p^.line;
  601. InsertLLItem(p^.last, p^.next, hp1);
  602. Dispose(p, Done);
  603. p := Pai(hp1^.next);
  604. End
  605. Else Dispose(TmpRef);
  606. End;
  607. 12: Begin
  608. {imul 12, reg1, reg2 to
  609. lea (,reg1,4), reg2
  610. lea (,reg1,8) reg2
  611. imul 12, reg1 to
  612. lea (reg1,reg1,2), reg1
  613. lea (,reg1,4), reg1}
  614. If (Opt_Processors <= i486)
  615. Then
  616. Begin
  617. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  618. If (Pai386(p)^.op3t = Top_Reg)
  619. Then
  620. Begin
  621. TmpRef^.base := TRegister(twowords(Pai386(p)^.op2).word2);
  622. TmpRef^.ScaleFactor := 8;
  623. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  624. TRegister(twowords(Pai386(p)^.op2).word2)));
  625. End
  626. Else
  627. Begin
  628. TmpRef^.base := R_NO;
  629. TmpRef^.ScaleFactor := 4;
  630. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  631. TRegister(Pai386(p)^.op2)));
  632. End;
  633. hp1^.line := p^.line;
  634. InsertLLItem(p, p^.next, hp1);
  635. New(TmpRef);
  636. TmpRef^.segment := R_DEFAULT_SEG;
  637. TmpRef^.symbol := nil;
  638. TmpRef^.isintvalue := false;
  639. TmpRef^.offset := 0;
  640. TmpRef^.Index := TRegister(Pai386(p)^.op2);
  641. If (Pai386(p)^.op3t = Top_Reg)
  642. Then
  643. Begin
  644. TmpRef^.base := R_NO;
  645. TmpRef^.ScaleFactor := 4;
  646. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  647. TRegister(twowords(Pai386(p)^.op2).word2)));
  648. End
  649. Else
  650. Begin
  651. TmpRef^.base := TRegister(Pai386(p)^.op2);
  652. TmpRef^.ScaleFactor := 2;
  653. hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  654. TRegister(Pai386(p)^.op2)));
  655. End;
  656. hp1^.line := p^.line;
  657. InsertLLItem(p^.last, p^.next, hp1);
  658. Dispose(p, Done);
  659. p := Pai(hp1^.next);
  660. End
  661. Else Dispose(TmpRef);
  662. End
  663. Else Dispose(TmpRef);
  664. End;
  665. End;
  666. End;
  667. A_LEA:
  668. Begin
  669. {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
  670. If (PReference(Pai386(p)^.op1)^.Base >= R_EAX) And
  671. (PReference(Pai386(p)^.op1)^.Base <= R_EDI) And
  672. (PReference(Pai386(p)^.op1)^.Index = R_NO) And
  673. (PReference(Pai386(p)^.op1)^.Offset = 0) And
  674. (Not(Assigned(PReference(Pai386(p)^.op1)^.Symbol))) Then
  675. Begin
  676. hp1 := New(Pai386, op_reg_reg(A_MOV, S_L,PReference(Pai386(p)^.op1)^.Base,
  677. TRegister(Pai386(p)^.op2)));
  678. hp1^.line := p^.line;
  679. InsertLLItem(p^.last,p^.next, hp1);
  680. Dispose(p, Done);
  681. p := hp1;
  682. Continue;
  683. End;
  684. End;
  685. A_MOV:
  686. Begin
  687. If (Pai386(p)^.op2t = top_reg) And
  688. (TRegister(Pai386(p)^.op2) In [R_EAX, R_EBX, R_EDX, R_EDI]) And
  689. { Assigned(p^.next) And}
  690. GetNextInstruction(p, hp1) And
  691. (Pai(hp1)^.typ = ait_instruction) And
  692. (Pai386(hp1)^._operator = A_MOV) And
  693. (Pai386(hp1)^.op1t = top_reg) And
  694. (Pai386(hp1)^.op1 = Pai386(p)^.op2)
  695. Then
  696. {we have "mov x, %treg; mov %treg, y}
  697. If (Pai386(hp1)^.op2t <> top_reg) Or
  698. (GetNextInstruction(hp1, hp2) And
  699. RegInInstruction(TRegister(Pai386(hp1)^.op2), hp2))
  700. Then
  701. {we've got "mov x, %treg; mov %treg, y; XXX y" (ie. y is used in
  702. the third instruction)}
  703. Case Pai386(p)^.op1t Of
  704. top_reg:
  705. {change "mov %reg, %treg; mov %treg, y"
  706. to "mov %reg, y"}
  707. Begin
  708. Pai386(hp1)^.op1 := Pai386(p)^.op1;
  709. { hp1 := Pai(p^.next);}
  710. AsmL^.Remove(p);
  711. Dispose(p, Done);
  712. p := hp1;
  713. continue;
  714. End;
  715. top_ref:
  716. If (Pai386(hp1)^.op2t = top_reg)
  717. Then
  718. {change "mov mem, %treg; mov %treg, %reg"
  719. to "mov mem, %reg"}
  720. Begin
  721. Pai386(p)^.op2 := Pai386(hp1)^.op2;
  722. { hp1 := Pai(p^.next);}
  723. AsmL^.Remove(hp1);
  724. Dispose(hp1, Done);
  725. continue;
  726. End;
  727. End
  728. Else
  729. {remove an instruction which never makes sense: we've got
  730. "mov mem, %reg1; mov %reg1, %edi" and then EDI isn't used anymore!}
  731. Begin
  732. If (TRegister(Pai386(hp1)^.op2) = R_EDI) And
  733. Not({Assigned(p^.next^.next) And}
  734. GetNextInstruction(hp1, hp2) And
  735. (Pai(hp2)^.typ = ait_instruction) And
  736. (Pai386(hp2)^.op2t = top_reg) And
  737. (Pai386(hp2)^.op2 = Pointer(R_ESI))) Then
  738. Begin
  739. { hp1 := pai(p^.next);}
  740. AsmL^.Remove(hp1);
  741. Dispose(hp1, Done);
  742. Continue;
  743. End
  744. End
  745. Else
  746. {Change "mov %reg1, %reg2; xxx %reg2, ???" to
  747. "mov %reg1, %reg2; xxx %reg1, ???" to
  748. avoid a write/read penalty}
  749. If (Pai386(p)^.op1t = top_reg) And
  750. (Pai386(p)^.op2t = top_reg) And
  751. { Assigned(p^.next) And}
  752. GetNextInstruction(p,hp1) And
  753. (Pai(hp1)^.typ = ait_instruction) And
  754. (Pai386(hp1)^.op1t = top_reg) And
  755. (Pai386(hp1)^.op1 = Pai386(p)^.op2)
  756. Then
  757. {we have "mov %reg1, %reg2; XXX %reg2, ???"}
  758. Begin
  759. If ((Pai386(hp1)^._operator = A_OR) Or
  760. (Pai386(hp1)^._operator = A_TEST)) And
  761. (Pai386(hp1)^.op2t = top_reg) And
  762. (Pai386(hp1)^.op1 = Pai386(hp1)^.op2)
  763. Then
  764. {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
  765. Begin
  766. If {Assigned(p^.next^.next) And}
  767. GetNextInstruction(hp1, hp2) And
  768. (Pai(hp2)^.typ = ait_labeled_instruction) And
  769. (TRegister(Pai386(p)^.op2) <> R_ESI)
  770. Then
  771. {change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
  772. "test %reg1, %reg1; jxx"}
  773. Begin
  774. { hp1 := pai(p^.next);}
  775. Pai386(hp1)^.op1 := Pai386(p)^.op1;
  776. Pai386(hp1)^.op2 := Pai386(p)^.op1;
  777. AsmL^.Remove(p);
  778. Dispose(p, done);
  779. p := hp1;
  780. continue
  781. End
  782. Else
  783. {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
  784. "mov %reg1, %reg2; test/or %reg1, %reg1"}
  785. Begin
  786. Pai386(hp1)^.op1 := Pai386(p)^.op1;
  787. Pai386(hp1)^.op2 := Pai386(p)^.op1;
  788. End;
  789. End
  790. Else
  791. { If (Pai386(p^.next)^._operator
  792. In [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
  793. {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
  794. "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
  795. End
  796. Else
  797. {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
  798. x >= RetOffset) as it doesn't do anything (it writes either to a
  799. parameter or to the temporary storage room for the function
  800. result)}
  801. If {Assigned(p^.next) And}
  802. GetNextInstruction(p, hp1) And
  803. (Pai(hp1)^.typ = ait_instruction)
  804. Then
  805. If ((Pai386(hp1)^._operator = A_LEAVE) Or
  806. (Pai386(hp1)^._operator = A_RET)) And
  807. (Pai386(p)^.op2t = top_ref) And
  808. (TReference(Pai386(p)^.op2^).base = ProcInfo.FramePointer) And
  809. (TReference(Pai386(p)^.op2^).offset >= ProcInfo.RetOffset) And
  810. (TReference(Pai386(p)^.op2^).index = R_NO) And
  811. (Pai386(p)^.op1t = top_reg)
  812. Then
  813. Begin
  814. { hp1 := Pai(p^.next);}
  815. AsmL^.Remove(p);
  816. Dispose(p, done);
  817. p := hp1;
  818. End
  819. Else
  820. If (Pai386(p)^.op1t = top_reg) And
  821. (Pai386(p)^.op2t = top_ref) And
  822. (Pai386(p)^.Size = Pai386(hp1)^.Size) And
  823. (Pai386(hp1)^._operator = A_CMP) And
  824. (Pai386(hp1)^.op2t = top_ref) And
  825. RefsEqual(TReference(Pai386(p)^.op2^),
  826. TReference(Pai386(hp1)^.op2^))
  827. Then
  828. {change "mov reg, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
  829. Begin
  830. Dispose(PReference(Pai386(hp1)^.op2));
  831. Pai386(hp1)^.opxt := Pai386(hp1)^.op1t + (top_reg shl 4);
  832. Pai386(hp1)^.op2 := Pai386(p)^.op1
  833. End;
  834. { Next instruction is also a MOV ? }
  835. If {assigned(p^.next) and}
  836. GetNextInstruction(p, hp1) And
  837. (pai(hp1)^.typ = ait_instruction) and
  838. (Pai386(hp1)^._operator = A_MOV)
  839. Then
  840. Begin
  841. { Removes the second statement from
  842. mov %reg, mem
  843. mov mem, %reg }
  844. If (Pai386(hp1)^.op1t = Pai386(p)^.op2t) and
  845. (Pai386(hp1)^.op2t = Pai386(p)^.op1t)
  846. Then
  847. Begin
  848. If (Pai386(hp1)^.op2t = top_ref)
  849. Then
  850. TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op2^), TReference(Pai386(p)^.op1^))
  851. Else
  852. TmpBool1 := Pai386(hp1)^.op2 = Pai386(p)^.op1;
  853. If TmpBool1
  854. Then
  855. Begin
  856. If (Pai386(hp1)^.op1t = top_ref)
  857. Then
  858. TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op1^),
  859. TReference(Pai386(p)^.op2^))
  860. Else TmpBool1 := (Pai386(hp1)^.op1 = Pai386(p)^.op2);
  861. If TmpBool1 Then
  862. Begin
  863. { hp1 := pai(p^.next);}
  864. AsmL^.remove(hp1);
  865. Dispose(hp1,done);
  866. End;
  867. End
  868. Else
  869. Begin
  870. { hp1 := pai(p^.next^.next);}
  871. If GetNextInstruction(hp1, hp2) And
  872. (Pai386(p)^.op1t = top_ref) And
  873. (Pai386(p)^.op2t = top_reg) And
  874. (Pai386(hp1)^.op1t = top_reg) And
  875. (Pai386(hp1)^.op1 = Pai386(p)^.op2) And
  876. (Pai386(hp1)^.op2t = top_ref) And
  877. { Assigned(hp1) And}
  878. (Pai(hp2)^.typ = ait_instruction) And
  879. (Pai386(hp2)^._operator = A_MOV) And
  880. (Pai386(hp2)^.op2t = top_reg) And
  881. (Pai386(hp2)^.op1t = top_ref) And
  882. RefsEqual(TReference(Pai386(hp2)^.op1^),
  883. TReference(Pai386(hp1)^.op2^))
  884. Then
  885. If (TRegister(Pai386(p)^.op2) <> R_ESI)
  886. Then
  887. { mov mem1, reg1
  888. mov reg1, mem2
  889. mov mem2, reg2
  890. to:
  891. mov mem1, reg2
  892. mov reg2, mem2}
  893. Begin
  894. Pai386(p)^.op2 := Pai386(hp2)^.op2;
  895. Pai386(hp1)^.op1 := Pai386(hp2)^.op2;
  896. AsmL^.Remove(hp2);
  897. Dispose(hp2,Done);
  898. End
  899. Else
  900. { mov mem1, esi
  901. mov esi, mem2
  902. mov mem2, reg2
  903. to:
  904. mov mem1, esi
  905. mov mem1, reg2
  906. mov esi, mem2}
  907. Begin
  908. Pai386(hp1)^.opxt := top_ref + top_reg shl 4;
  909. Pai386(hp1)^.op1 := Pai386(p)^.op2;
  910. TReference(Pai386(hp1)^.op1^) := TReference(Pai386(p)^.op1^);
  911. Pai386(hp1)^.op2 := Pai386(hp2)^.op2;
  912. Pai386(hp2)^.opxt := top_reg + top_ref shl 4;
  913. Pai386(hp2)^.op2 := Pai386(hp2)^.op1;
  914. Pai386(hp2)^.op1 := Pointer(R_ESI)
  915. End;
  916. End;
  917. End
  918. Else
  919. (* { movl [mem1],reg1
  920. movl [mem1],reg2
  921. to:
  922. movl [mem1],reg1
  923. movl reg1,reg2 }
  924. If (Pai386(p)^.op1t = top_ref) and
  925. (Pai386(p)^.op2t = top_reg) and
  926. (Pai386(hp1)^.op1t = top_ref) and
  927. (Pai386(hp1)^.op2t = top_reg) and
  928. (Pai386(p)^.size = Pai386(hp1)^.size) and
  929. RefsEqual(TReference(Pai386(p)^.op1^),TReference(Pai386(hp1)^.op1^)) and
  930. (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).base) and
  931. (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).index) then
  932. Begin
  933. Dispose(PReference(Pai386(hp1)^.op1));
  934. Pai386(hp1)^.op1:=Pai386(p)^.op2;
  935. Pai386(hp1)^.opxt:=Top_reg+Top_reg shl 4;
  936. End
  937. Else*)
  938. { movl const1,[mem1]
  939. movl [mem1],reg1
  940. to:
  941. movl const1,reg1
  942. movl reg1,[mem1] }
  943. If (Pai386(p)^.op1t = top_const) and
  944. (Pai386(p)^.op2t = top_ref) and
  945. (Pai386(hp1)^.op1t = top_ref) and
  946. (Pai386(hp1)^.op2t = top_reg) and
  947. (Pai386(p)^.size = Pai386(hp1)^.size) and
  948. RefsEqual(TReference(Pai386(hp1)^.op1^),TReference(Pai386(p)^.op2^)) then
  949. Begin
  950. Pai386(hp1)^.op1:=Pai386(hp1)^.op2;
  951. Pai386(hp1)^.op2:=Pai386(p)^.op2;
  952. Pai386(hp1)^.opxt:=Top_reg+Top_ref shl 4;
  953. Pai386(p)^.op2:=Pai386(hp1)^.op1;
  954. Pai386(p)^.opxt:=Top_const+(top_reg shl 4);
  955. End
  956. End;
  957. {changes "mov $0, %reg" into "xor %reg, %reg"}
  958. If (Pai386(p)^.op1t = Top_Const) And
  959. (Pai386(p)^.op1 = Pointer(0)) And
  960. (Pai386(p)^.op2t = Top_Reg)
  961. Then
  962. Begin
  963. Pai386(p)^._operator := A_XOR;
  964. Pai386(p)^.opxt := Top_Reg+Top_reg shl 4;
  965. Pai386(p)^.op1 := Pai386(p)^.op2;
  966. End;
  967. End;
  968. A_MOVZX:
  969. Begin
  970. {removes superfluous And's after movzx's}
  971. If (Pai386(p)^.op2t = top_reg) And
  972. { Assigned(p^.next) And}
  973. GetNextInstruction(p, hp1) And
  974. (Pai(hp1)^.typ = ait_instruction) And
  975. (Pai386(hp1)^._operator = A_AND) And
  976. (Pai386(hp1)^.op1t = top_const) And
  977. (Pai386(hp1)^.op2t = top_reg) And
  978. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  979. Then
  980. Case Pai386(p)^.Size Of
  981. S_BL, S_BW:
  982. If (Longint(Pai386(hp1)^.op1) = $ff)
  983. Then
  984. Begin
  985. { hp1 := Pai(p^.next);}
  986. AsmL^.Remove(hp1);
  987. Dispose(hp1, Done);
  988. End;
  989. S_WL:
  990. If (Longint(Pai386(hp1)^.op1) = $ffff)
  991. Then
  992. Begin
  993. { hp1 := Pai(p^.next);}
  994. AsmL^.Remove(hp1);
  995. Dispose(hp1, Done);
  996. End;
  997. End;
  998. {changes some movzx constructs to faster synonims (all examples
  999. are given with eax/ax, but are also valid for other registers)}
  1000. If (Pai386(p)^.op2t = top_reg) Then
  1001. If (Pai386(p)^.op1t = top_reg)
  1002. Then
  1003. Case Pai386(p)^.size of
  1004. S_BW:
  1005. Begin
  1006. If (TRegister(Pai386(p)^.op1) = Reg16ToReg8(TRegister(Pai386(p)^.op2))) And
  1007. Not(CS_LittleSize In AktSwitches)
  1008. Then
  1009. {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
  1010. Begin
  1011. Pai386(p)^._operator := A_AND;
  1012. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  1013. Longint(Pai386(p)^.op1) := $ff;
  1014. Pai386(p)^.Size := S_W
  1015. End
  1016. Else
  1017. If {Assigned(p^.next) And}
  1018. GetNextInstruction(p, hp1) And
  1019. (Pai(hp1)^.typ = ait_instruction) And
  1020. (Pai386(hp1)^._operator = A_AND) And
  1021. (Pai386(hp1)^.op1t = top_const) And
  1022. (Pai386(hp1)^.op2t = top_reg) And
  1023. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  1024. Then
  1025. {Change "movzbw %reg1, %reg2; andw $const, %reg2"
  1026. to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
  1027. Begin
  1028. Pai386(p)^._operator := A_MOV;
  1029. Pai386(p)^.Size := S_W;
  1030. Pai386(p)^.op1 := Pointer(Reg8ToReg16(TRegister(Pai386(p)^.op1)));
  1031. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
  1032. End;
  1033. End;
  1034. S_BL:
  1035. Begin
  1036. If (TRegister(Pai386(p)^.op1) = Reg32ToReg8(TRegister(Pai386(p)^.op2))) And
  1037. Not(CS_LittleSize in AktSwitches)
  1038. Then
  1039. {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
  1040. Begin
  1041. Pai386(p)^._operator := A_AND;
  1042. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  1043. Longint(Pai386(p)^.op1) := $ff;
  1044. Pai386(p)^.Size := S_L;
  1045. End
  1046. Else
  1047. If {Assigned(p^.next) And}
  1048. GetNextInstruction(p, hp1) And
  1049. (Pai(hp1)^.typ = ait_instruction) And
  1050. (Pai386(hp1)^._operator = A_AND) And
  1051. (Pai386(hp1)^.op1t = top_const) And
  1052. (Pai386(hp1)^.op2t = top_reg) And
  1053. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  1054. Then
  1055. {Change "movzbl %reg1, %reg2; andl $const, %reg2"
  1056. to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
  1057. Begin
  1058. Pai386(p)^._operator := A_MOV;
  1059. Pai386(p)^.Size := S_L;
  1060. Pai386(p)^.op1 := Pointer(Reg8ToReg32(TRegister(Pai386(p)^.op1)));
  1061. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
  1062. End
  1063. Else
  1064. If IsGP32Reg(TRegister(Pai386(p)^.op2)) And
  1065. Not(CS_LittleSize in AktSwitches) And
  1066. (Opt_Processors >= Pentium) And
  1067. (Opt_Processors < PentiumPro)
  1068. Then
  1069. {Change "movzbl %reg1, %reg2" to
  1070. "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
  1071. PentiumMMX}
  1072. Begin
  1073. hp1 := New(Pai386, op_reg_reg(A_XOR, S_L,
  1074. TRegister(Pai386(p)^.op2),
  1075. TRegister(Pai386(p)^.op2)));
  1076. hp1^.line := p^.line;
  1077. InsertLLItem(p^.last, p, hp1);
  1078. Pai386(p)^._operator := A_MOV;
  1079. Pai386(p)^.size := S_B;
  1080. Pai386(p)^.op2 :=
  1081. Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
  1082. InsertLLItem(p, p^.next, hp2);
  1083. End;
  1084. End;
  1085. S_WL:
  1086. Begin
  1087. If (TRegister(Pai386(p)^.op1) = Reg32ToReg16(TRegister(Pai386(p)^.op2))) And
  1088. Not(CS_LittleSize In AktSwitches)
  1089. Then
  1090. {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
  1091. Begin
  1092. Pai386(p)^._operator := A_AND;
  1093. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  1094. Longint(Pai386(p)^.op1) := $ffff;
  1095. Pai386(p)^.Size := S_L
  1096. End
  1097. Else
  1098. If {Assigned(p^.next) And}
  1099. GetNextInstruction(p, hp1) And
  1100. (Pai(hp1)^.typ = ait_instruction) And
  1101. (Pai386(hp1)^._operator = A_AND) And
  1102. (Pai386(hp1)^.op1t = top_const) And
  1103. (Pai386(hp1)^.op2t = top_reg) And
  1104. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  1105. Then
  1106. {Change "movzwl %reg1, %reg2; andl $const, %reg2"
  1107. to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
  1108. Begin
  1109. Pai386(p)^._operator := A_MOV;
  1110. Pai386(p)^.Size := S_L;
  1111. Pai386(p)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(p)^.op1)));
  1112. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ffff);
  1113. End;
  1114. End;
  1115. End
  1116. Else
  1117. If (Pai386(p)^.op1t = top_ref) Then
  1118. Begin
  1119. If (PReference(Pai386(p)^.op1)^.base <> TRegister(Pai386(p)^.op2)) And
  1120. (PReference(Pai386(p)^.op1)^.index <> TRegister(Pai386(p)^.op2)) And
  1121. Not(CS_LittleSize in AktSwitches) And
  1122. IsGP32Reg(TRegister(Pai386(p)^.op2)) And
  1123. (Opt_Processors >= Pentium) And
  1124. (Opt_Processors < PentiumPro) And
  1125. (Pai386(p)^.Size = S_BL)
  1126. Then
  1127. {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
  1128. Pentium and PentiumMMX}
  1129. Begin
  1130. hp1 := New(Pai386,op_reg_reg(A_XOR, S_L, TRegister(Pai386(p)^.op2),
  1131. TRegister(Pai386(p)^.op2)));
  1132. hp1^.line := p^.line;
  1133. Pai386(p)^._operator := A_MOV;
  1134. Pai386(p)^.size := S_B;
  1135. Pai386(p)^.op2 := Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
  1136. InsertLLItem(p^.last, p, hp1);
  1137. End
  1138. Else
  1139. If {Assigned(p^.next) And}
  1140. GetNextInstruction(p, hp1) And
  1141. (Pai(hp1)^.typ = ait_instruction) And
  1142. (Pai386(hp1)^._operator = A_AND) And
  1143. (Pai386(hp1)^.op1t = Top_Const) And
  1144. (Pai386(hp1)^.op2t = Top_Reg) And
  1145. (Pai386(hp1)^.op2 = Pai386(p)^.op2) Then
  1146. Begin
  1147. Pai386(p)^._operator := A_MOV;
  1148. Case Pai386(p)^.Size Of
  1149. S_BL:
  1150. Begin
  1151. Pai386(p)^.Size := S_L;
  1152. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  1153. And $ff);
  1154. End;
  1155. S_WL:
  1156. Begin
  1157. Pai386(p)^.Size := S_L;
  1158. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  1159. And $ffff);
  1160. End;
  1161. S_BW:
  1162. Begin
  1163. Pai386(p)^.Size := S_W;
  1164. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  1165. And $ff);
  1166. End;
  1167. End;
  1168. End;
  1169. End;
  1170. End;
  1171. A_POP:
  1172. Begin
  1173. if (Pai386(p)^.op1t = top_reg) And
  1174. { (assigned(p^.next)) and}
  1175. GetNextInstruction(p, hp1) And
  1176. (pai(hp1)^.typ=ait_instruction) and
  1177. (Pai386(hp1)^._operator=A_PUSH) and
  1178. (Pai386(hp1)^.op1t = top_reg) And
  1179. (Pai386(hp1)^.op1=Pai386(p)^.op1) then
  1180. begin
  1181. hp2:=pai(hp1^.next);
  1182. asml^.remove(p);
  1183. asml^.remove(hp1);
  1184. dispose(p,done);
  1185. dispose(hp1,done);
  1186. p:=hp2;
  1187. continue;
  1188. { Pai386(p)^._operator := A_MOV;
  1189. Pai386(p)^.op2 := Pai386(p)^.op1;
  1190. Pai386(p)^.opxt := top_ref + top_reg shl 4;
  1191. New(TmpRef);
  1192. TmpRef^.segment := R_DEFAULT_SEG;
  1193. TmpRef^.base := R_ESP;
  1194. TmpRef^.index := R_NO;
  1195. TmpRef^.scalefactor := 1;
  1196. TmpRef^.symbol := nil;
  1197. TmpRef^.isintvalue := false;
  1198. TmpRef^.offset := 0;
  1199. Pai386(p)^.op1 := Pointer(TmpRef);
  1200. hp1 := Pai(p^.next);
  1201. AsmL^.Remove(hp1);
  1202. Dispose(hp1, Done)}
  1203. end;
  1204. end;
  1205. A_PUSH:
  1206. Begin
  1207. If (Pai386(p)^.size = S_W) And
  1208. (Pai386(p)^.op1t = Top_Const) And
  1209. { Assigned(p^.next) And}
  1210. GetNextInstruction(p, hp1) And
  1211. (Pai(hp1)^.typ = ait_instruction) And
  1212. (Pai386(hp1)^._operator = A_PUSH) And
  1213. (Pai386(hp1)^.op1t = Top_Const) And
  1214. (Pai386(hp1)^.size = S_W) Then
  1215. Begin
  1216. { hp1 := Pai(p^.next);}
  1217. Pai386(p)^.Size := S_L;
  1218. Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) shl 16 + Longint(Pai386(hp1)^.op1));
  1219. AsmL^.Remove(hp1);
  1220. Dispose(hp1, Done)
  1221. End;
  1222. End;
  1223. A_SHL, A_SAL:
  1224. Begin
  1225. If (Pai386(p)^.op1t = Top_Const) And
  1226. (Pai386(p)^.op2t = Top_Reg) And
  1227. (Pai386(p)^.Size = S_L) And
  1228. (Longint(Pai386(p)^.op1) <= 3)
  1229. {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
  1230. Then
  1231. Begin
  1232. TmpBool1 := True; {should we check the next instruction?}
  1233. TmpBool2 := False; {have we found an add/sub which could be
  1234. integrated in the lea?}
  1235. New(TmpRef);
  1236. TmpRef^.segment := R_DEFAULT_SEG;
  1237. TmpRef^.base := R_NO;
  1238. TmpRef^.index := TRegister(Pai386(p)^.op2);
  1239. TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
  1240. TmpRef^.symbol := nil;
  1241. TmpRef^.isintvalue := false;
  1242. TmpRef^.offset := 0;
  1243. While TmpBool1 And
  1244. { Assigned(p^.next) And}
  1245. GetNextInstruction(p, hp1) And
  1246. (Pai(hp1)^.typ = ait_instruction) And
  1247. ((Pai386(hp1)^._operator = A_ADD) Or
  1248. (Pai386(hp1)^._operator = A_SUB)) And
  1249. (Pai386(hp1)^.op2t = Top_Reg) And
  1250. (Pai386(hp1)^.op2 = Pai386(p)^.op2) Do
  1251. Begin
  1252. TmpBool1 := False;
  1253. If (Pai386(hp1)^.op1t = Top_Const)
  1254. Then
  1255. Begin
  1256. TmpBool1 := True;
  1257. TmpBool2 := True;
  1258. If Pai386(hp1)^._operator = A_ADD
  1259. Then Inc(TmpRef^.offset, Longint(Pai386(hp1)^.op1))
  1260. Else Dec(TmpRef^.offset, Longint(Pai386(hp1)^.op1));
  1261. { hp1 := Pai(p^.next);}
  1262. AsmL^.Remove(hp1);
  1263. Dispose(hp1, Done);
  1264. End
  1265. Else
  1266. If (Pai386(hp1)^.op1t = Top_Reg) And
  1267. (Pai386(hp1)^._operator = A_ADD) And
  1268. (TmpRef^.base = R_NO) Then
  1269. Begin
  1270. TmpBool1 := True;
  1271. TmpBool2 := True;
  1272. TmpRef^.base := TRegister(Pai386(hp1)^.op1);
  1273. { hp1 := Pai(p^.next);}
  1274. AsmL^.Remove(hp1);
  1275. Dispose(hp1, Done);
  1276. End;
  1277. End;
  1278. If TmpBool2 Or
  1279. ((Opt_Processors < PentiumPro) And
  1280. (Longint(Pai386(p)^.op1) <= 3) And
  1281. Not(CS_LittleSize in AktSwitches))
  1282. Then
  1283. Begin
  1284. If Not(TmpBool2) And
  1285. (Longint(Pai386(p)^.op1) = 1)
  1286. Then
  1287. Begin
  1288. Dispose(TmpRef);
  1289. hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
  1290. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)))
  1291. End
  1292. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  1293. TRegister(Pai386(p)^.op2)));
  1294. hp1^.line := p^.line;
  1295. InsertLLItem(p^.last, p^.next, hp1);
  1296. Dispose(p, Done);
  1297. p := hp1;
  1298. End;
  1299. End
  1300. Else
  1301. If (Opt_Processors < PentiumPro) And
  1302. (Pai386(p)^.op1t = top_const) And
  1303. (Pai386(p)^.op2t = top_reg) Then
  1304. If (Longint(Pai386(p)^.op1) = 1)
  1305. Then
  1306. {changes "shl $1, %reg" to "add %reg, %reg", which
  1307. is the same on a 386, but faster on a 486, and pairable in both U and V
  1308. pipes on the Pentium (unlike shl, which is only pairable in the U pipe)}
  1309. Begin
  1310. hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
  1311. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
  1312. hp1^.line := p^.line;
  1313. InsertLLItem(p^.last, p^.next, hp1);
  1314. Dispose(p, done);
  1315. p := hp1;
  1316. End
  1317. Else If (Pai386(p)^.size = S_L) and
  1318. (Longint(Pai386(p)^.op1) <= 3) Then
  1319. {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
  1320. "shl $3, %reg" to "lea (,%reg,8), %reg}
  1321. Begin
  1322. New(TmpRef);
  1323. TmpRef^.segment := R_DEFAULT_SEG;
  1324. TmpRef^.base := R_NO;
  1325. TmpRef^.index := TRegister(Pai386(p)^.op2);
  1326. TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
  1327. TmpRef^.symbol := nil;
  1328. TmpRef^.isintvalue := false;
  1329. TmpRef^.offset := 0;
  1330. hp1 := new(Pai386,op_ref_reg(A_LEA,S_L,TmpRef, TRegister(Pai386(p)^.op2)));
  1331. hp1^.line := p^.line;
  1332. InsertLLItem(p^.last, p^.next, hp1);
  1333. Dispose(p, done);
  1334. p := hp1;
  1335. End
  1336. End;
  1337. A_SAR, A_SHR:
  1338. {changes the code sequence
  1339. shr/sar const1, %reg
  1340. shl const2, %reg
  1341. to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
  1342. Begin
  1343. { hp1 := pai(p^.next);}
  1344. If {Assigned(hp1) and}
  1345. GetNextInstruction(p, hp1) And
  1346. (pai(hp1)^.typ = ait_instruction) and
  1347. (Pai386(hp1)^._operator = A_SHL) and
  1348. (Pai386(p)^.op1t = top_const) and
  1349. (Pai386(hp1)^.op1t = top_const) Then
  1350. If (Longint(Pai386(p)^.op1) > Longint(Pai386(hp1)^.op1)) Then
  1351. If (Pai386(p)^.op2t = Top_reg) And
  1352. Not(CS_LittleSize In AktSwitches) And
  1353. ((Pai386(p)^.Size = S_B) Or
  1354. (Pai386(p)^.Size = S_L))
  1355. Then
  1356. Begin
  1357. Dec(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
  1358. Pai386(hp1)^._operator := A_And;
  1359. Pai386(hp1)^.op1 := Pointer(PowerOf2(Longint(Pai386(hp1)^.op1))-1);
  1360. If (Pai386(p)^.Size = S_L)
  1361. Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
  1362. Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1363. End
  1364. Else
  1365. If (Longint(Pai386(p)^.op1) < Longint(Pai386(hp1)^.op1)) Then
  1366. If (Pai386(p)^.op2t = Top_reg) And
  1367. Not(CS_LittleSize In AktSwitches) And
  1368. ((Pai386(p)^.Size = S_B) Or
  1369. (Pai386(p)^.Size = S_L))
  1370. Then
  1371. Begin
  1372. Dec(Longint(Pai386(hp1)^.op1), Longint(Pai386(p)^.op1));
  1373. Pai386(p)^._operator := A_And;
  1374. Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
  1375. If (Pai386(p)^.Size = S_L)
  1376. Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
  1377. Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1378. End
  1379. Else
  1380. Begin
  1381. Pai386(p)^._operator := A_And;
  1382. Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
  1383. Case Pai386(p)^.Size Of
  1384. S_B: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1385. S_W: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffff);
  1386. S_L: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor
  1387. $ffffffff);
  1388. End;
  1389. AsmL^.remove(hp1);
  1390. dispose(hp1, done);
  1391. End;
  1392. End;
  1393. A_SUB:
  1394. {change "subl $2, %esp; pushw x" to "pushl x"}
  1395. Begin
  1396. If (Pai386(p)^.op1t = top_const) And
  1397. (Longint(Pai386(p)^.op1) = 2) And
  1398. (Pai386(p)^.op2t = top_reg) And
  1399. (TRegister(Pai386(p)^.op2) = R_ESP)
  1400. Then
  1401. Begin
  1402. hp1 := Pai(p^.next);
  1403. While Assigned(hp1) And
  1404. (Pai(hp1)^.typ In [ait_instruction]+SkipInstr) And
  1405. Not((Pai(hp1)^.typ = ait_instruction) And
  1406. (Pai386(hp1)^._operator in [A_CALL,A_PUSH])) do
  1407. hp1 := Pai(hp1^.next);
  1408. If Assigned(hp1) And
  1409. (Pai(hp1)^.typ = ait_instruction) And
  1410. (Pai386(hp1)^._operator = A_PUSH) And
  1411. (Pai386(hp1)^.Size = S_W)
  1412. Then
  1413. Begin
  1414. Pai386(hp1)^.size := S_L;
  1415. If (Pai386(hp1)^.op1t = top_reg) Then
  1416. Pai386(hp1)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(hp1)^.op1)));
  1417. hp1 := Pai(p^.next);
  1418. AsmL^.Remove(p);
  1419. Dispose(p, Done);
  1420. p := hp1;
  1421. Continue
  1422. End
  1423. Else
  1424. If {Assigned(p^.last) And}
  1425. GetLastInstruction(p, hp1) And
  1426. (Pai(hp1)^.typ = ait_instruction) And
  1427. (Pai386(hp1)^._operator = A_SUB) And
  1428. (Pai386(hp1)^.op1t = top_const) And
  1429. (Pai386(hp1)^.op2t = top_reg) And
  1430. (TRegister(Pai386(hp1)^.Op2) = R_ESP)
  1431. Then
  1432. Begin
  1433. { hp1 := Pai(p^.last);}
  1434. Inc(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
  1435. AsmL^.Remove(hp1);
  1436. Dispose(hp1, Done);
  1437. End;
  1438. End;
  1439. End;
  1440. A_TEST, A_OR:
  1441. {removes the line marked with (x) from the sequence
  1442. And/or/xor/add/sub/... $x, %y
  1443. test/or %y, %y (x)
  1444. j(n)z _Label
  1445. as the first instruction already adjusts the ZF}
  1446. Begin
  1447. If (Pai386(p)^.op1 = Pai386(p)^.op2) And
  1448. { (assigned(p^.last)) And}
  1449. GetLastInstruction(p, hp1) And
  1450. (pai(hp1)^.typ = ait_instruction) Then
  1451. Case Pai386(hp1)^._operator Of
  1452. A_ADD, A_SUB, A_OR, A_XOR, A_AND, A_SHL, A_SHR:
  1453. Begin
  1454. If (Pai386(hp1)^.op2 = Pai386(p)^.op1) Then
  1455. Begin
  1456. hp1 := pai(p^.next);
  1457. asml^.remove(p);
  1458. dispose(p, done);
  1459. p := pai(hp1);
  1460. continue
  1461. End;
  1462. End;
  1463. A_DEC, A_INC, A_NEG:
  1464. Begin
  1465. If (Pai386(hp1)^.op1 = Pai386(p)^.op1) Then
  1466. Begin
  1467. hp1 := pai(p^.next);
  1468. asml^.remove(p);
  1469. dispose(p, done);
  1470. p := pai(hp1);
  1471. continue
  1472. End;
  1473. End
  1474. End;
  1475. End;
  1476. End;
  1477. End;
  1478. ait_label:
  1479. Begin
  1480. If Not(Pai_Label(p)^.l^.is_used)
  1481. Then
  1482. Begin
  1483. hp1 := Pai(p^.next);
  1484. AsmL^.Remove(p);
  1485. Dispose(p, Done);
  1486. p := hp1;
  1487. Continue
  1488. End;
  1489. End;
  1490. {$ifdef regalloc}
  1491. ait_regalloc: UsedRegs := UsedRegs + [PaiAlloc(p)^.Reg];
  1492. ait_regdealloc: UsedRegs := UsedRegs - [PaiAlloc(p)^.Reg];
  1493. {$endif regalloc}
  1494. End;
  1495. p:=pai(p^.next);
  1496. end;
  1497. end;
  1498. Procedure peepholeopt(AsmL : paasmoutput);
  1499. Procedure FindLoHiLabels;
  1500. {Walks through the paasmlist to find the lowest and highest label number;
  1501. Since 0.9.3: also removes unused labels}
  1502. Var LabelFound: Boolean;
  1503. P, hp1: Pai;
  1504. Begin
  1505. LabelFound := False;
  1506. LoLab := MaxLongint;
  1507. HiLab := 0;
  1508. p := Pai(AsmL^.first);
  1509. While Assigned(p) Do
  1510. Begin
  1511. If (Pai(p)^.typ = ait_label) Then
  1512. If (Pai_Label(p)^.l^.is_used)
  1513. Then
  1514. Begin
  1515. LabelFound := True;
  1516. If (Pai_Label(p)^.l^.nb < LoLab) Then
  1517. LoLab := Pai_Label(p)^.l^.nb;
  1518. If (Pai_Label(p)^.l^.nb > HiLab) Then
  1519. HiLab := Pai_Label(p)^.l^.nb;
  1520. End
  1521. Else
  1522. Begin
  1523. hp1 := pai(p^.next);
  1524. AsmL^.Remove(p);
  1525. Dispose(p, Done);
  1526. p := hp1;
  1527. continue;
  1528. End;
  1529. p := pai(p^.next);
  1530. End;
  1531. If LabelFound
  1532. Then LabDif := HiLab+1-LoLab
  1533. Else LabDif := 0;
  1534. End;
  1535. Procedure BuildLabelTable;
  1536. {Builds a table with the locations of the labels in the paasmoutput}
  1537. Var p: Pai;
  1538. Begin
  1539. If (LabDif <> 0) Then
  1540. Begin
  1541. {$IfDef TP}
  1542. If (MaxAvail >= LabDif*SizeOf(Pai))
  1543. Then
  1544. Begin
  1545. {$EndIf TP}
  1546. GetMem(LTable, LabDif*SizeOf(Pai));
  1547. FillChar(LTable^, LabDif*SizeOf(Pai), 0);
  1548. p := pai(AsmL^.first);
  1549. While Assigned(p) Do
  1550. Begin
  1551. If (Pai(p)^.typ = ait_label) Then
  1552. LTable^[Pai_Label(p)^.l^.nb-LoLab] := p;
  1553. p := pai(p^.next);
  1554. End;
  1555. {$IfDef TP}
  1556. End
  1557. Else LabDif := 0;
  1558. {$EndIf TP}
  1559. End;
  1560. End;
  1561. Begin
  1562. FindLoHiLabels;
  1563. BuildLabelTable;
  1564. DoOptimize(AsmL);
  1565. DoOptimize(AsmL);
  1566. If LabDif <> 0 Then Freemem(LTable, LabDif*SizeOf(Pai));
  1567. ReloadOpt(AsmL)
  1568. End;
  1569. End.
  1570. {
  1571. $Log$
  1572. Revision 1.7 1998-04-23 21:52:08 florian
  1573. * fixes of Jonas applied
  1574. Revision 1.6 1998/04/21 11:30:14 peter
  1575. * fixed $ifdef regalloc
  1576. Revision 1.5 1998/04/16 16:53:56 jonas
  1577. *** empty log message ***
  1578. Revision 1.4 1998/04/08 19:12:28 jonas
  1579. * fixed bug where "imul 12,reg" was replaced with a wrong lea sequence
  1580. Revision 1.3 1998/03/29 17:27:58 florian
  1581. * aopt386 compiles with TP
  1582. * correct line number is displayed, if a #0 is in the input
  1583. Revision 1.2 1998/03/28 23:09:53 florian
  1584. * secondin bugfix (m68k and i386)
  1585. * overflow checking bugfix (m68k and i386) -- pretty useless in
  1586. secondadd, since everything is done using 32-bit
  1587. * loading pointer to routines hopefully fixed (m68k)
  1588. * flags problem with calls to RTL internal routines fixed (still strcmp
  1589. to fix) (m68k)
  1590. * #ELSE was still incorrect (didn't take care of the previous level)
  1591. * problem with filenames in the command line solved
  1592. * problem with mangledname solved
  1593. * linking name problem solved (was case insensitive)
  1594. * double id problem and potential crash solved
  1595. * stop after first error
  1596. * and=>test problem removed
  1597. * correct read for all float types
  1598. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1599. * push/pop is now correct optimized (=> mov (%esp),reg)
  1600. Revision 1.1.1.1 1998/03/25 11:18:12 root
  1601. * Restored version
  1602. Revision 1.29 1998/03/24 21:48:29 florian
  1603. * just a couple of fixes applied:
  1604. - problem with fixed16 solved
  1605. - internalerror 10005 problem fixed
  1606. - patch for assembler reading
  1607. - small optimizer fix
  1608. - mem is now supported
  1609. Revision 1.28 1998/03/19 18:57:05 florian
  1610. * small fixes applied
  1611. Revision 1.27 1998/03/18 22:50:10 florian
  1612. + fstp/fld optimization
  1613. * routines which contains asm aren't longer optimzed
  1614. * wrong ifdef TEST_FUNCRET corrected
  1615. * wrong data generation for array[0..n] of char = '01234'; fixed
  1616. * bug0097 is fixed partial
  1617. * bug0116 fixed (-Og doesn't use enter of the stack frame is greater than
  1618. 65535)
  1619. Revision 1.26 1998/03/10 23:48:35 florian
  1620. * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
  1621. enough, it doesn't run
  1622. Revision 1.25 1998/03/10 01:17:14 peter
  1623. * all files have the same header
  1624. * messages are fully implemented, EXTDEBUG uses Comment()
  1625. + AG... files for the Assembler generation
  1626. Revision 1.24 1998/03/04 19:09:59 jonas
  1627. * fixed incompatibility with new code generator concerning "mov mem, reg; mov reg, edi" optimization
  1628. Revision 1.23 1998/03/03 22:37:09 peter
  1629. - uses errors
  1630. Revision 1.22 1998/03/03 14:48:31 jonas
  1631. * added errors to the uses clause (required for aopt386.inc)
  1632. Revision 1.21 1998/03/02 21:35:15 jonas
  1633. * added comments from last update
  1634. Revision 1.20 1998/03/02 21:29:04 jonas
  1635. * change "mov reg, mem; cmp x, mem" to "mov reg, mem; cmp x, reg"
  1636. * change "and x, reg; jxx" to "test reg, x; jxx" (also allows some extra reloading opts)
  1637. Revision 1.19 1998/03/02 01:47:58 peter
  1638. * renamed target_DOS to target_GO32V1
  1639. + new verbose system, merged old errors and verbose units into one new
  1640. verbose.pas, so errors.pas is obsolete
  1641. Revision 1.18 1998/02/27 16:33:26 florian
  1642. * syntax errors and line too long errors fixed
  1643. Revision 1.17 1998/02/26 17:20:31 jonas
  1644. * re-enabled mov optimizations, re-commented out the "mov mem, reg1; mov mem, reg2" optimization
  1645. Revision 1.16 1998/02/26 11:56:55 daniel
  1646. * New assembler optimizations commented out, because of bugs.
  1647. * Use of dir-/name- and extstr.
  1648. Revision 1.15 1998/02/25 14:08:30 daniel
  1649. * Compiler uses less memory. *FIX*
  1650. Revision 1.14 1998/02/25 12:32:12 daniel
  1651. * Compiler uses even less memory.
  1652. Revision 1.13 1998/02/24 21:18:12 jonas
  1653. * file name back to lower case
  1654. Revision 1.2 1998/02/24 20:32:11 jonas
  1655. * added comments from latest commit
  1656. Revision 1.1 1998/02/24 20:27:50 jonas
  1657. + change "cmp $0, reg" to "test reg, reg"
  1658. + add correct line numbers to Pai386 objects created by the optimizer
  1659. * dispose TReference of second instructions optimized from "mov mem, reg1; mov
  1660. mem, reg2" to "mov mem, reg; mov reg1, reg2"
  1661. + optimize "mov mem, reg1; mov reg1, reg2" to "mov mem, reg2" if reg1 <> esi
  1662. - disabled changing "mov mem, reg1; mov mem reg2" to "mov mem reg1; mov reg1,
  1663. reg2" because of conflict with the above optimization
  1664. + remove second instruction from "mov mem, reg; mov reg, %edi" because edi isn't
  1665. used anymore afterwards
  1666. + remove first instruction from "mov %eax, x(%ebp); leave/ret" because it is a
  1667. write to either a parameter or a temporary function result
  1668. + change "mov reg1, reg2; mov reg2, mem" to "mov reg1, mem" if reg2 <> esi
  1669. + change "mov reg1, reg2; test/or reg2, reg2; jxx" to "test/or reg1, reg1" if
  1670. reg2 <> esi
  1671. + change "mov reg1, reg2; test/or reg2, reg2" to "mov reg1, reg2; test/or reg1,
  1672. reg1" to avoid a read/write pnealty if reg2 = esi
  1673. * took FindLoHiLabel and BuildLabelTable out of the main loop, so they're both
  1674. called only once per code fragment that has to be optimized
  1675. Revision 1.12 1998/02/19 22:46:55 peter
  1676. * Fixed linebreaks
  1677. Revision 1.11 1998/02/13 10:34:32 daniel
  1678. * Made Motorola version compilable.
  1679. * Fixed optimizer
  1680. Revision 1.10 1998/02/12 17:18:51 florian
  1681. * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1682. also that aktswitches isn't a pointer)
  1683. Revision 1.9 1998/02/12 11:49:39 daniel
  1684. Yes! Finally! After three retries, my patch!
  1685. Changes:
  1686. Complete rewrite of psub.pas.
  1687. Added support for DLL's.
  1688. Compiler requires less memory.
  1689. Platform units for each platform.
  1690. Revision 1.8 1998/02/10 21:57:21 peter
  1691. + mov [mem1],reg1;mov [mem1],reg2 -> mov [mem1],reg1;mov reg1,reg2
  1692. + mov const,[mem1];mov [mem1],reg -> mov const,reg;mov reg,[mem1]
  1693. Revision 1.7 1998/02/07 10:10:34 michael
  1694. + superfluous AND's after MOVZX' removed
  1695. + change "subl $2, %esp; ... ; pushw x" to "pushl x"
  1696. + fold "subl $const, %esp; subl $2, %esp" into one instruction
  1697. Revision 1.5 1998/02/02 17:25:43 jonas
  1698. * back to CVS version; change "lea (reg1), reg2" to "mov reg1, reg2"
  1699. Revision 1.2 1997/12/09 13:19:36 carl
  1700. + renamed pai_labeled --> pai_labeled
  1701. Revision 1.1.1.1 1997/11/27 08:32:50 michael
  1702. FPC Compiler CVS start
  1703. Pre-CVS log:
  1704. FK Florian Klampfl (FK)
  1705. JM Jonas Maebe
  1706. + feature added
  1707. - removed
  1708. * bug fixed or changed
  1709. History (started with version 0.9.0):
  1710. 5th november 1996:
  1711. * adapted to 0.9.0
  1712. 30th december 1996:
  1713. * runs with 0.9.1
  1714. 25th July 1996:
  1715. + removal of superfluous "test %reg, %reg" instructions (JM)
  1716. 28th July 1997:
  1717. + change "shl $1, %reg" to "add %reg, %reg" (not working) (JM)
  1718. * fixed bugs in test optimization (tested and working) (JM)
  1719. 29th July 1997:
  1720. * fixed some pointer bugs in SHL optimization, but it still doesn't
  1721. work :( (JM)
  1722. 30th July 1997:
  1723. + change "sar const1, %reg; shl const2, %reg" to one statement (JM)
  1724. * I finally correctly understand the structure of the pai(386)
  1725. object <g> and fixed the shl optimization (tested and working) (JM)
  1726. 31th July 1997:
  1727. + removal of some superfluous reloading of registers (not working) (JM)
  1728. 4th August 1997:
  1729. * fixed reloading optimization (thanks Florian!) (JM)
  1730. 6th August 1997:
  1731. + removal of labels which are not referenced by any instruction
  1732. (allows for easier and better optimization), but it is slow :( (JM)
  1733. 8th August 1997:
  1734. - removed label-removal procedure as it seems to be impossible to
  1735. find out if there are labels which are referenced through a jump
  1736. table (JM)
  1737. 15th August 1997:
  1738. + removal of superfluous "or %reg, %reg" instructions (JM)
  1739. 22th september 1997:
  1740. * test is also removed if it follows neg, shl and shr (FK)
  1741. - removed the sar/shl optimization because:
  1742. movl $0xff,%eax
  1743. shrl $0x3,%eax
  1744. shll $0x3,%eax
  1745. => EAX is $0xf8 !!! (FK)
  1746. 23th September 1997:
  1747. + function FindLabel() so sequences like "jmp l2;l1:;l2:" can be
  1748. optimized (JM)
  1749. 24th September 1997:
  1750. + successive jumps reduced to one jump (see explanation at
  1751. GetFinalDestination). Works fine, but seems to enlarge the code...
  1752. I suppose because there are more >128 bytes-jumps and their opcodes
  1753. are longer. If (cs_littlesize in aktwitches^), this optimization is
  1754. not performed (JM)
  1755. 26th September 1997:
  1756. * removed the "Var" in front of the parameters of InsertLLItem, which
  1757. had introduced the need for the temp var p1 (also removed) (JM)
  1758. * fixed a bug in FindLabel() that caused false positives in some
  1759. cases (JM)
  1760. * removed the unit systems from the uses clause because it isn't
  1761. needed anymore (it was needed for the label-removal procedure) (JM)
  1762. * adapted for 0.9.3 and 0.9.4 (still bugged) (JM)
  1763. 27th September 1997:
  1764. * fixed 0.9.3+ related bugs (JM)
  1765. * make peepholeopt optimize the code twice, because after the first
  1766. pass several labels can be removed (those unset by
  1767. GetFinalDestination) which sometimes allows extra optimizations
  1768. (not when (cs_littlesize in aktswitches^), because then
  1769. GetFinalDestination is never called)) (JM)
  1770. 1st October 1997:
  1771. * adapted to use with tp (tlabeltable too large and lines to long) (FK)
  1772. + removal of dead code (which sits between a jmp and the next label), also
  1773. sometimes allows some extra optimizations during the second pass (JM)
  1774. 2nd October 1997:
  1775. + successive conditional jumps reduced to one jump (JM)
  1776. 3rd October 1997:
  1777. * made FindLabel a little shorter&faster (JM)
  1778. * make peepholeopt always go through the code twice, because the dead
  1779. code removal can allow some extra optimizations (JM)
  1780. 10th October 1997:
  1781. * optimized remove_mov code a little (JM)
  1782. 12th October 1997:
  1783. * bugfixed remove_mov change (JM)
  1784. 20th October 1997:
  1785. * changed the combiTmpBoolnation of two adds (which replaced "shl 2, %reg")
  1786. to a "lea %reg, (,%reg,4)" if the register is 32 bit (JM)
  1787. 21th October 1997:
  1788. + change movzx to faster equivalents (not working) (thanks to Daniel
  1789. Mantoine for the initial idea) (JM)
  1790. 30th October 1997:
  1791. * found out that "shl $const, %reg" is a pairable instruction after
  1792. all and therefore removed the dual "add %reg, %reg" sequences (JM)
  1793. * replace "shl $3, %reg" with "lea %reg, (,%reg,8)" (JM)
  1794. 2nd November 1997:
  1795. * fixed movzx replacements (JM)
  1796. 3rd November 1997:
  1797. * some changes in the optimization logic to generate better PPro
  1798. code (JM)
  1799. * change two consecutive 16 bit immediatie pushes to one 32 bit push
  1800. (thanks to Synopsis for the suggestion) (JM)
  1801. 4th November 1997:
  1802. + replace some constant multiplies with lea sequences (suggestion from
  1803. Synopsis, Daniel Mantoine and Florian Klaempfl) (JM)
  1804. 5th November 1997:
  1805. * finally bugfixed sar/shl optimization and reactivated it (JM)
  1806. + some extra movzx optimizations (JM)
  1807. 6th November 1997:
  1808. + change shl/add/sub sequences to one lea instruction if possible (JM)
  1809. * bugfixed some imul replacements (JM)
  1810. 30th November 1997:
  1811. * merge two consecutive "and $const, %reg"'s to one statement (JM)
  1812. 5th December 1997:
  1813. + change "mov $0, %reg" to "xor %reg, %reg" (JM)
  1814. * adapted to TP (typecasted pointer to longint for comparisons
  1815. and one line too long) (JM)
  1816. }