aopt386.pas 95 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931
  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
  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. (Opt_Processors < 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^.line := p^.line;
  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^.line:= p^.line;
  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 (Opt_Processors <= i486)
  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^.line := p^.line;
  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^.line := p^.line;
  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^.line := p^.line;
  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 (Opt_Processors <= i486) 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^.line := p^.line;
  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^.line := p^.line;
  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 (Opt_Processors <= i486)
  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^.line := p^.line;
  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^.line := p^.line;
  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^.line := p^.line;
  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. { Removes the second statement from
  845. mov %reg, mem
  846. mov mem, %reg }
  847. If (Pai386(hp1)^.op1t = Pai386(p)^.op2t) and
  848. (Pai386(hp1)^.op2t = Pai386(p)^.op1t)
  849. Then
  850. Begin
  851. If (Pai386(hp1)^.op2t = top_ref)
  852. Then
  853. TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op2^), TReference(Pai386(p)^.op1^))
  854. Else
  855. TmpBool1 := Pai386(hp1)^.op2 = Pai386(p)^.op1;
  856. If TmpBool1
  857. Then
  858. Begin
  859. If (Pai386(hp1)^.op1t = top_ref)
  860. Then
  861. TmpBool1 := RefsEqual(TReference(Pai386(hp1)^.op1^),
  862. TReference(Pai386(p)^.op2^))
  863. Else TmpBool1 := (Pai386(hp1)^.op1 = Pai386(p)^.op2);
  864. If TmpBool1 Then
  865. Begin
  866. { hp1 := pai(p^.next);}
  867. AsmL^.remove(hp1);
  868. Dispose(hp1,done);
  869. End;
  870. End
  871. Else
  872. Begin
  873. { hp1 := pai(p^.next^.next);}
  874. If GetNextInstruction(hp1, hp2) And
  875. (Pai386(p)^.op1t = top_ref) And
  876. (Pai386(p)^.op2t = top_reg) And
  877. (Pai386(hp1)^.op1t = top_reg) And
  878. (Pai386(hp1)^.op1 = Pai386(p)^.op2) And
  879. (Pai386(hp1)^.op2t = top_ref) And
  880. { Assigned(hp1) And}
  881. (Pai(hp2)^.typ = ait_instruction) And
  882. (Pai386(hp2)^._operator = A_MOV) And
  883. (Pai386(hp2)^.op2t = top_reg) And
  884. (Pai386(hp2)^.op1t = top_ref) And
  885. RefsEqual(TReference(Pai386(hp2)^.op1^),
  886. TReference(Pai386(hp1)^.op2^))
  887. Then
  888. If (TRegister(Pai386(p)^.op2) = R_EDI)
  889. Then
  890. { mov mem1, reg1
  891. mov reg1, mem2
  892. mov mem2, reg2
  893. to:
  894. mov mem1, reg2
  895. mov reg2, mem2}
  896. Begin
  897. Pai386(p)^.op2 := Pai386(hp2)^.op2;
  898. Pai386(hp1)^.op1 := Pai386(hp2)^.op2;
  899. AsmL^.Remove(hp2);
  900. Dispose(hp2,Done);
  901. End
  902. Else
  903. { mov mem1, esi
  904. mov esi, mem2
  905. mov mem2, reg2
  906. to:
  907. mov mem1, esi
  908. mov mem1, reg2
  909. mov esi, mem2}
  910. Begin
  911. Pai386(hp1)^.opxt := top_ref + top_reg shl 4;
  912. Pai386(hp1)^.op1 := Pai386(p)^.op2;
  913. TReference(Pai386(hp1)^.op1^) := TReference(Pai386(p)^.op1^);
  914. Pai386(hp1)^.op2 := Pai386(hp2)^.op2;
  915. Pai386(hp2)^.opxt := top_reg + top_ref shl 4;
  916. Pai386(hp2)^.op2 := Pai386(hp2)^.op1;
  917. Pai386(hp2)^.op1 := Pai386(p)^.op2;
  918. End;
  919. End;
  920. End
  921. Else
  922. (* { movl [mem1],reg1
  923. movl [mem1],reg2
  924. to:
  925. movl [mem1],reg1
  926. movl reg1,reg2 }
  927. If (Pai386(p)^.op1t = top_ref) and
  928. (Pai386(p)^.op2t = top_reg) and
  929. (Pai386(hp1)^.op1t = top_ref) and
  930. (Pai386(hp1)^.op2t = top_reg) and
  931. (Pai386(p)^.size = Pai386(hp1)^.size) and
  932. RefsEqual(TReference(Pai386(p)^.op1^),TReference(Pai386(hp1)^.op1^)) and
  933. (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).base) and
  934. (TRegister(Pai386(p)^.op2)<>TReference(Pai386(hp1)^.op1^).index) then
  935. Begin
  936. Dispose(PReference(Pai386(hp1)^.op1));
  937. Pai386(hp1)^.op1:=Pai386(p)^.op2;
  938. Pai386(hp1)^.opxt:=Top_reg+Top_reg shl 4;
  939. End
  940. Else*)
  941. { movl const1,[mem1]
  942. movl [mem1],reg1
  943. to:
  944. movl const1,reg1
  945. movl reg1,[mem1] }
  946. If (Pai386(p)^.op1t = top_const) and
  947. (Pai386(p)^.op2t = top_ref) and
  948. (Pai386(hp1)^.op1t = top_ref) and
  949. (Pai386(hp1)^.op2t = top_reg) and
  950. (Pai386(p)^.size = Pai386(hp1)^.size) and
  951. RefsEqual(TReference(Pai386(hp1)^.op1^),TReference(Pai386(p)^.op2^)) then
  952. Begin
  953. Pai386(hp1)^.op1:=Pai386(hp1)^.op2;
  954. Pai386(hp1)^.op2:=Pai386(p)^.op2;
  955. Pai386(hp1)^.opxt:=Top_reg+Top_ref shl 4;
  956. Pai386(p)^.op2:=Pai386(hp1)^.op1;
  957. Pai386(p)^.opxt:=Top_const+(top_reg shl 4);
  958. End
  959. End;
  960. {changes "mov $0, %reg" into "xor %reg, %reg"}
  961. If (Pai386(p)^.op1t = Top_Const) And
  962. (Pai386(p)^.op1 = Pointer(0)) And
  963. (Pai386(p)^.op2t = Top_Reg)
  964. Then
  965. Begin
  966. Pai386(p)^._operator := A_XOR;
  967. Pai386(p)^.opxt := Top_Reg+Top_reg shl 4;
  968. Pai386(p)^.op1 := Pai386(p)^.op2;
  969. End;
  970. End;
  971. A_MOVZX:
  972. Begin
  973. {removes superfluous And's after movzx's}
  974. If (Pai386(p)^.op2t = top_reg) And
  975. { Assigned(p^.next) And}
  976. GetNextInstruction(p, hp1) And
  977. (Pai(hp1)^.typ = ait_instruction) And
  978. (Pai386(hp1)^._operator = A_AND) And
  979. (Pai386(hp1)^.op1t = top_const) And
  980. (Pai386(hp1)^.op2t = top_reg) And
  981. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  982. Then
  983. Case Pai386(p)^.Size Of
  984. S_BL, S_BW:
  985. If (Longint(Pai386(hp1)^.op1) = $ff)
  986. Then
  987. Begin
  988. { hp1 := Pai(p^.next);}
  989. AsmL^.Remove(hp1);
  990. Dispose(hp1, Done);
  991. End;
  992. S_WL:
  993. If (Longint(Pai386(hp1)^.op1) = $ffff)
  994. Then
  995. Begin
  996. { hp1 := Pai(p^.next);}
  997. AsmL^.Remove(hp1);
  998. Dispose(hp1, Done);
  999. End;
  1000. End;
  1001. {changes some movzx constructs to faster synonims (all examples
  1002. are given with eax/ax, but are also valid for other registers)}
  1003. If (Pai386(p)^.op2t = top_reg) Then
  1004. If (Pai386(p)^.op1t = top_reg)
  1005. Then
  1006. Case Pai386(p)^.size of
  1007. S_BW:
  1008. Begin
  1009. If (TRegister(Pai386(p)^.op1) = Reg16ToReg8(TRegister(Pai386(p)^.op2))) And
  1010. Not(CS_LittleSize In AktSwitches)
  1011. Then
  1012. {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
  1013. Begin
  1014. Pai386(p)^._operator := A_AND;
  1015. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  1016. Longint(Pai386(p)^.op1) := $ff;
  1017. Pai386(p)^.Size := S_W
  1018. End
  1019. Else
  1020. If {Assigned(p^.next) And}
  1021. GetNextInstruction(p, hp1) And
  1022. (Pai(hp1)^.typ = ait_instruction) And
  1023. (Pai386(hp1)^._operator = A_AND) And
  1024. (Pai386(hp1)^.op1t = top_const) And
  1025. (Pai386(hp1)^.op2t = top_reg) And
  1026. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  1027. Then
  1028. {Change "movzbw %reg1, %reg2; andw $const, %reg2"
  1029. to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
  1030. Begin
  1031. Pai386(p)^._operator := A_MOV;
  1032. Pai386(p)^.Size := S_W;
  1033. Pai386(p)^.op1 := Pointer(Reg8ToReg16(TRegister(Pai386(p)^.op1)));
  1034. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
  1035. End;
  1036. End;
  1037. S_BL:
  1038. Begin
  1039. If (TRegister(Pai386(p)^.op1) = Reg32ToReg8(TRegister(Pai386(p)^.op2))) And
  1040. Not(CS_LittleSize in AktSwitches)
  1041. Then
  1042. {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
  1043. Begin
  1044. Pai386(p)^._operator := A_AND;
  1045. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  1046. Longint(Pai386(p)^.op1) := $ff;
  1047. Pai386(p)^.Size := S_L;
  1048. End
  1049. Else
  1050. If {Assigned(p^.next) And}
  1051. GetNextInstruction(p, hp1) And
  1052. (Pai(hp1)^.typ = ait_instruction) And
  1053. (Pai386(hp1)^._operator = A_AND) And
  1054. (Pai386(hp1)^.op1t = top_const) And
  1055. (Pai386(hp1)^.op2t = top_reg) And
  1056. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  1057. Then
  1058. {Change "movzbl %reg1, %reg2; andl $const, %reg2"
  1059. to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
  1060. Begin
  1061. Pai386(p)^._operator := A_MOV;
  1062. Pai386(p)^.Size := S_L;
  1063. Pai386(p)^.op1 := Pointer(Reg8ToReg32(TRegister(Pai386(p)^.op1)));
  1064. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ff);
  1065. End
  1066. Else
  1067. If IsGP32Reg(TRegister(Pai386(p)^.op2)) And
  1068. Not(CS_LittleSize in AktSwitches) And
  1069. (Opt_Processors >= Pentium) And
  1070. (Opt_Processors < PentiumPro)
  1071. Then
  1072. {Change "movzbl %reg1, %reg2" to
  1073. "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
  1074. PentiumMMX}
  1075. Begin
  1076. hp1 := New(Pai386, op_reg_reg(A_XOR, S_L,
  1077. TRegister(Pai386(p)^.op2),
  1078. TRegister(Pai386(p)^.op2)));
  1079. hp1^.line := p^.line;
  1080. InsertLLItem(p^.previous, p, hp1);
  1081. Pai386(p)^._operator := A_MOV;
  1082. Pai386(p)^.size := S_B;
  1083. Pai386(p)^.op2 :=
  1084. Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
  1085. InsertLLItem(p, p^.next, hp2);
  1086. End;
  1087. End;
  1088. S_WL:
  1089. Begin
  1090. If (TRegister(Pai386(p)^.op1) = Reg32ToReg16(TRegister(Pai386(p)^.op2))) And
  1091. Not(CS_LittleSize In AktSwitches)
  1092. Then
  1093. {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
  1094. Begin
  1095. Pai386(p)^._operator := A_AND;
  1096. Pai386(p)^.opxt := top_const+Top_reg shl 4;
  1097. Longint(Pai386(p)^.op1) := $ffff;
  1098. Pai386(p)^.Size := S_L
  1099. End
  1100. Else
  1101. If {Assigned(p^.next) And}
  1102. GetNextInstruction(p, hp1) And
  1103. (Pai(hp1)^.typ = ait_instruction) And
  1104. (Pai386(hp1)^._operator = A_AND) And
  1105. (Pai386(hp1)^.op1t = top_const) And
  1106. (Pai386(hp1)^.op2t = top_reg) And
  1107. (Pai386(hp1)^.op2 = Pai386(p)^.op2)
  1108. Then
  1109. {Change "movzwl %reg1, %reg2; andl $const, %reg2"
  1110. to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
  1111. Begin
  1112. Pai386(p)^._operator := A_MOV;
  1113. Pai386(p)^.Size := S_L;
  1114. Pai386(p)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(p)^.op1)));
  1115. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) And $ffff);
  1116. End;
  1117. End;
  1118. End
  1119. Else
  1120. If (Pai386(p)^.op1t = top_ref) Then
  1121. Begin
  1122. If (PReference(Pai386(p)^.op1)^.base <> TRegister(Pai386(p)^.op2)) And
  1123. (PReference(Pai386(p)^.op1)^.index <> TRegister(Pai386(p)^.op2)) And
  1124. Not(CS_LittleSize in AktSwitches) And
  1125. IsGP32Reg(TRegister(Pai386(p)^.op2)) And
  1126. (Opt_Processors >= Pentium) And
  1127. (Opt_Processors < PentiumPro) And
  1128. (Pai386(p)^.Size = S_BL)
  1129. Then
  1130. {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
  1131. Pentium and PentiumMMX}
  1132. Begin
  1133. hp1 := New(Pai386,op_reg_reg(A_XOR, S_L, TRegister(Pai386(p)^.op2),
  1134. TRegister(Pai386(p)^.op2)));
  1135. hp1^.line := p^.line;
  1136. Pai386(p)^._operator := A_MOV;
  1137. Pai386(p)^.size := S_B;
  1138. Pai386(p)^.op2 := Pointer(Reg32ToReg8(TRegister(Pai386(p)^.op2)));
  1139. InsertLLItem(p^.previous, p, hp1);
  1140. End
  1141. Else
  1142. If {Assigned(p^.next) And}
  1143. GetNextInstruction(p, hp1) And
  1144. (Pai(hp1)^.typ = ait_instruction) And
  1145. (Pai386(hp1)^._operator = A_AND) And
  1146. (Pai386(hp1)^.op1t = Top_Const) And
  1147. (Pai386(hp1)^.op2t = Top_Reg) And
  1148. (Pai386(hp1)^.op2 = Pai386(p)^.op2) Then
  1149. Begin
  1150. Pai386(p)^._operator := A_MOV;
  1151. Case Pai386(p)^.Size Of
  1152. S_BL:
  1153. Begin
  1154. Pai386(p)^.Size := S_L;
  1155. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  1156. And $ff);
  1157. End;
  1158. S_WL:
  1159. Begin
  1160. Pai386(p)^.Size := S_L;
  1161. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  1162. And $ffff);
  1163. End;
  1164. S_BW:
  1165. Begin
  1166. Pai386(p)^.Size := S_W;
  1167. Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1)
  1168. And $ff);
  1169. End;
  1170. End;
  1171. End;
  1172. End;
  1173. End;
  1174. A_POP:
  1175. Begin
  1176. if (Pai386(p)^.op1t = top_reg) And
  1177. { (assigned(p^.next)) and}
  1178. GetNextInstruction(p, hp1) And
  1179. (pai(hp1)^.typ=ait_instruction) and
  1180. (Pai386(hp1)^._operator=A_PUSH) and
  1181. (Pai386(hp1)^.op1t = top_reg) And
  1182. (Pai386(hp1)^.op1=Pai386(p)^.op1) then
  1183. begin
  1184. hp2:=pai(hp1^.next);
  1185. asml^.remove(p);
  1186. asml^.remove(hp1);
  1187. dispose(p,done);
  1188. dispose(hp1,done);
  1189. p:=hp2;
  1190. continue;
  1191. { Pai386(p)^._operator := A_MOV;
  1192. Pai386(p)^.op2 := Pai386(p)^.op1;
  1193. Pai386(p)^.opxt := top_ref + top_reg shl 4;
  1194. New(TmpRef);
  1195. TmpRef^.segment := R_DEFAULT_SEG;
  1196. TmpRef^.base := R_ESP;
  1197. TmpRef^.index := R_NO;
  1198. TmpRef^.scalefactor := 1;
  1199. TmpRef^.symbol := nil;
  1200. TmpRef^.isintvalue := false;
  1201. TmpRef^.offset := 0;
  1202. Pai386(p)^.op1 := Pointer(TmpRef);
  1203. hp1 := Pai(p^.next);
  1204. AsmL^.Remove(hp1);
  1205. Dispose(hp1, Done)}
  1206. end;
  1207. end;
  1208. A_PUSH:
  1209. Begin
  1210. If (Pai386(p)^.size = S_W) And
  1211. (Pai386(p)^.op1t = Top_Const) And
  1212. { Assigned(p^.next) And}
  1213. GetNextInstruction(p, hp1) And
  1214. (Pai(hp1)^.typ = ait_instruction) And
  1215. (Pai386(hp1)^._operator = A_PUSH) And
  1216. (Pai386(hp1)^.op1t = Top_Const) And
  1217. (Pai386(hp1)^.size = S_W) Then
  1218. Begin
  1219. { hp1 := Pai(p^.next);}
  1220. Pai386(p)^.Size := S_L;
  1221. Pai386(p)^.op1 := Pointer(Longint(Pai386(p)^.op1) shl 16 + Longint(Pai386(hp1)^.op1));
  1222. AsmL^.Remove(hp1);
  1223. Dispose(hp1, Done)
  1224. End;
  1225. End;
  1226. A_SHL, A_SAL:
  1227. Begin
  1228. If (Pai386(p)^.op1t = Top_Const) And
  1229. (Pai386(p)^.op2t = Top_Reg) And
  1230. (Pai386(p)^.Size = S_L) And
  1231. (Longint(Pai386(p)^.op1) <= 3)
  1232. {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
  1233. Then
  1234. Begin
  1235. TmpBool1 := True; {should we check the next instruction?}
  1236. TmpBool2 := False; {have we found an add/sub which could be
  1237. integrated in the lea?}
  1238. New(TmpRef);
  1239. TmpRef^.segment := R_DEFAULT_SEG;
  1240. TmpRef^.base := R_NO;
  1241. TmpRef^.index := TRegister(Pai386(p)^.op2);
  1242. TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
  1243. TmpRef^.symbol := nil;
  1244. TmpRef^.isintvalue := false;
  1245. TmpRef^.offset := 0;
  1246. While TmpBool1 And
  1247. { Assigned(p^.next) And}
  1248. GetNextInstruction(p, hp1) And
  1249. (Pai(hp1)^.typ = ait_instruction) And
  1250. ((Pai386(hp1)^._operator = A_ADD) Or
  1251. (Pai386(hp1)^._operator = A_SUB)) And
  1252. (Pai386(hp1)^.op2t = Top_Reg) And
  1253. (Pai386(hp1)^.op2 = Pai386(p)^.op2) Do
  1254. Begin
  1255. TmpBool1 := False;
  1256. If (Pai386(hp1)^.op1t = Top_Const)
  1257. Then
  1258. Begin
  1259. TmpBool1 := True;
  1260. TmpBool2 := True;
  1261. If Pai386(hp1)^._operator = A_ADD
  1262. Then Inc(TmpRef^.offset, Longint(Pai386(hp1)^.op1))
  1263. Else Dec(TmpRef^.offset, Longint(Pai386(hp1)^.op1));
  1264. { hp1 := Pai(p^.next);}
  1265. AsmL^.Remove(hp1);
  1266. Dispose(hp1, Done);
  1267. End
  1268. Else
  1269. If (Pai386(hp1)^.op1t = Top_Reg) And
  1270. (Pai386(hp1)^._operator = A_ADD) And
  1271. (TmpRef^.base = R_NO) Then
  1272. Begin
  1273. TmpBool1 := True;
  1274. TmpBool2 := True;
  1275. TmpRef^.base := TRegister(Pai386(hp1)^.op1);
  1276. { hp1 := Pai(p^.next);}
  1277. AsmL^.Remove(hp1);
  1278. Dispose(hp1, Done);
  1279. End;
  1280. End;
  1281. If TmpBool2 Or
  1282. ((Opt_Processors < PentiumPro) And
  1283. (Longint(Pai386(p)^.op1) <= 3) And
  1284. Not(CS_LittleSize in AktSwitches))
  1285. Then
  1286. Begin
  1287. If Not(TmpBool2) And
  1288. (Longint(Pai386(p)^.op1) = 1)
  1289. Then
  1290. Begin
  1291. Dispose(TmpRef);
  1292. hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
  1293. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)))
  1294. End
  1295. Else hp1 := New(Pai386, op_ref_reg(A_LEA, S_L, TmpRef,
  1296. TRegister(Pai386(p)^.op2)));
  1297. hp1^.line := p^.line;
  1298. InsertLLItem(p^.previous, p^.next, hp1);
  1299. Dispose(p, Done);
  1300. p := hp1;
  1301. End;
  1302. End
  1303. Else
  1304. If (Opt_Processors < PentiumPro) And
  1305. (Pai386(p)^.op1t = top_const) And
  1306. (Pai386(p)^.op2t = top_reg) Then
  1307. If (Longint(Pai386(p)^.op1) = 1)
  1308. Then
  1309. {changes "shl $1, %reg" to "add %reg, %reg", which
  1310. is the same on a 386, but faster on a 486, and pairable in both U and V
  1311. pipes on the Pentium (unlike shl, which is only pairable in the U pipe)}
  1312. Begin
  1313. hp1 := new(Pai386,op_reg_reg(A_ADD,Pai386(p)^.Size,
  1314. TRegister(Pai386(p)^.op2), TRegister(Pai386(p)^.op2)));
  1315. hp1^.line := p^.line;
  1316. InsertLLItem(p^.previous, p^.next, hp1);
  1317. Dispose(p, done);
  1318. p := hp1;
  1319. End
  1320. Else If (Pai386(p)^.size = S_L) and
  1321. (Longint(Pai386(p)^.op1) <= 3) Then
  1322. {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
  1323. "shl $3, %reg" to "lea (,%reg,8), %reg}
  1324. Begin
  1325. New(TmpRef);
  1326. TmpRef^.segment := R_DEFAULT_SEG;
  1327. TmpRef^.base := R_NO;
  1328. TmpRef^.index := TRegister(Pai386(p)^.op2);
  1329. TmpRef^.scalefactor := PowerOf2(Longint(Pai386(p)^.op1));
  1330. TmpRef^.symbol := nil;
  1331. TmpRef^.isintvalue := false;
  1332. TmpRef^.offset := 0;
  1333. hp1 := new(Pai386,op_ref_reg(A_LEA,S_L,TmpRef, TRegister(Pai386(p)^.op2)));
  1334. hp1^.line := p^.line;
  1335. InsertLLItem(p^.previous, p^.next, hp1);
  1336. Dispose(p, done);
  1337. p := hp1;
  1338. End
  1339. End;
  1340. A_SAR, A_SHR:
  1341. {changes the code sequence
  1342. shr/sar const1, %reg
  1343. shl const2, %reg
  1344. to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
  1345. Begin
  1346. { hp1 := pai(p^.next);}
  1347. If {Assigned(hp1) and}
  1348. GetNextInstruction(p, hp1) And
  1349. (pai(hp1)^.typ = ait_instruction) and
  1350. (Pai386(hp1)^._operator = A_SHL) and
  1351. (Pai386(p)^.op1t = top_const) and
  1352. (Pai386(hp1)^.op1t = top_const) Then
  1353. If (Longint(Pai386(p)^.op1) > Longint(Pai386(hp1)^.op1)) Then
  1354. If (Pai386(p)^.op2t = Top_reg) And
  1355. Not(CS_LittleSize In AktSwitches) And
  1356. ((Pai386(p)^.Size = S_B) Or
  1357. (Pai386(p)^.Size = S_L))
  1358. Then
  1359. Begin
  1360. Dec(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
  1361. Pai386(hp1)^._operator := A_And;
  1362. Pai386(hp1)^.op1 := Pointer(PowerOf2(Longint(Pai386(hp1)^.op1))-1);
  1363. If (Pai386(p)^.Size = S_L)
  1364. Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
  1365. Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1366. End
  1367. Else
  1368. If (Longint(Pai386(p)^.op1) < Longint(Pai386(hp1)^.op1)) Then
  1369. If (Pai386(p)^.op2t = Top_reg) And
  1370. Not(CS_LittleSize In AktSwitches) And
  1371. ((Pai386(p)^.Size = S_B) Or
  1372. (Pai386(p)^.Size = S_L))
  1373. Then
  1374. Begin
  1375. Dec(Longint(Pai386(hp1)^.op1), Longint(Pai386(p)^.op1));
  1376. Pai386(p)^._operator := A_And;
  1377. Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
  1378. If (Pai386(p)^.Size = S_L)
  1379. Then Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffffffff)
  1380. Else Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1381. End
  1382. Else
  1383. Begin
  1384. Pai386(p)^._operator := A_And;
  1385. Pai386(p)^.op1 := Pointer(PowerOf2(Longint(Pai386(p)^.op1))-1);
  1386. Case Pai386(p)^.Size Of
  1387. S_B: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ff);
  1388. S_W: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor $ffff);
  1389. S_L: Pai386(hp1)^.op1 := Pointer(Longint(Pai386(hp1)^.op1) Xor
  1390. $ffffffff);
  1391. End;
  1392. AsmL^.remove(hp1);
  1393. dispose(hp1, done);
  1394. End;
  1395. End;
  1396. A_SUB:
  1397. {change "subl $2, %esp; pushw x" to "pushl x"}
  1398. Begin
  1399. If (Pai386(p)^.op1t = top_const) And
  1400. (Longint(Pai386(p)^.op1) = 2) And
  1401. (Pai386(p)^.op2t = top_reg) And
  1402. (TRegister(Pai386(p)^.op2) = R_ESP)
  1403. Then
  1404. Begin
  1405. hp1 := Pai(p^.next);
  1406. While Assigned(hp1) And
  1407. (Pai(hp1)^.typ In [ait_instruction]+SkipInstr) And
  1408. Not((Pai(hp1)^.typ = ait_instruction) And
  1409. ((Pai386(hp1)^._operator = A_PUSH) or
  1410. ((Pai386(hp1)^._operator = A_MOV) And
  1411. (Pai386(hp1)^.op2t = top_ref) And
  1412. (TReference(Pai386(hp1)^.op2^).base = r_esp)))) do
  1413. hp1 := Pai(hp1^.next);
  1414. If Assigned(hp1) And
  1415. (Pai(hp1)^.typ = ait_instruction) And
  1416. (Pai386(hp1)^._operator = A_PUSH) And
  1417. (Pai386(hp1)^.Size = S_W)
  1418. Then
  1419. Begin
  1420. Pai386(hp1)^.size := S_L;
  1421. If (Pai386(hp1)^.op1t = top_reg) Then
  1422. Pai386(hp1)^.op1 := Pointer(Reg16ToReg32(TRegister(Pai386(hp1)^.op1)));
  1423. hp1 := Pai(p^.next);
  1424. AsmL^.Remove(p);
  1425. Dispose(p, Done);
  1426. p := hp1;
  1427. Continue
  1428. End
  1429. Else
  1430. If {Assigned(p^.previous) And}
  1431. GetLastInstruction(p, hp1) And
  1432. (Pai(hp1)^.typ = ait_instruction) And
  1433. (Pai386(hp1)^._operator = A_SUB) And
  1434. (Pai386(hp1)^.op1t = top_const) And
  1435. (Pai386(hp1)^.op2t = top_reg) And
  1436. (TRegister(Pai386(hp1)^.Op2) = R_ESP)
  1437. Then
  1438. Begin
  1439. { hp1 := Pai(p^.previous);}
  1440. Inc(Longint(Pai386(p)^.op1), Longint(Pai386(hp1)^.op1));
  1441. AsmL^.Remove(hp1);
  1442. Dispose(hp1, Done);
  1443. End;
  1444. End;
  1445. End;
  1446. A_TEST, A_OR:
  1447. {removes the line marked with (x) from the sequence
  1448. And/or/xor/add/sub/... $x, %y
  1449. test/or %y, %y (x)
  1450. j(n)z _Label
  1451. as the first instruction already adjusts the ZF}
  1452. Begin
  1453. If (Pai386(p)^.op1 = Pai386(p)^.op2) And
  1454. { (assigned(p^.previous)) And}
  1455. GetLastInstruction(p, hp1) And
  1456. (pai(hp1)^.typ = ait_instruction) Then
  1457. Case Pai386(hp1)^._operator Of
  1458. A_ADD, A_SUB, A_OR, A_XOR, A_AND, A_SHL, A_SHR:
  1459. Begin
  1460. If (Pai386(hp1)^.op2 = Pai386(p)^.op1) Then
  1461. Begin
  1462. hp1 := pai(p^.next);
  1463. asml^.remove(p);
  1464. dispose(p, done);
  1465. p := pai(hp1);
  1466. continue
  1467. End;
  1468. End;
  1469. A_DEC, A_INC, A_NEG:
  1470. Begin
  1471. If (Pai386(hp1)^.op1 = Pai386(p)^.op1) Then
  1472. Begin
  1473. hp1 := pai(p^.next);
  1474. asml^.remove(p);
  1475. dispose(p, done);
  1476. p := pai(hp1);
  1477. continue
  1478. End;
  1479. End
  1480. End;
  1481. End;
  1482. End;
  1483. End;
  1484. ait_label:
  1485. Begin
  1486. If Not(Pai_Label(p)^.l^.is_used)
  1487. Then
  1488. Begin
  1489. hp1 := Pai(p^.next);
  1490. AsmL^.Remove(p);
  1491. Dispose(p, Done);
  1492. p := hp1;
  1493. Continue
  1494. End;
  1495. End;
  1496. {$ifdef regalloc}
  1497. ait_regalloc: UsedRegs := UsedRegs + [PaiAlloc(p)^.Reg];
  1498. ait_regdealloc: UsedRegs := UsedRegs - [PaiAlloc(p)^.Reg];
  1499. {$endif regalloc}
  1500. End;
  1501. p:=pai(p^.next);
  1502. end;
  1503. end;
  1504. Procedure peepholeopt(AsmL : paasmoutput);
  1505. Procedure FindLoHiLabels;
  1506. {Walks through the paasmlist to find the lowest and highest label number;
  1507. Since 0.9.3: also removes unused labels}
  1508. Var LabelFound: Boolean;
  1509. P, hp1: Pai;
  1510. Begin
  1511. LabelFound := False;
  1512. LoLab := MaxLongint;
  1513. HiLab := 0;
  1514. p := Pai(AsmL^.first);
  1515. While Assigned(p) Do
  1516. Begin
  1517. If (Pai(p)^.typ = ait_label) Then
  1518. If (Pai_Label(p)^.l^.is_used)
  1519. Then
  1520. Begin
  1521. LabelFound := True;
  1522. If (Pai_Label(p)^.l^.nb < LoLab) Then
  1523. LoLab := Pai_Label(p)^.l^.nb;
  1524. If (Pai_Label(p)^.l^.nb > HiLab) Then
  1525. HiLab := Pai_Label(p)^.l^.nb;
  1526. End
  1527. Else
  1528. Begin
  1529. hp1 := pai(p^.next);
  1530. AsmL^.Remove(p);
  1531. Dispose(p, Done);
  1532. p := hp1;
  1533. continue;
  1534. End;
  1535. p := pai(p^.next);
  1536. End;
  1537. If LabelFound
  1538. Then LabDif := HiLab+1-LoLab
  1539. Else LabDif := 0;
  1540. End;
  1541. Procedure BuildLabelTable;
  1542. {Builds a table with the locations of the labels in the paasmoutput}
  1543. Var p: Pai;
  1544. Begin
  1545. If (LabDif <> 0) Then
  1546. Begin
  1547. {$IfDef TP}
  1548. If (MaxAvail >= LabDif*SizeOf(Pai))
  1549. Then
  1550. Begin
  1551. {$EndIf TP}
  1552. GetMem(LTable, LabDif*SizeOf(Pai));
  1553. FillChar(LTable^, LabDif*SizeOf(Pai), 0);
  1554. p := pai(AsmL^.first);
  1555. While Assigned(p) Do
  1556. Begin
  1557. If (Pai(p)^.typ = ait_label) Then
  1558. LTable^[Pai_Label(p)^.l^.nb-LoLab] := p;
  1559. p := pai(p^.next);
  1560. End;
  1561. {$IfDef TP}
  1562. End
  1563. Else LabDif := 0;
  1564. {$EndIf TP}
  1565. End;
  1566. End;
  1567. Begin
  1568. FindLoHiLabels;
  1569. BuildLabelTable;
  1570. DoOptimize(AsmL);
  1571. DoOptimize(AsmL);
  1572. If LabDif <> 0 Then Freemem(LTable, LabDif*SizeOf(Pai));
  1573. ReloadOpt(AsmL)
  1574. End;
  1575. End.
  1576. {
  1577. $Log$
  1578. Revision 1.10 1998-05-10 12:06:30 jonas
  1579. * bugfix in a_mov optimizations; completed bugfix of "sub $2,esp;...;movw reg, y(%esp)"
  1580. Revision 1.9 1998/05/06 08:38:34 pierre
  1581. * better position info with UseTokenInfo
  1582. UseTokenInfo greatly simplified
  1583. + added check for changed tree after first time firstpass
  1584. (if we could remove all the cases were it happen
  1585. we could skip all firstpass if firstpasscount > 1)
  1586. Only with ExtDebug
  1587. Revision 1.8 1998/04/29 10:33:43 pierre
  1588. + added some code for ansistring (not complete nor working yet)
  1589. * corrected operator overloading
  1590. * corrected nasm output
  1591. + started inline procedures
  1592. + added starstarn : use ** for exponentiation (^ gave problems)
  1593. + started UseTokenInfo cond to get accurate positions
  1594. Revision 1.7 1998/04/23 21:52:08 florian
  1595. * fixes of Jonas applied
  1596. Revision 1.6 1998/04/21 11:30:14 peter
  1597. * fixed $ifdef regalloc
  1598. Revision 1.5 1998/04/16 16:53:56 jonas
  1599. *** empty log message ***
  1600. Revision 1.4 1998/04/08 19:12:28 jonas
  1601. * fixed bug where "imul 12,reg" was replaced with a wrong lea sequence
  1602. Revision 1.3 1998/03/29 17:27:58 florian
  1603. * aopt386 compiles with TP
  1604. * correct line number is displayed, if a #0 is in the input
  1605. Revision 1.2 1998/03/28 23:09:53 florian
  1606. * secondin bugfix (m68k and i386)
  1607. * overflow checking bugfix (m68k and i386) -- pretty useless in
  1608. secondadd, since everything is done using 32-bit
  1609. * loading pointer to routines hopefully fixed (m68k)
  1610. * flags problem with calls to RTL internal routines fixed (still strcmp
  1611. to fix) (m68k)
  1612. * #ELSE was still incorrect (didn't take care of the previous level)
  1613. * problem with filenames in the command line solved
  1614. * problem with mangledname solved
  1615. * linking name problem solved (was case insensitive)
  1616. * double id problem and potential crash solved
  1617. * stop after first error
  1618. * and=>test problem removed
  1619. * correct read for all float types
  1620. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1621. * push/pop is now correct optimized (=> mov (%esp),reg)
  1622. Revision 1.1.1.1 1998/03/25 11:18:12 root
  1623. * Restored version
  1624. Revision 1.29 1998/03/24 21:48:29 florian
  1625. * just a couple of fixes applied:
  1626. - problem with fixed16 solved
  1627. - internalerror 10005 problem fixed
  1628. - patch for assembler reading
  1629. - small optimizer fix
  1630. - mem is now supported
  1631. Revision 1.28 1998/03/19 18:57:05 florian
  1632. * small fixes applied
  1633. Revision 1.27 1998/03/18 22:50:10 florian
  1634. + fstp/fld optimization
  1635. * routines which contains asm aren't longer optimzed
  1636. * wrong ifdef TEST_FUNCRET corrected
  1637. * wrong data generation for array[0..n] of char = '01234'; fixed
  1638. * bug0097 is fixed partial
  1639. * bug0116 fixed (-Og doesn't use enter of the stack frame is greater than
  1640. 65535)
  1641. Revision 1.26 1998/03/10 23:48:35 florian
  1642. * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
  1643. enough, it doesn't run
  1644. Revision 1.25 1998/03/10 01:17:14 peter
  1645. * all files have the same header
  1646. * messages are fully implemented, EXTDEBUG uses Comment()
  1647. + AG... files for the Assembler generation
  1648. Revision 1.24 1998/03/04 19:09:59 jonas
  1649. * fixed incompatibility with new code generator concerning "mov mem, reg; mov reg, edi" optimization
  1650. Revision 1.23 1998/03/03 22:37:09 peter
  1651. - uses errors
  1652. Revision 1.22 1998/03/03 14:48:31 jonas
  1653. * added errors to the uses clause (required for aopt386.inc)
  1654. Revision 1.21 1998/03/02 21:35:15 jonas
  1655. * added comments from last update
  1656. Revision 1.20 1998/03/02 21:29:04 jonas
  1657. * change "mov reg, mem; cmp x, mem" to "mov reg, mem; cmp x, reg"
  1658. * change "and x, reg; jxx" to "test reg, x; jxx" (also allows some extra reloading opts)
  1659. Revision 1.19 1998/03/02 01:47:58 peter
  1660. * renamed target_DOS to target_GO32V1
  1661. + new verbose system, merged old errors and verbose units into one new
  1662. verbose.pas, so errors.pas is obsolete
  1663. Revision 1.18 1998/02/27 16:33:26 florian
  1664. * syntax errors and line too long errors fixed
  1665. Revision 1.17 1998/02/26 17:20:31 jonas
  1666. * re-enabled mov optimizations, re-commented out the "mov mem, reg1; mov mem, reg2" optimization
  1667. Revision 1.16 1998/02/26 11:56:55 daniel
  1668. * New assembler optimizations commented out, because of bugs.
  1669. * Use of dir-/name- and extstr.
  1670. Revision 1.15 1998/02/25 14:08:30 daniel
  1671. * Compiler uses less memory. *FIX*
  1672. Revision 1.14 1998/02/25 12:32:12 daniel
  1673. * Compiler uses even less memory.
  1674. Revision 1.13 1998/02/24 21:18:12 jonas
  1675. * file name back to lower case
  1676. Revision 1.2 1998/02/24 20:32:11 jonas
  1677. * added comments from latest commit
  1678. Revision 1.1 1998/02/24 20:27:50 jonas
  1679. + change "cmp $0, reg" to "test reg, reg"
  1680. + add correct line numbers to Pai386 objects created by the optimizer
  1681. * dispose TReference of second instructions optimized from "mov mem, reg1; mov
  1682. mem, reg2" to "mov mem, reg; mov reg1, reg2"
  1683. + optimize "mov mem, reg1; mov reg1, reg2" to "mov mem, reg2" if reg1 <> esi
  1684. - disabled changing "mov mem, reg1; mov mem reg2" to "mov mem reg1; mov reg1,
  1685. reg2" because of conflict with the above optimization
  1686. + remove second instruction from "mov mem, reg; mov reg, %edi" because edi isn't
  1687. used anymore afterwards
  1688. + remove first instruction from "mov %eax, x(%ebp); leave/ret" because it is a
  1689. write to either a parameter or a temporary function result
  1690. + change "mov reg1, reg2; mov reg2, mem" to "mov reg1, mem" if reg2 <> esi
  1691. + change "mov reg1, reg2; test/or reg2, reg2; jxx" to "test/or reg1, reg1" if
  1692. reg2 <> esi
  1693. + change "mov reg1, reg2; test/or reg2, reg2" to "mov reg1, reg2; test/or reg1,
  1694. reg1" to avoid a read/write pnealty if reg2 = esi
  1695. * took FindLoHiLabel and BuildLabelTable out of the main loop, so they're both
  1696. called only once per code fragment that has to be optimized
  1697. Revision 1.12 1998/02/19 22:46:55 peter
  1698. * Fixed linebreaks
  1699. Revision 1.11 1998/02/13 10:34:32 daniel
  1700. * Made Motorola version compilable.
  1701. * Fixed optimizer
  1702. Revision 1.10 1998/02/12 17:18:51 florian
  1703. * fixed to get remake3 work, but needs additional fixes (output, I don't like
  1704. also that aktswitches isn't a pointer)
  1705. Revision 1.9 1998/02/12 11:49:39 daniel
  1706. Yes! Finally! After three retries, my patch!
  1707. Changes:
  1708. Complete rewrite of psub.pas.
  1709. Added support for DLL's.
  1710. Compiler requires less memory.
  1711. Platform units for each platform.
  1712. Revision 1.8 1998/02/10 21:57:21 peter
  1713. + mov [mem1],reg1;mov [mem1],reg2 -> mov [mem1],reg1;mov reg1,reg2
  1714. + mov const,[mem1];mov [mem1],reg -> mov const,reg;mov reg,[mem1]
  1715. Revision 1.7 1998/02/07 10:10:34 michael
  1716. + superfluous AND's after MOVZX' removed
  1717. + change "subl $2, %esp; ... ; pushw x" to "pushl x"
  1718. + fold "subl $const, %esp; subl $2, %esp" into one instruction
  1719. Revision 1.5 1998/02/02 17:25:43 jonas
  1720. * back to CVS version; change "lea (reg1), reg2" to "mov reg1, reg2"
  1721. Revision 1.2 1997/12/09 13:19:36 carl
  1722. + renamed pai_labeled --> pai_labeled
  1723. Revision 1.1.1.1 1997/11/27 08:32:50 michael
  1724. FPC Compiler CVS start
  1725. Pre-CVS log:
  1726. FK Florian Klampfl (FK)
  1727. JM Jonas Maebe
  1728. + feature added
  1729. - removed
  1730. * bug fixed or changed
  1731. History (started with version 0.9.0):
  1732. 5th november 1996:
  1733. * adapted to 0.9.0
  1734. 30th december 1996:
  1735. * runs with 0.9.1
  1736. 25th July 1996:
  1737. + removal of superfluous "test %reg, %reg" instructions (JM)
  1738. 28th July 1997:
  1739. + change "shl $1, %reg" to "add %reg, %reg" (not working) (JM)
  1740. * fixed bugs in test optimization (tested and working) (JM)
  1741. 29th July 1997:
  1742. * fixed some pointer bugs in SHL optimization, but it still doesn't
  1743. work :( (JM)
  1744. 30th July 1997:
  1745. + change "sar const1, %reg; shl const2, %reg" to one statement (JM)
  1746. * I finally correctly understand the structure of the pai(386)
  1747. object <g> and fixed the shl optimization (tested and working) (JM)
  1748. 31th July 1997:
  1749. + removal of some superfluous reloading of registers (not working) (JM)
  1750. 4th August 1997:
  1751. * fixed reloading optimization (thanks Florian!) (JM)
  1752. 6th August 1997:
  1753. + removal of labels which are not referenced by any instruction
  1754. (allows for easier and better optimization), but it is slow :( (JM)
  1755. 8th August 1997:
  1756. - removed label-removal procedure as it seems to be impossible to
  1757. find out if there are labels which are referenced through a jump
  1758. table (JM)
  1759. 15th August 1997:
  1760. + removal of superfluous "or %reg, %reg" instructions (JM)
  1761. 22th september 1997:
  1762. * test is also removed if it follows neg, shl and shr (FK)
  1763. - removed the sar/shl optimization because:
  1764. movl $0xff,%eax
  1765. shrl $0x3,%eax
  1766. shll $0x3,%eax
  1767. => EAX is $0xf8 !!! (FK)
  1768. 23th September 1997:
  1769. + function FindLabel() so sequences like "jmp l2;l1:;l2:" can be
  1770. optimized (JM)
  1771. 24th September 1997:
  1772. + successive jumps reduced to one jump (see explanation at
  1773. GetFinalDestination). Works fine, but seems to enlarge the code...
  1774. I suppose because there are more >128 bytes-jumps and their opcodes
  1775. are longer. If (cs_littlesize in aktwitches^), this optimization is
  1776. not performed (JM)
  1777. 26th September 1997:
  1778. * removed the "Var" in front of the parameters of InsertLLItem, which
  1779. had introduced the need for the temp var p1 (also removed) (JM)
  1780. * fixed a bug in FindLabel() that caused false positives in some
  1781. cases (JM)
  1782. * removed the unit systems from the uses clause because it isn't
  1783. needed anymore (it was needed for the label-removal procedure) (JM)
  1784. * adapted for 0.9.3 and 0.9.4 (still bugged) (JM)
  1785. 27th September 1997:
  1786. * fixed 0.9.3+ related bugs (JM)
  1787. * make peepholeopt optimize the code twice, because after the first
  1788. pass several labels can be removed (those unset by
  1789. GetFinalDestination) which sometimes allows extra optimizations
  1790. (not when (cs_littlesize in aktswitches^), because then
  1791. GetFinalDestination is never called)) (JM)
  1792. 1st October 1997:
  1793. * adapted to use with tp (tlabeltable too large and lines to long) (FK)
  1794. + removal of dead code (which sits between a jmp and the next label), also
  1795. sometimes allows some extra optimizations during the second pass (JM)
  1796. 2nd October 1997:
  1797. + successive conditional jumps reduced to one jump (JM)
  1798. 3rd October 1997:
  1799. * made FindLabel a little shorter&faster (JM)
  1800. * make peepholeopt always go through the code twice, because the dead
  1801. code removal can allow some extra optimizations (JM)
  1802. 10th October 1997:
  1803. * optimized remove_mov code a little (JM)
  1804. 12th October 1997:
  1805. * bugfixed remove_mov change (JM)
  1806. 20th October 1997:
  1807. * changed the combiTmpBoolnation of two adds (which replaced "shl 2, %reg")
  1808. to a "lea %reg, (,%reg,4)" if the register is 32 bit (JM)
  1809. 21th October 1997:
  1810. + change movzx to faster equivalents (not working) (thanks to Daniel
  1811. Mantoine for the initial idea) (JM)
  1812. 30th October 1997:
  1813. * found out that "shl $const, %reg" is a pairable instruction after
  1814. all and therefore removed the dual "add %reg, %reg" sequences (JM)
  1815. * replace "shl $3, %reg" with "lea %reg, (,%reg,8)" (JM)
  1816. 2nd November 1997:
  1817. * fixed movzx replacements (JM)
  1818. 3rd November 1997:
  1819. * some changes in the optimization logic to generate better PPro
  1820. code (JM)
  1821. * change two consecutive 16 bit immediatie pushes to one 32 bit push
  1822. (thanks to Synopsis for the suggestion) (JM)
  1823. 4th November 1997:
  1824. + replace some constant multiplies with lea sequences (suggestion from
  1825. Synopsis, Daniel Mantoine and Florian Klaempfl) (JM)
  1826. 5th November 1997:
  1827. * finally bugfixed sar/shl optimization and reactivated it (JM)
  1828. + some extra movzx optimizations (JM)
  1829. 6th November 1997:
  1830. + change shl/add/sub sequences to one lea instruction if possible (JM)
  1831. * bugfixed some imul replacements (JM)
  1832. 30th November 1997:
  1833. * merge two consecutive "and $const, %reg"'s to one statement (JM)
  1834. 5th December 1997:
  1835. + change "mov $0, %reg" to "xor %reg, %reg" (JM)
  1836. * adapted to TP (typecasted pointer to longint for comparisons
  1837. and one line too long) (JM)
  1838. }