aopt386.pas 92 KB

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