aopt386.pas 93 KB

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