popt386.pas 104 KB

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