aopt386.pas 87 KB

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