popt386.pas 101 KB

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