aopt386.pas 97 KB

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