popt386.pas 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe
  4. This unit contains the peephole optimizer.
  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 popt386;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses Aasmbase,aasmtai,aasmcpu,verbose;
  22. procedure PrePeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
  23. procedure PeepHoleOptPass1(asml: taasmoutput; BlockStart, BlockEnd: tai);
  24. procedure PeepHoleOptPass2(asml: taasmoutput; BlockStart, BlockEnd: tai);
  25. procedure PostPeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
  26. implementation
  27. uses
  28. globtype,systems,
  29. globals,cgbase,procinfo,
  30. symsym,
  31. {$ifdef finaldestdebug}
  32. cobjects,
  33. {$endif finaldestdebug}
  34. cpuinfo,cpubase,cgutils,daopt386;
  35. function RegUsedAfterInstruction(reg: Tregister; p: tai; var UsedRegs: TRegSet): Boolean;
  36. var
  37. supreg: tsuperregister;
  38. begin
  39. supreg := getsupreg(reg);
  40. UpdateUsedRegs(UsedRegs, tai(p.Next));
  41. RegUsedAfterInstruction :=
  42. (supreg in UsedRegs) and
  43. (not(getNextInstruction(p,p)) or
  44. not(regLoadedWithNewValue(supreg,false,p)));
  45. end;
  46. function doFpuLoadStoreOpt(asmL: TAAsmoutput; var p: tai): boolean;
  47. { returns true if a "continue" should be done after this optimization }
  48. var hp1, hp2: tai;
  49. begin
  50. doFpuLoadStoreOpt := false;
  51. if (taicpu(p).oper[0]^.typ = top_ref) and
  52. getNextInstruction(p, hp1) and
  53. (hp1.typ = ait_instruction) and
  54. (((taicpu(hp1).opcode = A_FLD) and
  55. (taicpu(p).opcode = A_FSTP)) or
  56. ((taicpu(p).opcode = A_FISTP) and
  57. (taicpu(hp1).opcode = A_FILD))) and
  58. (taicpu(hp1).oper[0]^.typ = top_ref) and
  59. (taicpu(hp1).opsize = taicpu(p).opsize) and
  60. refsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
  61. begin
  62. { replacing fstp f;fld f by fst f is only valid for extended because of rounding }
  63. if (taicpu(p).opsize=S_FX) and
  64. getNextInstruction(hp1, hp2) and
  65. (hp2.typ = ait_instruction) and
  66. ((taicpu(hp2).opcode = A_LEAVE) or
  67. (taicpu(hp2).opcode = A_RET)) and
  68. (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
  69. not(assigned(current_procinfo.procdef.funcretsym) and
  70. (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
  71. (taicpu(p).oper[0]^.ref^.index = NR_NO) then
  72. begin
  73. asml.remove(p);
  74. asml.remove(hp1);
  75. p.free;
  76. hp1.free;
  77. p := hp2;
  78. removeLastDeallocForFuncRes(asmL, p);
  79. doFPULoadStoreOpt := true;
  80. end
  81. { can't be done because the store operation rounds
  82. else
  83. { fst can't store an extended value! }
  84. if (taicpu(p).opsize <> S_FX) and
  85. (taicpu(p).opsize <> S_IQ) then
  86. begin
  87. if (taicpu(p).opcode = A_FSTP) then
  88. taicpu(p).opcode := A_FST
  89. else taicpu(p).opcode := A_FIST;
  90. asml.remove(hp1);
  91. hp1.free;
  92. end
  93. }
  94. end;
  95. end;
  96. procedure PrePeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
  97. var
  98. p,hp1: tai;
  99. l: aint;
  100. tmpRef: treference;
  101. begin
  102. p := BlockStart;
  103. while (p <> BlockEnd) Do
  104. begin
  105. case p.Typ Of
  106. Ait_Instruction:
  107. begin
  108. case taicpu(p).opcode Of
  109. A_IMUL:
  110. {changes certain "imul const, %reg"'s to lea sequences}
  111. begin
  112. if (taicpu(p).oper[0]^.typ = Top_Const) and
  113. (taicpu(p).oper[1]^.typ = Top_Reg) and
  114. (taicpu(p).opsize = S_L) then
  115. if (taicpu(p).oper[0]^.val = 1) then
  116. if (taicpu(p).ops = 2) then
  117. {remove "imul $1, reg"}
  118. begin
  119. hp1 := tai(p.Next);
  120. asml.remove(p);
  121. p.free;
  122. p := hp1;
  123. continue;
  124. end
  125. else
  126. {change "imul $1, reg1, reg2" to "mov reg1, reg2"}
  127. begin
  128. hp1 := taicpu.Op_Reg_Reg(A_MOV, S_L, taicpu(p).oper[1]^.reg,taicpu(p).oper[2]^.reg);
  129. InsertLLItem(asml, p.previous, p.next, hp1);
  130. p.free;
  131. p := hp1;
  132. end
  133. else if
  134. ((taicpu(p).ops <= 2) or
  135. (taicpu(p).oper[2]^.typ = Top_Reg)) and
  136. (aktoptprocessor < ClassPentium2) and
  137. (taicpu(p).oper[0]^.val <= 12) and
  138. not(CS_LittleSize in aktglobalswitches) and
  139. (not(GetNextInstruction(p, hp1)) or
  140. {GetNextInstruction(p, hp1) and}
  141. not((tai(hp1).typ = ait_instruction) and
  142. ((taicpu(hp1).opcode=A_Jcc) and
  143. (taicpu(hp1).condition in [C_O,C_NO])))) then
  144. begin
  145. reference_reset(tmpref);
  146. case taicpu(p).oper[0]^.val Of
  147. 3: begin
  148. {imul 3, reg1, reg2 to
  149. lea (reg1,reg1,2), reg2
  150. imul 3, reg1 to
  151. lea (reg1,reg1,2), reg1}
  152. TmpRef.base := taicpu(p).oper[1]^.reg;
  153. TmpRef.index := taicpu(p).oper[1]^.reg;
  154. TmpRef.ScaleFactor := 2;
  155. if (taicpu(p).ops = 2) then
  156. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
  157. else
  158. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
  159. InsertLLItem(asml,p.previous, p.next, hp1);
  160. p.free;
  161. p := hp1;
  162. end;
  163. 5: begin
  164. {imul 5, reg1, reg2 to
  165. lea (reg1,reg1,4), reg2
  166. imul 5, reg1 to
  167. lea (reg1,reg1,4), reg1}
  168. TmpRef.base := taicpu(p).oper[1]^.reg;
  169. TmpRef.index := taicpu(p).oper[1]^.reg;
  170. TmpRef.ScaleFactor := 4;
  171. if (taicpu(p).ops = 2) then
  172. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
  173. else
  174. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
  175. InsertLLItem(asml,p.previous, p.next, hp1);
  176. p.free;
  177. p := hp1;
  178. end;
  179. 6: begin
  180. {imul 6, reg1, reg2 to
  181. lea (,reg1,2), reg2
  182. lea (reg2,reg1,4), reg2
  183. imul 6, reg1 to
  184. lea (reg1,reg1,2), reg1
  185. add reg1, reg1}
  186. if (aktoptprocessor <= Class386) then
  187. begin
  188. TmpRef.index := taicpu(p).oper[1]^.reg;
  189. if (taicpu(p).ops = 3) then
  190. begin
  191. TmpRef.base := taicpu(p).oper[2]^.reg;
  192. TmpRef.ScaleFactor := 4;
  193. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
  194. end
  195. else
  196. begin
  197. hp1 := taicpu.op_reg_reg(A_ADD, S_L,
  198. taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
  199. end;
  200. InsertLLItem(asml,p, p.next, hp1);
  201. reference_reset(tmpref);
  202. TmpRef.index := taicpu(p).oper[1]^.reg;
  203. TmpRef.ScaleFactor := 2;
  204. if (taicpu(p).ops = 3) then
  205. begin
  206. TmpRef.base := NR_NO;
  207. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
  208. taicpu(p).oper[2]^.reg);
  209. end
  210. else
  211. begin
  212. TmpRef.base := taicpu(p).oper[1]^.reg;
  213. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
  214. end;
  215. InsertLLItem(asml,p.previous, p.next, hp1);
  216. p.free;
  217. p := tai(hp1.next);
  218. end
  219. end;
  220. 9: begin
  221. {imul 9, reg1, reg2 to
  222. lea (reg1,reg1,8), reg2
  223. imul 9, reg1 to
  224. lea (reg1,reg1,8), reg1}
  225. TmpRef.base := taicpu(p).oper[1]^.reg;
  226. TmpRef.index := taicpu(p).oper[1]^.reg;
  227. TmpRef.ScaleFactor := 8;
  228. if (taicpu(p).ops = 2) then
  229. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg)
  230. else
  231. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
  232. InsertLLItem(asml,p.previous, p.next, hp1);
  233. p.free;
  234. p := hp1;
  235. end;
  236. 10: begin
  237. {imul 10, reg1, reg2 to
  238. lea (reg1,reg1,4), reg2
  239. add reg2, reg2
  240. imul 10, reg1 to
  241. lea (reg1,reg1,4), reg1
  242. add reg1, reg1}
  243. if (aktoptprocessor <= Class386) then
  244. begin
  245. if (taicpu(p).ops = 3) then
  246. hp1 := taicpu.op_reg_reg(A_ADD, S_L,
  247. taicpu(p).oper[2]^.reg,taicpu(p).oper[2]^.reg)
  248. else
  249. hp1 := taicpu.op_reg_reg(A_ADD, S_L,
  250. taicpu(p).oper[1]^.reg,taicpu(p).oper[1]^.reg);
  251. InsertLLItem(asml,p, p.next, hp1);
  252. TmpRef.base := taicpu(p).oper[1]^.reg;
  253. TmpRef.index := taicpu(p).oper[1]^.reg;
  254. TmpRef.ScaleFactor := 4;
  255. if (taicpu(p).ops = 3) then
  256. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg)
  257. else
  258. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
  259. InsertLLItem(asml,p.previous, p.next, hp1);
  260. p.free;
  261. p := tai(hp1.next);
  262. end
  263. end;
  264. 12: begin
  265. {imul 12, reg1, reg2 to
  266. lea (,reg1,4), reg2
  267. lea (,reg1,8) reg2
  268. imul 12, reg1 to
  269. lea (reg1,reg1,2), reg1
  270. lea (,reg1,4), reg1}
  271. if (aktoptprocessor <= Class386)
  272. then
  273. begin
  274. TmpRef.index := taicpu(p).oper[1]^.reg;
  275. if (taicpu(p).ops = 3) then
  276. begin
  277. TmpRef.base := taicpu(p).oper[2]^.reg;
  278. TmpRef.ScaleFactor := 8;
  279. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
  280. end
  281. else
  282. begin
  283. TmpRef.base := NR_NO;
  284. TmpRef.ScaleFactor := 4;
  285. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
  286. end;
  287. InsertLLItem(asml,p, p.next, hp1);
  288. reference_reset(tmpref);
  289. TmpRef.index := taicpu(p).oper[1]^.reg;
  290. if (taicpu(p).ops = 3) then
  291. begin
  292. TmpRef.base := NR_NO;
  293. TmpRef.ScaleFactor := 4;
  294. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[2]^.reg);
  295. end
  296. else
  297. begin
  298. TmpRef.base := taicpu(p).oper[1]^.reg;
  299. TmpRef.ScaleFactor := 2;
  300. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef, taicpu(p).oper[1]^.reg);
  301. end;
  302. InsertLLItem(asml,p.previous, p.next, hp1);
  303. p.free;
  304. p := tai(hp1.next);
  305. end
  306. end
  307. end;
  308. end;
  309. end;
  310. A_SAR, A_SHR:
  311. {changes the code sequence
  312. shr/sar const1, x
  313. shl const2, x
  314. to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
  315. begin
  316. if GetNextInstruction(p, hp1) and
  317. (tai(hp1).typ = ait_instruction) and
  318. (taicpu(hp1).opcode = A_SHL) and
  319. (taicpu(p).oper[0]^.typ = top_const) and
  320. (taicpu(hp1).oper[0]^.typ = top_const) and
  321. (taicpu(hp1).opsize = taicpu(p).opsize) and
  322. (taicpu(hp1).oper[1]^.typ = taicpu(p).oper[1]^.typ) and
  323. OpsEqual(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^) then
  324. if (taicpu(p).oper[0]^.val > taicpu(hp1).oper[0]^.val) and
  325. not(CS_LittleSize in aktglobalswitches) then
  326. { shr/sar const1, %reg
  327. shl const2, %reg
  328. with const1 > const2 }
  329. begin
  330. taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
  331. taicpu(hp1).opcode := A_AND;
  332. l := (1 shl (taicpu(hp1).oper[0]^.val)) - 1;
  333. case taicpu(p).opsize Of
  334. S_L: taicpu(hp1).LoadConst(0,l Xor aint($ffffffff));
  335. S_B: taicpu(hp1).LoadConst(0,l Xor $ff);
  336. S_W: taicpu(hp1).LoadConst(0,l Xor $ffff);
  337. end;
  338. end
  339. else if (taicpu(p).oper[0]^.val<taicpu(hp1).oper[0]^.val) and
  340. not(CS_LittleSize in aktglobalswitches) then
  341. { shr/sar const1, %reg
  342. shl const2, %reg
  343. with const1 < const2 }
  344. begin
  345. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val-taicpu(p).oper[0]^.val);
  346. taicpu(p).opcode := A_AND;
  347. l := (1 shl (taicpu(p).oper[0]^.val))-1;
  348. case taicpu(p).opsize Of
  349. S_L: taicpu(p).LoadConst(0,l Xor aint($ffffffff));
  350. S_B: taicpu(p).LoadConst(0,l Xor $ff);
  351. S_W: taicpu(p).LoadConst(0,l Xor $ffff);
  352. end;
  353. end
  354. else
  355. { shr/sar const1, %reg
  356. shl const2, %reg
  357. with const1 = const2 }
  358. if (taicpu(p).oper[0]^.val = taicpu(hp1).oper[0]^.val) then
  359. begin
  360. taicpu(p).opcode := A_AND;
  361. l := (1 shl (taicpu(p).oper[0]^.val))-1;
  362. case taicpu(p).opsize Of
  363. S_B: taicpu(p).LoadConst(0,l Xor $ff);
  364. S_W: taicpu(p).LoadConst(0,l Xor $ffff);
  365. S_L: taicpu(p).LoadConst(0,l Xor aint($ffffffff));
  366. end;
  367. asml.remove(hp1);
  368. hp1.free;
  369. end;
  370. end;
  371. A_XOR:
  372. if (taicpu(p).oper[0]^.typ = top_reg) and
  373. (taicpu(p).oper[1]^.typ = top_reg) and
  374. (taicpu(p).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  375. { temporarily change this to 'mov reg,0' to make it easier }
  376. { for the CSE. Will be changed back in pass 2 }
  377. begin
  378. taicpu(p).opcode := A_MOV;
  379. taicpu(p).loadconst(0,0);
  380. end;
  381. end;
  382. end;
  383. end;
  384. p := tai(p.next)
  385. end;
  386. end;
  387. procedure PeepHoleOptPass1(Asml: taasmoutput; BlockStart, BlockEnd: tai);
  388. {First pass of peepholeoptimizations}
  389. var
  390. l : longint;
  391. p,hp1,hp2 : tai;
  392. hp3,hp4: tai;
  393. TmpRef: TReference;
  394. UsedRegs, TmpUsedRegs: TRegSet;
  395. TmpBool1, TmpBool2: Boolean;
  396. function SkipLabels(hp: tai; var hp2: tai): boolean;
  397. {skips all labels and returns the next "real" instruction}
  398. begin
  399. while assigned(hp.next) and
  400. (tai(hp.next).typ in SkipInstr + [ait_label,ait_align]) Do
  401. hp := tai(hp.next);
  402. if assigned(hp.next) then
  403. begin
  404. SkipLabels := True;
  405. hp2 := tai(hp.next)
  406. end
  407. else
  408. begin
  409. hp2 := hp;
  410. SkipLabels := False
  411. end;
  412. end;
  413. function GetFinalDestination(asml: taasmoutput; hp: taicpu; level: longint): boolean;
  414. {traces sucessive jumps to their final destination and sets it, e.g.
  415. je l1 je l3
  416. <code> <code>
  417. l1: becomes l1:
  418. je l2 je l3
  419. <code> <code>
  420. l2: l2:
  421. jmp l3 jmp l3
  422. the level parameter denotes how deeep we have already followed the jump,
  423. to avoid endless loops with constructs such as "l5: ; jmp l5" }
  424. var p1, p2: tai;
  425. l: tasmlabel;
  426. function FindAnyLabel(hp: tai; var l: tasmlabel): Boolean;
  427. begin
  428. FindAnyLabel := false;
  429. while assigned(hp.next) and
  430. (tai(hp.next).typ in (SkipInstr+[ait_align])) Do
  431. hp := tai(hp.next);
  432. if assigned(hp.next) and
  433. (tai(hp.next).typ = ait_label) then
  434. begin
  435. FindAnyLabel := true;
  436. l := tai_label(hp.next).l;
  437. end
  438. end;
  439. begin
  440. GetfinalDestination := false;
  441. if level > 20 then
  442. exit;
  443. p1 := dfa.getlabelwithsym(tasmlabel(hp.oper[0]^.ref^.symbol));
  444. if assigned(p1) then
  445. begin
  446. SkipLabels(p1,p1);
  447. if (tai(p1).typ = ait_instruction) and
  448. (taicpu(p1).is_jmp) then
  449. if { the next instruction after the label where the jump hp arrives}
  450. { is unconditional or of the same type as hp, so continue }
  451. (taicpu(p1).condition in [C_None,hp.condition]) or
  452. { the next instruction after the label where the jump hp arrives}
  453. { is the opposite of hp (so this one is never taken), but after }
  454. { that one there is a branch that will be taken, so perform a }
  455. { little hack: set p1 equal to this instruction (that's what the}
  456. { last SkipLabels is for, only works with short bool evaluation)}
  457. ((taicpu(p1).condition = inverse_cond[hp.condition]) and
  458. SkipLabels(p1,p2) and
  459. (p2.typ = ait_instruction) and
  460. (taicpu(p2).is_jmp) and
  461. (taicpu(p2).condition in [C_None,hp.condition]) and
  462. SkipLabels(p1,p1)) then
  463. begin
  464. { quick check for loops of the form "l5: ; jmp l5 }
  465. if (tasmlabel(taicpu(p1).oper[0]^.ref^.symbol).labelnr =
  466. tasmlabel(hp.oper[0]^.ref^.symbol).labelnr) then
  467. exit;
  468. if not GetFinalDestination(asml, taicpu(p1),succ(level)) then
  469. exit;
  470. tasmlabel(hp.oper[0]^.ref^.symbol).decrefs;
  471. hp.oper[0]^.ref^.symbol:=taicpu(p1).oper[0]^.ref^.symbol;
  472. tasmlabel(hp.oper[0]^.ref^.symbol).increfs;
  473. end
  474. else
  475. if (taicpu(p1).condition = inverse_cond[hp.condition]) then
  476. if not FindAnyLabel(p1,l) then
  477. begin
  478. {$ifdef finaldestdebug}
  479. insertllitem(asml,p1,p1.next,tai_comment.Create(
  480. strpnew('previous label inserted'))));
  481. {$endif finaldestdebug}
  482. objectlibrary.getlabel(l);
  483. insertllitem(asml,p1,p1.next,tai_label.Create(l));
  484. tasmlabel(taicpu(hp).oper[0]^.ref^.symbol).decrefs;
  485. hp.oper[0]^.ref^.symbol := l;
  486. l.increfs;
  487. { this won't work, since the new label isn't in the labeltable }
  488. { so it will fail the rangecheck. Labeltable should become a }
  489. { hashtable to support this: }
  490. { GetFinalDestination(asml, hp); }
  491. end
  492. else
  493. begin
  494. {$ifdef finaldestdebug}
  495. insertllitem(asml,p1,p1.next,tai_comment.Create(
  496. strpnew('next label reused'))));
  497. {$endif finaldestdebug}
  498. l.increfs;
  499. hp.oper[0]^.ref^.symbol := l;
  500. if not GetFinalDestination(asml, hp,succ(level)) then
  501. exit;
  502. end;
  503. end;
  504. GetFinalDestination := true;
  505. end;
  506. function DoSubAddOpt(var p: tai): Boolean;
  507. begin
  508. DoSubAddOpt := False;
  509. if GetLastInstruction(p, hp1) and
  510. (hp1.typ = ait_instruction) and
  511. (taicpu(hp1).opsize = taicpu(p).opsize) then
  512. case taicpu(hp1).opcode Of
  513. A_DEC:
  514. if (taicpu(hp1).oper[0]^.typ = top_reg) and
  515. (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  516. begin
  517. taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val+1);
  518. asml.remove(hp1);
  519. hp1.free;
  520. end;
  521. A_SUB:
  522. if (taicpu(hp1).oper[0]^.typ = top_const) and
  523. (taicpu(hp1).oper[1]^.typ = top_reg) and
  524. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  525. begin
  526. taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val+taicpu(hp1).oper[0]^.val);
  527. asml.remove(hp1);
  528. hp1.free;
  529. end;
  530. A_ADD:
  531. if (taicpu(hp1).oper[0]^.typ = top_const) and
  532. (taicpu(hp1).oper[1]^.typ = top_reg) and
  533. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  534. begin
  535. taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val-taicpu(hp1).oper[0]^.val);
  536. asml.remove(hp1);
  537. hp1.free;
  538. if (taicpu(p).oper[0]^.val = 0) then
  539. begin
  540. hp1 := tai(p.next);
  541. asml.remove(p);
  542. p.free;
  543. if not GetLastInstruction(hp1, p) then
  544. p := hp1;
  545. DoSubAddOpt := True;
  546. end
  547. end;
  548. end;
  549. end;
  550. begin
  551. p := BlockStart;
  552. UsedRegs := [];
  553. while (p <> BlockEnd) Do
  554. begin
  555. UpDateUsedRegs(UsedRegs, tai(p.next));
  556. case p.Typ Of
  557. ait_instruction:
  558. begin
  559. { Handle Jmp Optimizations }
  560. if taicpu(p).is_jmp then
  561. begin
  562. {the following if-block removes all code between a jmp and the next label,
  563. because it can never be executed}
  564. if (taicpu(p).opcode = A_JMP) then
  565. begin
  566. while GetNextInstruction(p, hp1) and
  567. (hp1.typ <> ait_label) do
  568. if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
  569. begin
  570. asml.remove(hp1);
  571. hp1.free;
  572. end
  573. else break;
  574. end;
  575. { remove jumps to a label coming right after them }
  576. if GetNextInstruction(p, hp1) then
  577. begin
  578. if FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp1) and
  579. {$warning FIXME removing the first instruction fails}
  580. (p<>blockstart) then
  581. begin
  582. hp2:=tai(hp1.next);
  583. asml.remove(p);
  584. p.free;
  585. p:=hp2;
  586. continue;
  587. end
  588. else
  589. begin
  590. if hp1.typ = ait_label then
  591. SkipLabels(hp1,hp1);
  592. if (tai(hp1).typ=ait_instruction) and
  593. (taicpu(hp1).opcode=A_JMP) and
  594. GetNextInstruction(hp1, hp2) and
  595. FindLabel(tasmlabel(taicpu(p).oper[0]^.ref^.symbol), hp2) then
  596. begin
  597. if taicpu(p).opcode=A_Jcc then
  598. begin
  599. taicpu(p).condition:=inverse_cond[taicpu(p).condition];
  600. tai_label(hp2).l.decrefs;
  601. taicpu(p).oper[0]^.ref^.symbol:=taicpu(hp1).oper[0]^.ref^.symbol;
  602. taicpu(p).oper[0]^.ref^.symbol.increfs;
  603. asml.remove(hp1);
  604. hp1.free;
  605. GetFinalDestination(asml, taicpu(p),0);
  606. end
  607. else
  608. begin
  609. GetFinalDestination(asml, taicpu(p),0);
  610. p:=tai(p.next);
  611. continue;
  612. end;
  613. end
  614. else
  615. GetFinalDestination(asml, taicpu(p),0);
  616. end;
  617. end;
  618. end
  619. else
  620. { All other optimizes }
  621. begin
  622. for l := 0 to taicpu(p).ops-1 Do
  623. if (taicpu(p).oper[l]^.typ = top_ref) then
  624. With taicpu(p).oper[l]^.ref^ Do
  625. begin
  626. if (base = NR_NO) and
  627. (index <> NR_NO) and
  628. (scalefactor in [0,1]) then
  629. begin
  630. base := index;
  631. index := NR_NO
  632. end
  633. end;
  634. case taicpu(p).opcode Of
  635. A_AND:
  636. begin
  637. if (taicpu(p).oper[0]^.typ = top_const) and
  638. (taicpu(p).oper[1]^.typ = top_reg) and
  639. GetNextInstruction(p, hp1) and
  640. (tai(hp1).typ = ait_instruction) and
  641. (taicpu(hp1).opcode = A_AND) and
  642. (taicpu(hp1).oper[0]^.typ = top_const) and
  643. (taicpu(hp1).oper[1]^.typ = top_reg) and
  644. (taicpu(p).oper[1]^.reg = taicpu(hp1).oper[1]^.reg) then
  645. {change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
  646. begin
  647. taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val and taicpu(hp1).oper[0]^.val);
  648. asml.remove(hp1);
  649. hp1.free;
  650. end
  651. else
  652. {change "and x, reg; jxx" to "test x, reg", if reg is deallocated before the
  653. jump, but only if it's a conditional jump (PFV) }
  654. if (taicpu(p).oper[1]^.typ = top_reg) and
  655. GetNextInstruction(p, hp1) and
  656. (hp1.typ = ait_instruction) and
  657. (taicpu(hp1).is_jmp) and
  658. (taicpu(hp1).opcode<>A_JMP) and
  659. not(getsupreg(taicpu(p).oper[1]^.reg) in UsedRegs) then
  660. taicpu(p).opcode := A_TEST;
  661. end;
  662. A_CMP:
  663. begin
  664. if (taicpu(p).oper[0]^.typ = top_const) and
  665. (taicpu(p).oper[1]^.typ in [top_reg,top_ref]) and
  666. (taicpu(p).oper[0]^.val = 0) and
  667. GetNextInstruction(p, hp1) and
  668. (hp1.typ = ait_instruction) and
  669. (taicpu(hp1).is_jmp) and
  670. (taicpu(hp1).opcode=A_Jcc) and
  671. (taicpu(hp1).condition in [C_LE,C_BE]) and
  672. GetNextInstruction(hp1,hp2) and
  673. (hp2.typ = ait_instruction) and
  674. (taicpu(hp2).opcode = A_DEC) and
  675. OpsEqual(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^) and
  676. GetNextInstruction(hp2, hp3) and
  677. (hp3.typ = ait_instruction) and
  678. (taicpu(hp3).is_jmp) and
  679. (taicpu(hp3).opcode = A_JMP) and
  680. GetNextInstruction(hp3, hp4) and
  681. FindLabel(tasmlabel(taicpu(hp1).oper[0]^.ref^.symbol),hp4) then
  682. begin
  683. taicpu(hp2).Opcode := A_SUB;
  684. taicpu(hp2).Loadoper(1,taicpu(hp2).oper[0]^);
  685. taicpu(hp2).LoadConst(0,1);
  686. taicpu(hp2).ops:=2;
  687. taicpu(hp3).Opcode := A_Jcc;
  688. case taicpu(hp1).condition of
  689. C_LE: taicpu(hp3).condition := C_GE;
  690. C_BE: taicpu(hp3).condition := C_AE;
  691. end;
  692. asml.remove(p);
  693. asml.remove(hp1);
  694. p.free;
  695. hp1.free;
  696. p := hp2;
  697. continue;
  698. end
  699. end;
  700. A_FLD:
  701. begin
  702. if (taicpu(p).oper[0]^.typ = top_reg) and
  703. GetNextInstruction(p, hp1) and
  704. (hp1.typ = Ait_Instruction) and
  705. (taicpu(hp1).oper[0]^.typ = top_reg) and
  706. (taicpu(hp1).oper[1]^.typ = top_reg) and
  707. (taicpu(hp1).oper[0]^.reg = NR_ST) and
  708. (taicpu(hp1).oper[1]^.reg = NR_ST1) then
  709. { change to
  710. fld reg fxxx reg,st
  711. fxxxp st, st1 (hp1)
  712. Remark: non commutative operations must be reversed!
  713. }
  714. begin
  715. case taicpu(hp1).opcode Of
  716. A_FMULP,A_FADDP,
  717. A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
  718. begin
  719. case taicpu(hp1).opcode Of
  720. A_FADDP: taicpu(hp1).opcode := A_FADD;
  721. A_FMULP: taicpu(hp1).opcode := A_FMUL;
  722. A_FSUBP: taicpu(hp1).opcode := A_FSUBR;
  723. A_FSUBRP: taicpu(hp1).opcode := A_FSUB;
  724. A_FDIVP: taicpu(hp1).opcode := A_FDIVR;
  725. A_FDIVRP: taicpu(hp1).opcode := A_FDIV;
  726. end;
  727. taicpu(hp1).oper[0]^.reg := taicpu(p).oper[0]^.reg;
  728. taicpu(hp1).oper[1]^.reg := NR_ST;
  729. asml.remove(p);
  730. p.free;
  731. p := hp1;
  732. continue;
  733. end;
  734. end;
  735. end
  736. else
  737. if (taicpu(p).oper[0]^.typ = top_ref) and
  738. GetNextInstruction(p, hp2) and
  739. (hp2.typ = Ait_Instruction) and
  740. (taicpu(hp2).ops = 2) and
  741. (taicpu(hp2).oper[0]^.typ = top_reg) and
  742. (taicpu(hp2).oper[1]^.typ = top_reg) and
  743. (taicpu(p).opsize in [S_FS, S_FL]) and
  744. (taicpu(hp2).oper[0]^.reg = NR_ST) and
  745. (taicpu(hp2).oper[1]^.reg = NR_ST1) then
  746. if GetLastInstruction(p, hp1) and
  747. (hp1.typ = Ait_Instruction) and
  748. ((taicpu(hp1).opcode = A_FLD) or
  749. (taicpu(hp1).opcode = A_FST)) and
  750. (taicpu(hp1).opsize = taicpu(p).opsize) and
  751. (taicpu(hp1).oper[0]^.typ = top_ref) and
  752. RefsEqual(taicpu(p).oper[0]^.ref^, taicpu(hp1).oper[0]^.ref^) then
  753. if ((taicpu(hp2).opcode = A_FMULP) or
  754. (taicpu(hp2).opcode = A_FADDP)) then
  755. { change to
  756. fld/fst mem1 (hp1) fld/fst mem1
  757. fld mem1 (p) fadd/
  758. faddp/ fmul st, st
  759. fmulp st, st1 (hp2) }
  760. begin
  761. asml.remove(p);
  762. p.free;
  763. p := hp1;
  764. if (taicpu(hp2).opcode = A_FADDP) then
  765. taicpu(hp2).opcode := A_FADD
  766. else
  767. taicpu(hp2).opcode := A_FMUL;
  768. taicpu(hp2).oper[1]^.reg := NR_ST;
  769. end
  770. else
  771. { change to
  772. fld/fst mem1 (hp1) fld/fst mem1
  773. fld mem1 (p) fld st}
  774. begin
  775. taicpu(p).changeopsize(S_FL);
  776. taicpu(p).loadreg(0,NR_ST);
  777. end
  778. else
  779. begin
  780. case taicpu(hp2).opcode Of
  781. A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
  782. { change to
  783. fld/fst mem1 (hp1) fld/fst mem1
  784. fld mem2 (p) fxxx mem2
  785. fxxxp st, st1 (hp2) }
  786. begin
  787. case taicpu(hp2).opcode Of
  788. A_FADDP: taicpu(p).opcode := A_FADD;
  789. A_FMULP: taicpu(p).opcode := A_FMUL;
  790. A_FSUBP: taicpu(p).opcode := A_FSUBR;
  791. A_FSUBRP: taicpu(p).opcode := A_FSUB;
  792. A_FDIVP: taicpu(p).opcode := A_FDIVR;
  793. A_FDIVRP: taicpu(p).opcode := A_FDIV;
  794. end;
  795. asml.remove(hp2);
  796. hp2.free;
  797. end
  798. end
  799. end
  800. end;
  801. A_FSTP,A_FISTP:
  802. if doFpuLoadStoreOpt(asmL,p) then
  803. continue;
  804. A_LEA:
  805. begin
  806. {removes seg register prefixes from LEA operations, as they
  807. don't do anything}
  808. taicpu(p).oper[0]^.ref^.Segment := NR_NO;
  809. {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
  810. if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
  811. (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX..RS_ESP]) and
  812. (taicpu(p).oper[0]^.ref^.index = NR_NO) and
  813. (not(Assigned(taicpu(p).oper[0]^.ref^.Symbol))) then
  814. if (taicpu(p).oper[0]^.ref^.base <> taicpu(p).oper[1]^.reg) and
  815. (taicpu(p).oper[0]^.ref^.offset = 0) then
  816. begin
  817. hp1 := taicpu.op_reg_reg(A_MOV, S_L,taicpu(p).oper[0]^.ref^.base,
  818. taicpu(p).oper[1]^.reg);
  819. InsertLLItem(asml,p.previous,p.next, hp1);
  820. p.free;
  821. p := hp1;
  822. continue;
  823. end
  824. else if (taicpu(p).oper[0]^.ref^.offset = 0) then
  825. begin
  826. hp1 := tai(p.Next);
  827. asml.remove(p);
  828. p.free;
  829. p := hp1;
  830. continue;
  831. end
  832. else
  833. with taicpu(p).oper[0]^.ref^ do
  834. if (base = taicpu(p).oper[1]^.reg) then
  835. begin
  836. l := offset;
  837. if (l=1) then
  838. begin
  839. taicpu(p).opcode := A_INC;
  840. taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
  841. taicpu(p).ops := 1
  842. end
  843. else if (l=-1) then
  844. begin
  845. taicpu(p).opcode := A_DEC;
  846. taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
  847. taicpu(p).ops := 1;
  848. end
  849. else
  850. begin
  851. taicpu(p).opcode := A_ADD;
  852. taicpu(p).loadconst(0,l);
  853. end;
  854. end;
  855. end;
  856. A_MOV:
  857. begin
  858. TmpUsedRegs := UsedRegs;
  859. if (taicpu(p).oper[1]^.typ = top_reg) and
  860. (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX, RS_EBX, RS_ECX, RS_EDX, RS_ESI, RS_EDI]) and
  861. GetNextInstruction(p, hp1) and
  862. (tai(hp1).typ = ait_instruction) and
  863. (taicpu(hp1).opcode = A_MOV) and
  864. (taicpu(hp1).oper[0]^.typ = top_reg) and
  865. (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  866. begin
  867. {we have "mov x, %treg; mov %treg, y}
  868. if not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs)) then
  869. {we've got "mov x, %treg; mov %treg, y; with %treg is not used after }
  870. case taicpu(p).oper[0]^.typ Of
  871. top_reg:
  872. begin
  873. { change "mov %reg, %treg; mov %treg, y"
  874. to "mov %reg, y" }
  875. taicpu(p).LoadOper(1,taicpu(hp1).oper[1]^);
  876. asml.remove(hp1);
  877. hp1.free;
  878. continue;
  879. end;
  880. top_ref:
  881. if (taicpu(hp1).oper[1]^.typ = top_reg) then
  882. begin
  883. { change "mov mem, %treg; mov %treg, %reg"
  884. to "mov mem, %reg" }
  885. taicpu(p).Loadoper(1,taicpu(hp1).oper[1]^);
  886. asml.remove(hp1);
  887. hp1.free;
  888. continue;
  889. end;
  890. end
  891. end
  892. else
  893. {Change "mov %reg1, %reg2; xxx %reg2, ???" to
  894. "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
  895. penalty}
  896. if (taicpu(p).oper[0]^.typ = top_reg) and
  897. (taicpu(p).oper[1]^.typ = top_reg) and
  898. GetNextInstruction(p,hp1) and
  899. (tai(hp1).typ = ait_instruction) and
  900. (taicpu(hp1).ops >= 1) and
  901. (taicpu(hp1).oper[0]^.typ = top_reg) and
  902. (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) then
  903. {we have "mov %reg1, %reg2; XXX %reg2, ???"}
  904. begin
  905. if ((taicpu(hp1).opcode = A_OR) or
  906. (taicpu(hp1).opcode = A_TEST)) and
  907. (taicpu(hp1).oper[1]^.typ = top_reg) and
  908. (taicpu(hp1).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) then
  909. {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
  910. begin
  911. TmpUsedRegs := UsedRegs;
  912. { reg1 will be used after the first instruction, }
  913. { so update the allocation info }
  914. allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
  915. if GetNextInstruction(hp1, hp2) and
  916. (hp2.typ = ait_instruction) and
  917. taicpu(hp2).is_jmp and
  918. not(RegUsedAfterInstruction(taicpu(hp1).oper[0]^.reg, hp1, TmpUsedRegs)) then
  919. { change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
  920. "test %reg1, %reg1; jxx" }
  921. begin
  922. taicpu(hp1).Loadoper(0,taicpu(p).oper[0]^);
  923. taicpu(hp1).Loadoper(1,taicpu(p).oper[0]^);
  924. asml.remove(p);
  925. p.free;
  926. p := hp1;
  927. continue
  928. end
  929. else
  930. {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
  931. "mov %reg1, %reg2; test/or %reg1, %reg1"}
  932. begin
  933. taicpu(hp1).Loadoper(0,taicpu(p).oper[0]^);
  934. taicpu(hp1).Loadoper(1,taicpu(p).oper[0]^);
  935. end;
  936. end
  937. { else
  938. if (taicpu(p.next)^.opcode
  939. in [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
  940. {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
  941. "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
  942. end
  943. else
  944. {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
  945. x >= RetOffset) as it doesn't do anything (it writes either to a
  946. parameter or to the temporary storage room for the function
  947. result)}
  948. if GetNextInstruction(p, hp1) and
  949. (tai(hp1).typ = ait_instruction) then
  950. if ((taicpu(hp1).opcode = A_LEAVE) or
  951. (taicpu(hp1).opcode = A_RET)) and
  952. (taicpu(p).oper[1]^.typ = top_ref) and
  953. (taicpu(p).oper[1]^.ref^.base = current_procinfo.FramePointer) and
  954. not(assigned(current_procinfo.procdef.funcretsym) and
  955. (taicpu(p).oper[1]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
  956. (taicpu(p).oper[1]^.ref^.index = NR_NO) and
  957. (taicpu(p).oper[0]^.typ = top_reg) then
  958. begin
  959. asml.remove(p);
  960. p.free;
  961. p := hp1;
  962. RemoveLastDeallocForFuncRes(asmL,p);
  963. end
  964. else
  965. if (taicpu(p).oper[0]^.typ = top_reg) and
  966. (taicpu(p).oper[1]^.typ = top_ref) and
  967. (taicpu(p).opsize = taicpu(hp1).opsize) and
  968. (taicpu(hp1).opcode = A_CMP) and
  969. (taicpu(hp1).oper[1]^.typ = top_ref) and
  970. RefsEqual(taicpu(p).oper[1]^.ref^, taicpu(hp1).oper[1]^.ref^) then
  971. {change "mov reg1, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
  972. begin
  973. taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
  974. allocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
  975. end;
  976. { Next instruction is also a MOV ? }
  977. if GetNextInstruction(p, hp1) and
  978. (tai(hp1).typ = ait_instruction) and
  979. (taicpu(hp1).opcode = A_MOV) and
  980. (taicpu(hp1).opsize = taicpu(p).opsize) then
  981. begin
  982. if (taicpu(hp1).oper[0]^.typ = taicpu(p).oper[1]^.typ) and
  983. (taicpu(hp1).oper[1]^.typ = taicpu(p).oper[0]^.typ) then
  984. {mov reg1, mem1 or mov mem1, reg1
  985. mov mem2, reg2 mov reg2, mem2}
  986. begin
  987. if OpsEqual(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) then
  988. {mov reg1, mem1 or mov mem1, reg1
  989. mov mem2, reg1 mov reg2, mem1}
  990. begin
  991. if OpsEqual(taicpu(hp1).oper[0]^,taicpu(p).oper[1]^) then
  992. { Removes the second statement from
  993. mov reg1, mem1/reg2
  994. mov mem1/reg2, reg1 }
  995. begin
  996. if (taicpu(p).oper[0]^.typ = top_reg) then
  997. AllocRegBetween(asmL,taicpu(p).oper[0]^.reg,p,hp1,usedregs);
  998. asml.remove(hp1);
  999. hp1.free;
  1000. end
  1001. else
  1002. begin
  1003. TmpUsedRegs := UsedRegs;
  1004. UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
  1005. if (taicpu(p).oper[1]^.typ = top_ref) and
  1006. { mov reg1, mem1
  1007. mov mem2, reg1 }
  1008. (taicpu(hp1).oper[0]^.ref^.refaddr = addr_no) and
  1009. GetNextInstruction(hp1, hp2) and
  1010. (hp2.typ = ait_instruction) and
  1011. (taicpu(hp2).opcode = A_CMP) and
  1012. (taicpu(hp2).opsize = taicpu(p).opsize) and
  1013. (taicpu(hp2).oper[0]^.typ = TOp_Ref) and
  1014. (taicpu(hp2).oper[1]^.typ = TOp_Reg) and
  1015. RefsEqual(taicpu(hp2).oper[0]^.ref^, taicpu(p).oper[1]^.ref^) and
  1016. (taicpu(hp2).oper[1]^.reg= taicpu(p).oper[0]^.reg) and
  1017. not(RegUsedAfterInstruction(taicpu(p).oper[0]^.reg, hp2, TmpUsedRegs)) then
  1018. { change to
  1019. mov reg1, mem1 mov reg1, mem1
  1020. mov mem2, reg1 cmp reg1, mem2
  1021. cmp mem1, reg1 }
  1022. begin
  1023. asml.remove(hp2);
  1024. hp2.free;
  1025. taicpu(hp1).opcode := A_CMP;
  1026. taicpu(hp1).loadref(1,taicpu(hp1).oper[0]^.ref^);
  1027. taicpu(hp1).loadreg(0,taicpu(p).oper[0]^.reg);
  1028. end;
  1029. end;
  1030. end
  1031. else
  1032. begin
  1033. tmpUsedRegs := UsedRegs;
  1034. if GetNextInstruction(hp1, hp2) and
  1035. (taicpu(p).oper[0]^.typ = top_ref) and
  1036. (taicpu(p).oper[1]^.typ = top_reg) and
  1037. (taicpu(hp1).oper[0]^.typ = top_reg) and
  1038. (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
  1039. (taicpu(hp1).oper[1]^.typ = top_ref) and
  1040. (tai(hp2).typ = ait_instruction) and
  1041. (taicpu(hp2).opcode = A_MOV) and
  1042. (taicpu(hp2).opsize = taicpu(p).opsize) and
  1043. (taicpu(hp2).oper[1]^.typ = top_reg) and
  1044. (taicpu(hp2).oper[0]^.typ = top_ref) and
  1045. RefsEqual(taicpu(hp2).oper[0]^.ref^, taicpu(hp1).oper[1]^.ref^) then
  1046. if not regInRef(getsupreg(taicpu(hp2).oper[1]^.reg),taicpu(hp2).oper[0]^.ref^) and
  1047. not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,hp1,tmpUsedRegs)) then
  1048. { mov mem1, %reg1
  1049. mov %reg1, mem2
  1050. mov mem2, reg2
  1051. to:
  1052. mov mem1, reg2
  1053. mov reg2, mem2}
  1054. begin
  1055. AllocRegBetween(asmL,taicpu(hp2).oper[1]^.reg,p,hp2,usedregs);
  1056. taicpu(p).Loadoper(1,taicpu(hp2).oper[1]^);
  1057. taicpu(hp1).loadoper(0,taicpu(hp2).oper[1]^);
  1058. asml.remove(hp2);
  1059. hp2.free;
  1060. end
  1061. else
  1062. if (taicpu(p).oper[1]^.reg <> taicpu(hp2).oper[1]^.reg) and
  1063. not(RegInRef(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^.ref^)) and
  1064. not(RegInRef(getsupreg(taicpu(hp2).oper[1]^.reg),taicpu(hp2).oper[0]^.ref^)) then
  1065. { mov mem1, reg1 mov mem1, reg1
  1066. mov reg1, mem2 mov reg1, mem2
  1067. mov mem2, reg2 mov mem2, reg1
  1068. to: to:
  1069. mov mem1, reg1 mov mem1, reg1
  1070. mov mem1, reg2 mov reg1, mem2
  1071. mov reg1, mem2
  1072. or (if mem1 depends on reg1
  1073. and/or if mem2 depends on reg2)
  1074. to:
  1075. mov mem1, reg1
  1076. mov reg1, mem2
  1077. mov reg1, reg2
  1078. }
  1079. begin
  1080. taicpu(hp1).LoadRef(0,taicpu(p).oper[0]^.ref^);
  1081. taicpu(hp1).LoadReg(1,taicpu(hp2).oper[1]^.reg);
  1082. taicpu(hp2).LoadRef(1,taicpu(hp2).oper[0]^.ref^);
  1083. taicpu(hp2).LoadReg(0,taicpu(p).oper[1]^.reg);
  1084. allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
  1085. if (taicpu(p).oper[0]^.ref^.base <> NR_NO) and
  1086. (getsupreg(taicpu(p).oper[0]^.ref^.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
  1087. allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.base,p,hp2,usedregs);
  1088. if (taicpu(p).oper[0]^.ref^.index <> NR_NO) and
  1089. (getsupreg(taicpu(p).oper[0]^.ref^.index) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) then
  1090. allocRegBetween(asmL,taicpu(p).oper[0]^.ref^.index,p,hp2,usedregs);
  1091. end
  1092. else
  1093. if (taicpu(hp1).Oper[0]^.reg <> taicpu(hp2).Oper[1]^.reg) then
  1094. begin
  1095. taicpu(hp2).LoadReg(0,taicpu(hp1).Oper[0]^.reg);
  1096. allocRegBetween(asmL,taicpu(p).oper[1]^.reg,p,hp2,usedregs);
  1097. end
  1098. else
  1099. begin
  1100. asml.remove(hp2);
  1101. hp2.free;
  1102. end
  1103. end
  1104. end
  1105. else
  1106. (* {movl [mem1],reg1
  1107. movl [mem1],reg2
  1108. to:
  1109. movl [mem1],reg1
  1110. movl reg1,reg2 }
  1111. if (taicpu(p).oper[0]^.typ = top_ref) and
  1112. (taicpu(p).oper[1]^.typ = top_reg) and
  1113. (taicpu(hp1).oper[0]^.typ = top_ref) and
  1114. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1115. (taicpu(p).opsize = taicpu(hp1).opsize) and
  1116. RefsEqual(TReference(taicpu(p).oper[0]^^),taicpu(hp1).oper[0]^^.ref^) and
  1117. (taicpu(p).oper[1]^.reg<>taicpu(hp1).oper[0]^^.ref^.base) and
  1118. (taicpu(p).oper[1]^.reg<>taicpu(hp1).oper[0]^^.ref^.index) then
  1119. taicpu(hp1).LoadReg(0,taicpu(p).oper[1]^.reg)
  1120. else*)
  1121. { movl const1,[mem1]
  1122. movl [mem1],reg1
  1123. to:
  1124. movl const1,reg1
  1125. movl reg1,[mem1] }
  1126. if (taicpu(p).oper[0]^.typ = top_const) and
  1127. (taicpu(p).oper[1]^.typ = top_ref) and
  1128. (taicpu(hp1).oper[0]^.typ = top_ref) and
  1129. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1130. (taicpu(p).opsize = taicpu(hp1).opsize) and
  1131. RefsEqual(taicpu(hp1).oper[0]^.ref^,taicpu(p).oper[1]^.ref^) then
  1132. begin
  1133. allocregbetween(asml,taicpu(hp1).oper[1]^.reg,p,hp1,usedregs);
  1134. taicpu(hp1).LoadReg(0,taicpu(hp1).oper[1]^.reg);
  1135. taicpu(hp1).LoadRef(1,taicpu(p).oper[1]^.ref^);
  1136. taicpu(p).LoadReg(1,taicpu(hp1).oper[0]^.reg);
  1137. end
  1138. end;
  1139. end;
  1140. A_MOVZX:
  1141. begin
  1142. {removes superfluous And's after movzx's}
  1143. if (taicpu(p).oper[1]^.typ = top_reg) and
  1144. GetNextInstruction(p, hp1) and
  1145. (tai(hp1).typ = ait_instruction) and
  1146. (taicpu(hp1).opcode = A_AND) and
  1147. (taicpu(hp1).oper[0]^.typ = top_const) and
  1148. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1149. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  1150. case taicpu(p).opsize Of
  1151. S_BL, S_BW:
  1152. if (taicpu(hp1).oper[0]^.val = $ff) then
  1153. begin
  1154. asml.remove(hp1);
  1155. hp1.free;
  1156. end;
  1157. S_WL:
  1158. if (taicpu(hp1).oper[0]^.val = $ffff) then
  1159. begin
  1160. asml.remove(hp1);
  1161. hp1.free;
  1162. end;
  1163. end;
  1164. {changes some movzx constructs to faster synonims (all examples
  1165. are given with eax/ax, but are also valid for other registers)}
  1166. if (taicpu(p).oper[1]^.typ = top_reg) then
  1167. if (taicpu(p).oper[0]^.typ = top_reg) then
  1168. case taicpu(p).opsize of
  1169. S_BW:
  1170. begin
  1171. if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
  1172. not(CS_LittleSize in aktglobalswitches) then
  1173. {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
  1174. begin
  1175. taicpu(p).opcode := A_AND;
  1176. taicpu(p).changeopsize(S_W);
  1177. taicpu(p).LoadConst(0,$ff);
  1178. end
  1179. else if GetNextInstruction(p, hp1) and
  1180. (tai(hp1).typ = ait_instruction) and
  1181. (taicpu(hp1).opcode = A_AND) and
  1182. (taicpu(hp1).oper[0]^.typ = top_const) and
  1183. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1184. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  1185. {Change "movzbw %reg1, %reg2; andw $const, %reg2"
  1186. to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
  1187. begin
  1188. taicpu(p).opcode := A_MOV;
  1189. taicpu(p).changeopsize(S_W);
  1190. setsubreg(taicpu(p).oper[0]^.reg,R_SUBW);
  1191. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
  1192. end;
  1193. end;
  1194. S_BL:
  1195. begin
  1196. if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
  1197. not(CS_LittleSize in aktglobalswitches) then
  1198. {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
  1199. begin
  1200. taicpu(p).opcode := A_AND;
  1201. taicpu(p).changeopsize(S_L);
  1202. taicpu(p).loadconst(0,$ff)
  1203. end
  1204. else if GetNextInstruction(p, hp1) and
  1205. (tai(hp1).typ = ait_instruction) and
  1206. (taicpu(hp1).opcode = A_AND) and
  1207. (taicpu(hp1).oper[0]^.typ = top_const) and
  1208. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1209. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  1210. {Change "movzbl %reg1, %reg2; andl $const, %reg2"
  1211. to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
  1212. begin
  1213. taicpu(p).opcode := A_MOV;
  1214. taicpu(p).changeopsize(S_L);
  1215. setsubreg(taicpu(p).oper[0]^.reg,R_SUBWHOLE);
  1216. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
  1217. end
  1218. end;
  1219. S_WL:
  1220. begin
  1221. if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
  1222. not(CS_LittleSize in aktglobalswitches) then
  1223. {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
  1224. begin
  1225. taicpu(p).opcode := A_AND;
  1226. taicpu(p).changeopsize(S_L);
  1227. taicpu(p).LoadConst(0,$ffff);
  1228. end
  1229. else if GetNextInstruction(p, hp1) and
  1230. (tai(hp1).typ = ait_instruction) and
  1231. (taicpu(hp1).opcode = A_AND) and
  1232. (taicpu(hp1).oper[0]^.typ = top_const) and
  1233. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1234. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  1235. {Change "movzwl %reg1, %reg2; andl $const, %reg2"
  1236. to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
  1237. begin
  1238. taicpu(p).opcode := A_MOV;
  1239. taicpu(p).changeopsize(S_L);
  1240. setsubreg(taicpu(p).oper[0]^.reg,R_SUBWHOLE);
  1241. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
  1242. end;
  1243. end;
  1244. end
  1245. else if (taicpu(p).oper[0]^.typ = top_ref) then
  1246. begin
  1247. if GetNextInstruction(p, hp1) and
  1248. (tai(hp1).typ = ait_instruction) and
  1249. (taicpu(hp1).opcode = A_AND) and
  1250. (taicpu(hp1).oper[0]^.typ = Top_Const) and
  1251. (taicpu(hp1).oper[1]^.typ = Top_Reg) and
  1252. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  1253. begin
  1254. taicpu(p).opcode := A_MOV;
  1255. case taicpu(p).opsize Of
  1256. S_BL:
  1257. begin
  1258. taicpu(p).changeopsize(S_L);
  1259. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
  1260. end;
  1261. S_WL:
  1262. begin
  1263. taicpu(p).changeopsize(S_L);
  1264. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
  1265. end;
  1266. S_BW:
  1267. begin
  1268. taicpu(p).changeopsize(S_W);
  1269. taicpu(hp1).LoadConst(0,taicpu(hp1).oper[0]^.val and $ff);
  1270. end;
  1271. end;
  1272. end;
  1273. end;
  1274. end;
  1275. (* should not be generated anymore by the current code generator
  1276. A_POP:
  1277. begin
  1278. if target_info.system=system_i386_go32v2 then
  1279. begin
  1280. { Transform a series of pop/pop/pop/push/push/push to }
  1281. { 'movl x(%esp),%reg' for go32v2 (not for the rest, }
  1282. { because I'm not sure whether they can cope with }
  1283. { 'movl x(%esp),%reg' with x > 0, I believe we had }
  1284. { such a problem when using esp as frame pointer (JM) }
  1285. if (taicpu(p).oper[0]^.typ = top_reg) then
  1286. begin
  1287. hp1 := p;
  1288. hp2 := p;
  1289. l := 0;
  1290. while getNextInstruction(hp1,hp1) and
  1291. (hp1.typ = ait_instruction) and
  1292. (taicpu(hp1).opcode = A_POP) and
  1293. (taicpu(hp1).oper[0]^.typ = top_reg) do
  1294. begin
  1295. hp2 := hp1;
  1296. inc(l,4);
  1297. end;
  1298. getLastInstruction(p,hp3);
  1299. l1 := 0;
  1300. while (hp2 <> hp3) and
  1301. assigned(hp1) and
  1302. (hp1.typ = ait_instruction) and
  1303. (taicpu(hp1).opcode = A_PUSH) and
  1304. (taicpu(hp1).oper[0]^.typ = top_reg) and
  1305. (taicpu(hp1).oper[0]^.reg.enum = taicpu(hp2).oper[0]^.reg.enum) do
  1306. begin
  1307. { change it to a two op operation }
  1308. taicpu(hp2).oper[1]^.typ:=top_none;
  1309. taicpu(hp2).ops:=2;
  1310. taicpu(hp2).opcode := A_MOV;
  1311. taicpu(hp2).Loadoper(1,taicpu(hp1).oper[0]^);
  1312. reference_reset(tmpref);
  1313. tmpRef.base.enum:=R_INTREGISTER;
  1314. tmpRef.base.number:=NR_STACK_POINTER_REG;
  1315. convert_register_to_enum(tmpref.base);
  1316. tmpRef.offset := l;
  1317. taicpu(hp2).loadRef(0,tmpRef);
  1318. hp4 := hp1;
  1319. getNextInstruction(hp1,hp1);
  1320. asml.remove(hp4);
  1321. hp4.free;
  1322. getLastInstruction(hp2,hp2);
  1323. dec(l,4);
  1324. inc(l1);
  1325. end;
  1326. if l <> -4 then
  1327. begin
  1328. inc(l,4);
  1329. for l1 := l1 downto 1 do
  1330. begin
  1331. getNextInstruction(hp2,hp2);
  1332. dec(taicpu(hp2).oper[0]^.ref^.offset,l);
  1333. end
  1334. end
  1335. end
  1336. end
  1337. else
  1338. begin
  1339. if (taicpu(p).oper[0]^.typ = top_reg) and
  1340. GetNextInstruction(p, hp1) and
  1341. (tai(hp1).typ=ait_instruction) and
  1342. (taicpu(hp1).opcode=A_PUSH) and
  1343. (taicpu(hp1).oper[0]^.typ = top_reg) and
  1344. (taicpu(hp1).oper[0]^.reg.enum=taicpu(p).oper[0]^.reg.enum) then
  1345. begin
  1346. { change it to a two op operation }
  1347. taicpu(p).oper[1]^.typ:=top_none;
  1348. taicpu(p).ops:=2;
  1349. taicpu(p).opcode := A_MOV;
  1350. taicpu(p).Loadoper(1,taicpu(p).oper[0]^);
  1351. reference_reset(tmpref);
  1352. TmpRef.base.enum := R_ESP;
  1353. taicpu(p).LoadRef(0,TmpRef);
  1354. asml.remove(hp1);
  1355. hp1.free;
  1356. end;
  1357. end;
  1358. end;
  1359. *)
  1360. A_PUSH:
  1361. begin
  1362. if (taicpu(p).opsize = S_W) and
  1363. (taicpu(p).oper[0]^.typ = Top_Const) and
  1364. GetNextInstruction(p, hp1) and
  1365. (tai(hp1).typ = ait_instruction) and
  1366. (taicpu(hp1).opcode = A_PUSH) and
  1367. (taicpu(hp1).oper[0]^.typ = Top_Const) and
  1368. (taicpu(hp1).opsize = S_W) then
  1369. begin
  1370. taicpu(p).changeopsize(S_L);
  1371. taicpu(p).LoadConst(0,taicpu(p).oper[0]^.val shl 16 + word(taicpu(hp1).oper[0]^.val));
  1372. asml.remove(hp1);
  1373. hp1.free;
  1374. end;
  1375. end;
  1376. A_SHL, A_SAL:
  1377. begin
  1378. if (taicpu(p).oper[0]^.typ = Top_Const) and
  1379. (taicpu(p).oper[1]^.typ = Top_Reg) and
  1380. (taicpu(p).opsize = S_L) and
  1381. (taicpu(p).oper[0]^.val <= 3) then
  1382. {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
  1383. begin
  1384. TmpBool1 := True; {should we check the next instruction?}
  1385. TmpBool2 := False; {have we found an add/sub which could be
  1386. integrated in the lea?}
  1387. reference_reset(tmpref);
  1388. TmpRef.index := taicpu(p).oper[1]^.reg;
  1389. TmpRef.scalefactor := 1 shl taicpu(p).oper[0]^.val;
  1390. while TmpBool1 and
  1391. GetNextInstruction(p, hp1) and
  1392. (tai(hp1).typ = ait_instruction) and
  1393. ((((taicpu(hp1).opcode = A_ADD) or
  1394. (taicpu(hp1).opcode = A_SUB)) and
  1395. (taicpu(hp1).oper[1]^.typ = Top_Reg) and
  1396. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg)) or
  1397. (((taicpu(hp1).opcode = A_INC) or
  1398. (taicpu(hp1).opcode = A_DEC)) and
  1399. (taicpu(hp1).oper[0]^.typ = Top_Reg) and
  1400. (taicpu(hp1).oper[0]^.reg = taicpu(p).oper[1]^.reg))) Do
  1401. begin
  1402. TmpBool1 := False;
  1403. if (taicpu(hp1).oper[0]^.typ = Top_Const) then
  1404. begin
  1405. TmpBool1 := True;
  1406. TmpBool2 := True;
  1407. case taicpu(hp1).opcode of
  1408. A_ADD:
  1409. inc(TmpRef.offset, longint(taicpu(hp1).oper[0]^.val));
  1410. A_SUB:
  1411. dec(TmpRef.offset, longint(taicpu(hp1).oper[0]^.val));
  1412. end;
  1413. asml.remove(hp1);
  1414. hp1.free;
  1415. end
  1416. else
  1417. if (taicpu(hp1).oper[0]^.typ = Top_Reg) and
  1418. (((taicpu(hp1).opcode = A_ADD) and
  1419. (TmpRef.base = NR_NO)) or
  1420. (taicpu(hp1).opcode = A_INC) or
  1421. (taicpu(hp1).opcode = A_DEC)) then
  1422. begin
  1423. TmpBool1 := True;
  1424. TmpBool2 := True;
  1425. case taicpu(hp1).opcode of
  1426. A_ADD:
  1427. TmpRef.base := taicpu(hp1).oper[0]^.reg;
  1428. A_INC:
  1429. inc(TmpRef.offset);
  1430. A_DEC:
  1431. dec(TmpRef.offset);
  1432. end;
  1433. asml.remove(hp1);
  1434. hp1.free;
  1435. end;
  1436. end;
  1437. if TmpBool2 or
  1438. ((aktoptprocessor < ClassPentium2) and
  1439. (taicpu(p).oper[0]^.val <= 3) and
  1440. not(CS_LittleSize in aktglobalswitches)) then
  1441. begin
  1442. if not(TmpBool2) and
  1443. (taicpu(p).oper[0]^.val = 1) then
  1444. begin
  1445. hp1 := taicpu.Op_reg_reg(A_ADD,taicpu(p).opsize,
  1446. taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg)
  1447. end
  1448. else
  1449. hp1 := taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
  1450. taicpu(p).oper[1]^.reg);
  1451. InsertLLItem(asml,p.previous, p.next, hp1);
  1452. p.free;
  1453. p := hp1;
  1454. end;
  1455. end
  1456. else
  1457. if (aktoptprocessor < ClassPentium2) and
  1458. (taicpu(p).oper[0]^.typ = top_const) and
  1459. (taicpu(p).oper[1]^.typ = top_reg) then
  1460. if (taicpu(p).oper[0]^.val = 1) then
  1461. {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
  1462. but faster on a 486, and Tairable in both U and V pipes on the Pentium
  1463. (unlike shl, which is only Tairable in the U pipe)}
  1464. begin
  1465. hp1 := taicpu.Op_reg_reg(A_ADD,taicpu(p).opsize,
  1466. taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg);
  1467. InsertLLItem(asml,p.previous, p.next, hp1);
  1468. p.free;
  1469. p := hp1;
  1470. end
  1471. else if (taicpu(p).opsize = S_L) and
  1472. (taicpu(p).oper[0]^.val<= 3) then
  1473. {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
  1474. "shl $3, %reg" to "lea (,%reg,8), %reg}
  1475. begin
  1476. reference_reset(tmpref);
  1477. TmpRef.index := taicpu(p).oper[1]^.reg;
  1478. TmpRef.scalefactor := 1 shl taicpu(p).oper[0]^.val;
  1479. hp1 := taicpu.Op_ref_reg(A_LEA,S_L,TmpRef, taicpu(p).oper[1]^.reg);
  1480. InsertLLItem(asml,p.previous, p.next, hp1);
  1481. p.free;
  1482. p := hp1;
  1483. end
  1484. end;
  1485. A_SETcc :
  1486. { changes
  1487. setcc (funcres) setcc reg
  1488. movb (funcres), reg to leave/ret
  1489. leave/ret }
  1490. begin
  1491. if (taicpu(p).oper[0]^.typ = top_ref) and
  1492. GetNextInstruction(p, hp1) and
  1493. GetNextInstruction(hp1, hp2) and
  1494. (hp2.typ = ait_instruction) and
  1495. ((taicpu(hp2).opcode = A_LEAVE) or
  1496. (taicpu(hp2).opcode = A_RET)) and
  1497. (taicpu(p).oper[0]^.ref^.base = current_procinfo.FramePointer) and
  1498. (taicpu(p).oper[0]^.ref^.index = NR_NO) and
  1499. not(assigned(current_procinfo.procdef.funcretsym) and
  1500. (taicpu(p).oper[0]^.ref^.offset < tabstractnormalvarsym(current_procinfo.procdef.funcretsym).localloc.reference.offset)) and
  1501. (hp1.typ = ait_instruction) and
  1502. (taicpu(hp1).opcode = A_MOV) and
  1503. (taicpu(hp1).opsize = S_B) and
  1504. (taicpu(hp1).oper[0]^.typ = top_ref) and
  1505. RefsEqual(taicpu(hp1).oper[0]^.ref^, taicpu(p).oper[0]^.ref^) then
  1506. begin
  1507. taicpu(p).LoadReg(0,taicpu(hp1).oper[1]^.reg);
  1508. asml.remove(hp1);
  1509. hp1.free;
  1510. end
  1511. end;
  1512. A_SUB:
  1513. { * change "subl $2, %esp; pushw x" to "pushl x"}
  1514. { * change "sub/add const1, reg" or "dec reg" followed by
  1515. "sub const2, reg" to one "sub ..., reg" }
  1516. begin
  1517. if (taicpu(p).oper[0]^.typ = top_const) and
  1518. (taicpu(p).oper[1]^.typ = top_reg) then
  1519. if (taicpu(p).oper[0]^.val = 2) and
  1520. (taicpu(p).oper[1]^.reg = NR_ESP) and
  1521. { Don't do the sub/push optimization if the sub }
  1522. { comes from setting up the stack frame (JM) }
  1523. (not getLastInstruction(p,hp1) or
  1524. (hp1.typ <> ait_instruction) or
  1525. (taicpu(hp1).opcode <> A_MOV) or
  1526. (taicpu(hp1).oper[0]^.typ <> top_reg) or
  1527. (taicpu(hp1).oper[0]^.reg <> NR_ESP) or
  1528. (taicpu(hp1).oper[1]^.typ <> top_reg) or
  1529. (taicpu(hp1).oper[1]^.reg <> NR_EBP)) then
  1530. begin
  1531. hp1 := tai(p.next);
  1532. while Assigned(hp1) and
  1533. (tai(hp1).typ in [ait_instruction]+SkipInstr) and
  1534. not regReadByInstruction(RS_ESP,hp1) and
  1535. not regModifiedByInstruction(RS_ESP,hp1) do
  1536. hp1 := tai(hp1.next);
  1537. if Assigned(hp1) and
  1538. (tai(hp1).typ = ait_instruction) and
  1539. (taicpu(hp1).opcode = A_PUSH) and
  1540. (taicpu(hp1).opsize = S_W) then
  1541. begin
  1542. taicpu(hp1).changeopsize(S_L);
  1543. if taicpu(hp1).oper[0]^.typ=top_reg then
  1544. setsubreg(taicpu(hp1).oper[0]^.reg,R_SUBWHOLE);
  1545. hp1 := tai(p.next);
  1546. asml.remove(p);
  1547. p.free;
  1548. p := hp1;
  1549. continue
  1550. end;
  1551. if DoSubAddOpt(p) then
  1552. continue;
  1553. end
  1554. else if DoSubAddOpt(p) then
  1555. continue
  1556. end;
  1557. end;
  1558. end; { if is_jmp }
  1559. end;
  1560. end;
  1561. updateUsedRegs(UsedRegs,p);
  1562. p:=tai(p.next);
  1563. end;
  1564. end;
  1565. function isFoldableArithOp(hp1: taicpu; reg: tregister): boolean;
  1566. begin
  1567. isFoldableArithOp := False;
  1568. case hp1.opcode of
  1569. A_ADD,A_SUB,A_OR,A_XOR,A_AND,A_SHL,A_SHR,A_SAR:
  1570. isFoldableArithOp :=
  1571. ((taicpu(hp1).oper[0]^.typ = top_const) or
  1572. ((taicpu(hp1).oper[0]^.typ = top_reg) and
  1573. (taicpu(hp1).oper[0]^.reg <> reg))) and
  1574. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1575. (taicpu(hp1).oper[1]^.reg = reg);
  1576. A_INC,A_DEC:
  1577. isFoldableArithOp :=
  1578. (taicpu(hp1).oper[0]^.typ = top_reg) and
  1579. (taicpu(hp1).oper[0]^.reg = reg);
  1580. end;
  1581. end;
  1582. procedure PeepHoleOptPass2(asml: taasmoutput; BlockStart, BlockEnd: tai);
  1583. {$ifdef USECMOV}
  1584. function CanBeCMOV(p : tai) : boolean;
  1585. begin
  1586. CanBeCMOV:=assigned(p) and (p.typ=ait_instruction) and
  1587. (taicpu(p).opcode=A_MOV) and
  1588. (taicpu(p).opsize in [S_L,S_W]) and
  1589. ((taicpu(p).oper[0]^.typ = top_reg) or
  1590. ((taicpu(p).oper[0]^.typ = top_ref) and
  1591. (taicpu(p).oper[0]^.ref^.refaddr = addr_no))) and
  1592. (taicpu(p).oper[1]^.typ in [top_reg]);
  1593. end;
  1594. {$endif USECMOV}
  1595. var
  1596. p,hp1,hp2: tai;
  1597. {$ifdef USECMOV}
  1598. l : longint;
  1599. condition : tasmcond;
  1600. hp3: tai;
  1601. {$endif USECMOV}
  1602. UsedRegs, TmpUsedRegs: TRegSet;
  1603. begin
  1604. p := BlockStart;
  1605. UsedRegs := [];
  1606. while (p <> BlockEnd) Do
  1607. begin
  1608. UpdateUsedRegs(UsedRegs, tai(p.next));
  1609. case p.Typ Of
  1610. Ait_Instruction:
  1611. begin
  1612. case taicpu(p).opcode Of
  1613. {$ifdef USECMOV}
  1614. A_Jcc:
  1615. if (aktspecificoptprocessor>=ClassPentium2) then
  1616. begin
  1617. { check for
  1618. jCC xxx
  1619. <several movs>
  1620. xxx:
  1621. }
  1622. l:=0;
  1623. GetNextInstruction(p, hp1);
  1624. while assigned(hp1) and
  1625. CanBeCMOV(hp1) do
  1626. begin
  1627. inc(l);
  1628. GetNextInstruction(hp1,hp1);
  1629. end;
  1630. if assigned(hp1) then
  1631. begin
  1632. if FindLabel(tasmlabel(taicpu(p).oper[0]^.sym),hp1) then
  1633. begin
  1634. if (l<=4) and (l>0) then
  1635. begin
  1636. condition:=inverse_cond[taicpu(p).condition];
  1637. GetNextInstruction(p,hp1);
  1638. asml.remove(p);
  1639. p.free;
  1640. p:=hp1;
  1641. repeat
  1642. taicpu(hp1).opcode:=A_CMOVcc;
  1643. taicpu(hp1).condition:=condition;
  1644. GetNextInstruction(hp1,hp1);
  1645. until not(assigned(hp1)) or
  1646. not(CanBeCMOV(hp1));
  1647. asml.remove(hp1);
  1648. hp1.free;
  1649. continue;
  1650. end;
  1651. end
  1652. else
  1653. begin
  1654. { check further for
  1655. jCC xxx
  1656. <several movs>
  1657. jmp yyy
  1658. xxx:
  1659. <several movs>
  1660. yyy:
  1661. }
  1662. { hp2 points to jmp xxx }
  1663. hp2:=hp1;
  1664. { skip hp1 to xxx }
  1665. GetNextInstruction(hp1, hp1);
  1666. if assigned(hp2) and
  1667. assigned(hp1) and
  1668. (l<=3) and
  1669. (hp2.typ=ait_instruction) and
  1670. (taicpu(hp2).is_jmp) and
  1671. (taicpu(hp2).condition=C_None) and
  1672. FindLabel(tasmlabel(taicpu(p).oper[0]^.sym),hp1) then
  1673. begin
  1674. l:=0;
  1675. while assigned(hp1) and
  1676. CanBeCMOV(hp1) do
  1677. begin
  1678. inc(l);
  1679. GetNextInstruction(hp1, hp1);
  1680. end;
  1681. end;
  1682. {
  1683. if assigned(hp1) and
  1684. FindLabel(tasmlabel(taicpu(hp2).oper[0]^.sym),hp1) then
  1685. begin
  1686. condition:=inverse_cond[taicpu(p).condition];
  1687. GetNextInstruction(p,hp1);
  1688. asml.remove(p);
  1689. p.free;
  1690. p:=hp1;
  1691. repeat
  1692. taicpu(hp1).opcode:=A_CMOVcc;
  1693. taicpu(hp1).condition:=condition;
  1694. GetNextInstruction(hp1,hp1);
  1695. until not(assigned(hp1)) or
  1696. not(CanBeCMOV(hp1));
  1697. hp2:=hp1.next;
  1698. condition:=inverse_cond[condition];
  1699. asml.remove(hp1.next)
  1700. hp1.next.free;
  1701. asml.remove(hp1);
  1702. hp1.free;
  1703. continue;
  1704. end;
  1705. }
  1706. end;
  1707. end;
  1708. end;
  1709. {$endif USECMOV}
  1710. A_FSTP,A_FISTP:
  1711. if doFpuLoadStoreOpt(asmL,p) then
  1712. continue;
  1713. A_IMUL:
  1714. begin
  1715. if (taicpu(p).ops >= 2) and
  1716. ((taicpu(p).oper[0]^.typ = top_const) or
  1717. ((taicpu(p).oper[0]^.typ = top_ref) and (taicpu(p).oper[0]^.ref^.refaddr=addr_full))) and
  1718. (taicpu(p).oper[1]^.typ = top_reg) and
  1719. ((taicpu(p).ops = 2) or
  1720. ((taicpu(p).oper[2]^.typ = top_reg) and
  1721. (taicpu(p).oper[2]^.reg = taicpu(p).oper[1]^.reg))) and
  1722. getLastInstruction(p,hp1) and
  1723. (hp1.typ = ait_instruction) and
  1724. (taicpu(hp1).opcode = A_MOV) and
  1725. (taicpu(hp1).oper[0]^.typ = top_reg) and
  1726. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1727. (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
  1728. { change "mov reg1,reg2; imul y,reg2" to "imul y,reg1,reg2" }
  1729. begin
  1730. taicpu(p).ops := 3;
  1731. taicpu(p).loadreg(1,taicpu(hp1).oper[0]^.reg);
  1732. taicpu(p).loadreg(2,taicpu(hp1).oper[1]^.reg);
  1733. asml.remove(hp1);
  1734. hp1.free;
  1735. end;
  1736. end;
  1737. A_MOV:
  1738. begin
  1739. if (taicpu(p).oper[0]^.typ = top_reg) and
  1740. (taicpu(p).oper[1]^.typ = top_reg) and
  1741. GetNextInstruction(p, hp1) and
  1742. (hp1.typ = ait_Instruction) and
  1743. ((taicpu(hp1).opcode = A_MOV) or
  1744. (taicpu(hp1).opcode = A_MOVZX) or
  1745. (taicpu(hp1).opcode = A_MOVSX)) and
  1746. (taicpu(hp1).oper[0]^.typ = top_ref) and
  1747. (taicpu(hp1).oper[1]^.typ = top_reg) and
  1748. ((taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) or
  1749. (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg)) and
  1750. (getsupreg(taicpu(hp1).oper[1]^.reg) = getsupreg(taicpu(p).oper[1]^.reg)) then
  1751. {mov reg1, reg2
  1752. mov/zx/sx (reg2, ..), reg2 to mov/zx/sx (reg1, ..), reg2}
  1753. begin
  1754. if (taicpu(hp1).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) then
  1755. taicpu(hp1).oper[0]^.ref^.base := taicpu(p).oper[0]^.reg;
  1756. if (taicpu(hp1).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) then
  1757. taicpu(hp1).oper[0]^.ref^.index := taicpu(p).oper[0]^.reg;
  1758. asml.remove(p);
  1759. p.free;
  1760. p := hp1;
  1761. continue;
  1762. end
  1763. else if (taicpu(p).oper[0]^.typ = top_ref) and
  1764. GetNextInstruction(p,hp1) and
  1765. (hp1.typ = ait_instruction) and
  1766. IsFoldableArithOp(taicpu(hp1),taicpu(p).oper[1]^.reg) and
  1767. GetNextInstruction(hp1,hp2) and
  1768. (hp2.typ = ait_instruction) and
  1769. (taicpu(hp2).opcode = A_MOV) and
  1770. (taicpu(hp2).oper[0]^.typ = top_reg) and
  1771. (taicpu(hp2).oper[0]^.reg = taicpu(p).oper[1]^.reg) and
  1772. (taicpu(hp2).oper[1]^.typ = top_ref) then
  1773. begin
  1774. TmpUsedRegs := UsedRegs;
  1775. UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
  1776. if (RefsEqual(taicpu(hp2).oper[1]^.ref^, taicpu(p).oper[0]^.ref^) and
  1777. not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,
  1778. hp2, TmpUsedRegs))) then
  1779. { change mov (ref), reg }
  1780. { add/sub/or/... reg2/$const, reg }
  1781. { mov reg, (ref) }
  1782. { # release reg }
  1783. { to add/sub/or/... reg2/$const, (ref) }
  1784. begin
  1785. case taicpu(hp1).opcode of
  1786. A_INC,A_DEC:
  1787. taicpu(hp1).LoadRef(0,taicpu(p).oper[0]^.ref^)
  1788. else
  1789. taicpu(hp1).LoadRef(1,taicpu(p).oper[0]^.ref^);
  1790. end;
  1791. asml.remove(p);
  1792. asml.remove(hp2);
  1793. p.free;
  1794. hp2.free;
  1795. p := hp1
  1796. end;
  1797. end
  1798. end;
  1799. end;
  1800. end;
  1801. end;
  1802. p := tai(p.next)
  1803. end;
  1804. end;
  1805. procedure PostPeepHoleOpts(asml: taasmoutput; BlockStart, BlockEnd: tai);
  1806. var
  1807. p,hp1,hp2: tai;
  1808. begin
  1809. p := BlockStart;
  1810. while (p <> BlockEnd) Do
  1811. begin
  1812. case p.Typ Of
  1813. Ait_Instruction:
  1814. begin
  1815. case taicpu(p).opcode Of
  1816. A_CALL:
  1817. if (AktOptProcessor < ClassPentium2) and
  1818. GetNextInstruction(p, hp1) and
  1819. (hp1.typ = ait_instruction) and
  1820. (taicpu(hp1).opcode = A_JMP) and
  1821. ((taicpu(hp1).oper[0]^.typ=top_ref) and (taicpu(hp1).oper[0]^.ref^.refaddr=addr_full)) then
  1822. begin
  1823. hp2 := taicpu.Op_sym(A_PUSH,S_L,taicpu(hp1).oper[0]^.ref^.symbol);
  1824. InsertLLItem(asml, p.previous, p, hp2);
  1825. taicpu(p).opcode := A_JMP;
  1826. taicpu(p).is_jmp := true;
  1827. asml.remove(hp1);
  1828. hp1.free;
  1829. end;
  1830. A_CMP:
  1831. begin
  1832. if (taicpu(p).oper[0]^.typ = top_const) and
  1833. (taicpu(p).oper[0]^.val = 0) and
  1834. (taicpu(p).oper[1]^.typ = top_reg) then
  1835. {change "cmp $0, %reg" to "test %reg, %reg"}
  1836. begin
  1837. taicpu(p).opcode := A_TEST;
  1838. taicpu(p).loadreg(0,taicpu(p).oper[1]^.reg);
  1839. continue;
  1840. end;
  1841. end;
  1842. (*
  1843. Optimization is not safe; xor clears the carry flag.
  1844. See test/tgadint64 in the test suite.
  1845. A_MOV:
  1846. if (taicpu(p).oper[0]^.typ = Top_Const) and
  1847. (taicpu(p).oper[0]^.val = 0) and
  1848. (taicpu(p).oper[1]^.typ = Top_Reg) then
  1849. { change "mov $0, %reg" into "xor %reg, %reg" }
  1850. begin
  1851. taicpu(p).opcode := A_XOR;
  1852. taicpu(p).LoadReg(0,taicpu(p).oper[1]^.reg);
  1853. end;
  1854. *)
  1855. A_MOVZX:
  1856. { if register vars are on, it's possible there is code like }
  1857. { "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx" }
  1858. { so we can't safely replace the movzx then with xor/mov, }
  1859. { since that would change the flags (JM) }
  1860. if not(cs_regvars in aktglobalswitches) then
  1861. begin
  1862. if (taicpu(p).oper[1]^.typ = top_reg) then
  1863. if (taicpu(p).oper[0]^.typ = top_reg)
  1864. then
  1865. case taicpu(p).opsize of
  1866. S_BL:
  1867. begin
  1868. if IsGP32Reg(getsupreg(taicpu(p).oper[1]^.reg)) and
  1869. not(CS_LittleSize in aktglobalswitches) and
  1870. (aktoptprocessor = ClassPentium) then
  1871. {Change "movzbl %reg1, %reg2" to
  1872. "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
  1873. PentiumMMX}
  1874. begin
  1875. hp1 := taicpu.op_reg_reg(A_XOR, S_L,
  1876. taicpu(p).oper[1]^.reg, taicpu(p).oper[1]^.reg);
  1877. InsertLLItem(asml,p.previous, p, hp1);
  1878. taicpu(p).opcode := A_MOV;
  1879. taicpu(p).changeopsize(S_B);
  1880. setsubreg(taicpu(p).oper[1]^.reg,R_SUBL);
  1881. end;
  1882. end;
  1883. end
  1884. else if (taicpu(p).oper[0]^.typ = top_ref) and
  1885. (taicpu(p).oper[0]^.ref^.base <> taicpu(p).oper[1]^.reg) and
  1886. (taicpu(p).oper[0]^.ref^.index <> taicpu(p).oper[1]^.reg) and
  1887. not(CS_LittleSize in aktglobalswitches) and
  1888. IsGP32Reg(getsupreg(taicpu(p).oper[1]^.reg)) and
  1889. (aktoptprocessor = ClassPentium) and
  1890. (taicpu(p).opsize = S_BL) then
  1891. {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
  1892. Pentium and PentiumMMX}
  1893. begin
  1894. hp1 := taicpu.Op_reg_reg(A_XOR, S_L, taicpu(p).oper[1]^.reg,
  1895. taicpu(p).oper[1]^.reg);
  1896. taicpu(p).opcode := A_MOV;
  1897. taicpu(p).changeopsize(S_B);
  1898. setsubreg(taicpu(p).oper[1]^.reg,R_SUBL);
  1899. InsertLLItem(asml,p.previous, p, hp1);
  1900. end;
  1901. end;
  1902. A_TEST, A_OR:
  1903. {removes the line marked with (x) from the sequence
  1904. and/or/xor/add/sub/... $x, %y
  1905. test/or %y, %y (x)
  1906. j(n)z _Label
  1907. as the first instruction already adjusts the ZF}
  1908. begin
  1909. if OpsEqual(taicpu(p).oper[0]^,taicpu(p).oper[1]^) then
  1910. if GetLastInstruction(p, hp1) and
  1911. (tai(hp1).typ = ait_instruction) then
  1912. case taicpu(hp1).opcode Of
  1913. A_ADD, A_SUB, A_OR, A_XOR, A_AND{, A_SHL, A_SHR}:
  1914. begin
  1915. if OpsEqual(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) then
  1916. begin
  1917. hp1 := tai(p.next);
  1918. asml.remove(p);
  1919. p.free;
  1920. p := tai(hp1);
  1921. continue
  1922. end;
  1923. end;
  1924. A_DEC, A_INC, A_NEG:
  1925. begin
  1926. if OpsEqual(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) then
  1927. begin
  1928. case taicpu(hp1).opcode Of
  1929. A_DEC, A_INC:
  1930. {replace inc/dec with add/sub 1, because inc/dec doesn't set the carry flag}
  1931. begin
  1932. case taicpu(hp1).opcode Of
  1933. A_DEC: taicpu(hp1).opcode := A_SUB;
  1934. A_INC: taicpu(hp1).opcode := A_ADD;
  1935. end;
  1936. taicpu(hp1).Loadoper(1,taicpu(hp1).oper[0]^);
  1937. taicpu(hp1).LoadConst(0,1);
  1938. taicpu(hp1).ops:=2;
  1939. end
  1940. end;
  1941. hp1 := tai(p.next);
  1942. asml.remove(p);
  1943. p.free;
  1944. p := tai(hp1);
  1945. continue
  1946. end;
  1947. end
  1948. end
  1949. end;
  1950. end;
  1951. end;
  1952. end;
  1953. p := tai(p.next)
  1954. end;
  1955. end;
  1956. end.
  1957. {
  1958. $Log$
  1959. Revision 1.68 2005-02-25 20:50:53 jonas
  1960. * fixed uninitialised function result in getfinaldestination() when
  1961. maximum recursion reached
  1962. Revision 1.67 2005/02/14 17:13:10 peter
  1963. * truncate log
  1964. }