popt386.pas 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  20. Interface
  21. Uses Aasm;
  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,hcodegen,
  30. {$ifdef finaldestdebug}
  31. cobjects,
  32. {$endif finaldestdebug}
  33. cpubase,cpuasm,DAOpt386,tgcpu;
  34. Function RegUsedAfterInstruction(Reg: TRegister; p: Tai; Var UsedRegs: TRegSet): Boolean;
  35. Begin
  36. reg := reg32(reg);
  37. UpdateUsedRegs(UsedRegs, Tai(p.Next));
  38. RegUsedAfterInstruction :=
  39. (Reg in UsedRegs) and
  40. (not(getNextInstruction(p,p)) or
  41. not(regLoadedWithNewValue(reg,false,p)));
  42. End;
  43. function doFpuLoadStoreOpt(asmL: TAAsmoutput; var p: Tai): boolean;
  44. { returns true if a "continue" should be done after this optimization }
  45. var hp1, hp2: Tai;
  46. begin
  47. doFpuLoadStoreOpt := false;
  48. if (Taicpu(p).oper[0].typ = top_ref) and
  49. getNextInstruction(p, hp1) and
  50. (hp1.typ = ait_instruction) and
  51. (((Taicpu(hp1).opcode = A_FLD) and
  52. (Taicpu(p).opcode = A_FSTP)) or
  53. ((Taicpu(p).opcode = A_FISTP) and
  54. (Taicpu(hp1).opcode = A_FILD))) and
  55. (Taicpu(hp1).oper[0].typ = top_ref) and
  56. (Taicpu(hp1).opsize = Taicpu(p).opsize) and
  57. refsEqual(Taicpu(p).oper[0].ref^, Taicpu(hp1).oper[0].ref^) then
  58. begin
  59. if getNextInstruction(hp1, hp2) and
  60. (hp2.typ = ait_instruction) and
  61. ((Taicpu(hp2).opcode = A_LEAVE) or
  62. (Taicpu(hp2).opcode = A_RET)) and
  63. (Taicpu(p).oper[0].ref^.Base = procinfo^.FramePointer) and
  64. (Taicpu(p).oper[0].ref^.Offset >= procinfo^.Return_Offset) and
  65. (Taicpu(p).oper[0].ref^.Index = R_NO) then
  66. begin
  67. asml.remove(p);
  68. asml.remove(hp1);
  69. p.free;
  70. hp1.free;
  71. p := hp2;
  72. removeLastDeallocForFuncRes(asmL, p);
  73. doFPULoadStoreOpt := true;
  74. end
  75. else
  76. { fst can't store an extended value! }
  77. if (Taicpu(p).opsize <> S_FX) and
  78. (Taicpu(p).opsize <> S_IQ) then
  79. begin
  80. if (Taicpu(p).opcode = A_FSTP) then
  81. Taicpu(p).opcode := A_FST
  82. else Taicpu(p).opcode := A_FIST;
  83. asml.remove(hp1);
  84. hp1.free;
  85. end
  86. end;
  87. end;
  88. Procedure PrePeepHoleOpts(AsmL: TAAsmOutput; BlockStart, BlockEnd: Tai);
  89. var
  90. p,hp1: Tai;
  91. l: longint;
  92. tmpRef: treference;
  93. Begin
  94. P := BlockStart;
  95. While (P <> BlockEnd) Do
  96. Begin
  97. Case p.Typ Of
  98. Ait_Instruction:
  99. Begin
  100. Case Taicpu(p).opcode Of
  101. A_IMUL:
  102. {changes certain "imul const, %reg"'s to lea sequences}
  103. Begin
  104. If (Taicpu(p).oper[0].typ = Top_Const) And
  105. (Taicpu(p).oper[1].typ = Top_Reg) And
  106. (Taicpu(p).opsize = S_L) Then
  107. If (Taicpu(p).oper[0].val = 1) Then
  108. If (Taicpu(p).oper[2].typ = Top_None) Then
  109. {remove "imul $1, reg"}
  110. Begin
  111. hp1 := Tai(p.Next);
  112. asml.Remove(p);
  113. p.free;
  114. p := hp1;
  115. Continue;
  116. End
  117. Else
  118. {change "imul $1, reg1, reg2" to "mov reg1, reg2"}
  119. Begin
  120. hp1 := Taicpu.Op_Reg_Reg(A_MOV, S_L, Taicpu(p).oper[1].reg,Taicpu(p).oper[2].reg);
  121. InsertLLItem(AsmL, p.previous, p.next, hp1);
  122. p.free;
  123. p := hp1;
  124. End
  125. Else If
  126. ((Taicpu(p).oper[2].typ = Top_Reg) or
  127. (Taicpu(p).oper[2].typ = Top_None)) And
  128. (aktoptprocessor < ClassP6) And
  129. (Taicpu(p).oper[0].val <= 12) And
  130. Not(CS_LittleSize in aktglobalswitches) And
  131. (Not(GetNextInstruction(p, hp1)) Or
  132. {GetNextInstruction(p, hp1) And}
  133. Not((Tai(hp1).typ = ait_instruction) And
  134. ((Taicpu(hp1).opcode=A_Jcc) and
  135. (Taicpu(hp1).condition in [C_O,C_NO]))))
  136. Then
  137. Begin
  138. Reset_reference(tmpref);
  139. Case Taicpu(p).oper[0].val Of
  140. 3: Begin
  141. {imul 3, reg1, reg2 to
  142. lea (reg1,reg1,2), reg2
  143. imul 3, reg1 to
  144. lea (reg1,reg1,2), reg1}
  145. TmpRef.base := Taicpu(p).oper[1].reg;
  146. TmpRef.Index := Taicpu(p).oper[1].reg;
  147. TmpRef.ScaleFactor := 2;
  148. If (Taicpu(p).oper[2].typ = Top_None) Then
  149. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg)
  150. Else
  151. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[2].reg);
  152. InsertLLItem(AsmL,p.previous, p.next, hp1);
  153. p.free;
  154. p := hp1;
  155. End;
  156. 5: Begin
  157. {imul 5, reg1, reg2 to
  158. lea (reg1,reg1,4), reg2
  159. imul 5, reg1 to
  160. lea (reg1,reg1,4), reg1}
  161. TmpRef.base := Taicpu(p).oper[1].reg;
  162. TmpRef.Index := Taicpu(p).oper[1].reg;
  163. TmpRef.ScaleFactor := 4;
  164. If (Taicpu(p).oper[2].typ = Top_None) Then
  165. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg)
  166. Else
  167. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[2].reg);
  168. InsertLLItem(AsmL,p.previous, p.next, hp1);
  169. p.free;
  170. p := hp1;
  171. End;
  172. 6: Begin
  173. {imul 6, reg1, reg2 to
  174. lea (,reg1,2), reg2
  175. lea (reg2,reg1,4), reg2
  176. imul 6, reg1 to
  177. lea (reg1,reg1,2), reg1
  178. add reg1, reg1}
  179. If (aktoptprocessor <= Class386)
  180. Then
  181. Begin
  182. TmpRef.Index := Taicpu(p).oper[1].reg;
  183. If (Taicpu(p).oper[2].typ = Top_Reg)
  184. Then
  185. Begin
  186. TmpRef.base := Taicpu(p).oper[2].reg;
  187. TmpRef.ScaleFactor := 4;
  188. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg);
  189. End
  190. Else
  191. Begin
  192. hp1 := Taicpu.op_reg_reg(A_ADD, S_L,
  193. Taicpu(p).oper[1].reg,Taicpu(p).oper[1].reg);
  194. End;
  195. InsertLLItem(AsmL,p, p.next, hp1);
  196. Reset_reference(tmpref);
  197. TmpRef.Index := Taicpu(p).oper[1].reg;
  198. TmpRef.ScaleFactor := 2;
  199. If (Taicpu(p).oper[2].typ = Top_Reg)
  200. Then
  201. Begin
  202. TmpRef.base := R_NO;
  203. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(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, newReference(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).oper[2].typ = Top_None) Then
  225. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg)
  226. Else
  227. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(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).oper[2].typ = Top_Reg) 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).oper[2].typ = Top_Reg)
  252. Then
  253. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[2].reg)
  254. Else
  255. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg);
  256. InsertLLItem(AsmL,p.previous, p.next, hp1);
  257. p.free;
  258. p := Tai(hp1.next);
  259. End
  260. End;
  261. 12: Begin
  262. {imul 12, reg1, reg2 to
  263. lea (,reg1,4), reg2
  264. lea (,reg1,8) reg2
  265. imul 12, reg1 to
  266. lea (reg1,reg1,2), reg1
  267. lea (,reg1,4), reg1}
  268. If (aktoptprocessor <= Class386)
  269. Then
  270. Begin
  271. TmpRef.Index := Taicpu(p).oper[1].reg;
  272. If (Taicpu(p).oper[2].typ = Top_Reg) Then
  273. Begin
  274. TmpRef.base := Taicpu(p).oper[2].reg;
  275. TmpRef.ScaleFactor := 8;
  276. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[2].reg);
  277. End
  278. Else
  279. Begin
  280. TmpRef.base := R_NO;
  281. TmpRef.ScaleFactor := 4;
  282. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg);
  283. End;
  284. InsertLLItem(AsmL,p, p.next, hp1);
  285. Reset_reference(tmpref);
  286. TmpRef.Index := Taicpu(p).oper[1].reg;
  287. If (Taicpu(p).oper[2].typ = Top_Reg) Then
  288. Begin
  289. TmpRef.base := R_NO;
  290. TmpRef.ScaleFactor := 4;
  291. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[2].reg);
  292. End
  293. Else
  294. Begin
  295. TmpRef.base := Taicpu(p).oper[1].reg;
  296. TmpRef.ScaleFactor := 2;
  297. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef), Taicpu(p).oper[1].reg);
  298. End;
  299. InsertLLItem(AsmL,p.previous, p.next, hp1);
  300. p.free;
  301. p := Tai(hp1.next);
  302. End
  303. End
  304. End;
  305. End;
  306. End;
  307. A_SAR, A_SHR:
  308. {changes the code sequence
  309. shr/sar const1, x
  310. shl const2, x
  311. to either "sar/and", "shl/and" or just "and" depending on const1 and const2}
  312. Begin
  313. If GetNextInstruction(p, hp1) And
  314. (Tai(hp1).typ = ait_instruction) and
  315. (Taicpu(hp1).opcode = A_SHL) and
  316. (Taicpu(p).oper[0].typ = top_const) and
  317. (Taicpu(hp1).oper[0].typ = top_const) and
  318. (Taicpu(hp1).opsize = Taicpu(p).opsize) And
  319. (Taicpu(hp1).oper[1].typ = Taicpu(p).oper[1].typ) And
  320. OpsEqual(Taicpu(hp1).oper[1], Taicpu(p).oper[1])
  321. Then
  322. If (Taicpu(p).oper[0].val > Taicpu(hp1).oper[0].val) And
  323. Not(CS_LittleSize In aktglobalswitches)
  324. Then
  325. { shr/sar const1, %reg
  326. shl const2, %reg
  327. with const1 > const2 }
  328. Begin
  329. Taicpu(p).LoadConst(0,Taicpu(p).oper[0].val-Taicpu(hp1).oper[0].val);
  330. Taicpu(hp1).opcode := A_AND;
  331. l := (1 shl (Taicpu(hp1).oper[0].val)) - 1;
  332. Case Taicpu(p).opsize Of
  333. S_L: Taicpu(hp1).LoadConst(0,l Xor longint(-1));
  334. S_B: Taicpu(hp1).LoadConst(0,l Xor $ff);
  335. S_W: Taicpu(hp1).LoadConst(0,l Xor $ffff);
  336. End;
  337. End
  338. Else
  339. If (Taicpu(p).oper[0].val<Taicpu(hp1).oper[0].val) And
  340. Not(CS_LittleSize In aktglobalswitches)
  341. Then
  342. { shr/sar const1, %reg
  343. shl const2, %reg
  344. with const1 < const2 }
  345. Begin
  346. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val-Taicpu(p).oper[0].val);
  347. Taicpu(p).opcode := A_AND;
  348. l := (1 shl (Taicpu(p).oper[0].val))-1;
  349. Case Taicpu(p).opsize Of
  350. S_L: Taicpu(p).LoadConst(0,l Xor longint($ffffffff));
  351. S_B: Taicpu(p).LoadConst(0,l Xor $ff);
  352. S_W: Taicpu(p).LoadConst(0,l Xor $ffff);
  353. End;
  354. End
  355. Else
  356. { shr/sar const1, %reg
  357. shl const2, %reg
  358. with const1 = const2 }
  359. if (Taicpu(p).oper[0].val = Taicpu(hp1).oper[0].val) then
  360. Begin
  361. Taicpu(p).opcode := A_AND;
  362. l := (1 shl (Taicpu(p).oper[0].val))-1;
  363. Case Taicpu(p).opsize Of
  364. S_B: Taicpu(p).LoadConst(0,l Xor $ff);
  365. S_W: Taicpu(p).LoadConst(0,l Xor $ffff);
  366. S_L: Taicpu(p).LoadConst(0,l Xor longint($ffffffff));
  367. End;
  368. asml.remove(hp1);
  369. hp1.free;
  370. End;
  371. End;
  372. A_XOR:
  373. If (Taicpu(p).oper[0].typ = top_reg) And
  374. (Taicpu(p).oper[1].typ = top_reg) And
  375. (Taicpu(p).oper[0].reg = Taicpu(p).oper[1].reg) then
  376. { temporarily change this to 'mov reg,0' to make it easier }
  377. { for the CSE. Will be changed back in pass 2 }
  378. begin
  379. Taicpu(p).opcode := A_MOV;
  380. Taicpu(p).loadconst(0,0);
  381. end;
  382. End;
  383. End;
  384. End;
  385. p := Tai(p.next)
  386. End;
  387. End;
  388. Procedure PeepHoleOptPass1(Asml: TAAsmOutput; BlockStart, BlockEnd: Tai);
  389. {First pass of peepholeoptimizations}
  390. Var
  391. l,l1 : longint;
  392. p,hp1,hp2 : Tai;
  393. hp3,hp4: Tai;
  394. TmpRef: TReference;
  395. UsedRegs, TmpUsedRegs: TRegSet;
  396. TmpBool1, TmpBool2: Boolean;
  397. Function SkipLabels(hp: Tai; var hp2: Tai): boolean;
  398. {skips all labels and returns the next "real" instruction}
  399. Begin
  400. While assigned(hp.next) and
  401. (Tai(hp.next).typ In SkipInstr + [ait_label,ait_align]) Do
  402. hp := Tai(hp.next);
  403. If assigned(hp.next) Then
  404. Begin
  405. SkipLabels := True;
  406. hp2 := Tai(hp.next)
  407. End
  408. Else
  409. Begin
  410. hp2 := hp;
  411. SkipLabels := False
  412. End;
  413. End;
  414. function GetFinalDestination(AsmL: TAAsmOutput; hp: Taicpu; level: longint): boolean;
  415. {traces sucessive jumps to their final destination and sets it, e.g.
  416. je l1 je l3
  417. <code> <code>
  418. l1: becomes l1:
  419. je l2 je l3
  420. <code> <code>
  421. l2: l2:
  422. jmp l3 jmp l3
  423. the level parameter denotes how deeep we have already followed the jump,
  424. to avoid endless loops with constructs such as "l5: ; jmp l5" }
  425. Var p1, p2: Tai;
  426. l: tasmlabel;
  427. Function FindAnyLabel(hp: Tai; var l: tasmlabel): Boolean;
  428. Begin
  429. FindAnyLabel := false;
  430. While assigned(hp.next) and
  431. (Tai(hp.next).typ In (SkipInstr+[ait_align])) Do
  432. hp := Tai(hp.next);
  433. If assigned(hp.next) and
  434. (Tai(hp.next).typ = ait_label) Then
  435. Begin
  436. FindAnyLabel := true;
  437. l := Tai_label(hp.next).l;
  438. End
  439. End;
  440. Begin
  441. if level > 20 then
  442. exit;
  443. GetfinalDestination := false;
  444. If (tasmlabel(hp.oper[0].sym).labelnr >= LoLab) and
  445. (tasmlabel(hp.oper[0].sym).labelnr <= HiLab) and {range check, a jump can go past an assembler block!}
  446. Assigned(LTable^[tasmlabel(hp.oper[0].sym).labelnr-LoLab].TaiObj) Then
  447. Begin
  448. p1 := LTable^[tasmlabel(hp.oper[0].sym).labelnr-LoLab].TaiObj; {the jump's destination}
  449. SkipLabels(p1,p1);
  450. If (Tai(p1).typ = ait_instruction) and
  451. (Taicpu(p1).is_jmp) Then
  452. If { the next instruction after the label where the jump hp arrives}
  453. { is unconditional or of the same type as hp, so continue }
  454. (Taicpu(p1).condition in [C_None,hp.condition]) or
  455. { the next instruction after the label where the jump hp arrives}
  456. { is the opposite of hp (so this one is never taken), but after }
  457. { that one there is a branch that will be taken, so perform a }
  458. { little hack: set p1 equal to this instruction (that's what the}
  459. { last SkipLabels is for, only works with short bool evaluation)}
  460. ((Taicpu(p1).condition = inverse_cond[hp.condition]) and
  461. SkipLabels(p1,p2) and
  462. (p2.typ = ait_instruction) and
  463. (Taicpu(p2).is_jmp) and
  464. (Taicpu(p2).condition in [C_None,hp.condition]) and
  465. SkipLabels(p1,p1)) Then
  466. Begin
  467. { quick check for loops of the form "l5: ; jmp l5 }
  468. if (tasmlabel(Taicpu(p1).oper[0].sym).labelnr =
  469. tasmlabel(hp.oper[0].sym).labelnr) then
  470. exit;
  471. if not GetFinalDestination(asml, Taicpu(p1),succ(level)) then
  472. exit;
  473. Dec(tasmlabel(hp.oper[0].sym).refs);
  474. hp.oper[0].sym:=Taicpu(p1).oper[0].sym;
  475. inc(tasmlabel(hp.oper[0].sym).refs);
  476. End
  477. Else
  478. If (Taicpu(p1).condition = inverse_cond[hp.condition]) then
  479. if not FindAnyLabel(p1,l) then
  480. begin
  481. {$ifdef finaldestdebug}
  482. insertllitem(asml,p1,p1.next,Tai_asm_comment.Create(
  483. strpnew('previous label inserted'))));
  484. {$endif finaldestdebug}
  485. getlabel(l);
  486. insertllitem(asml,p1,p1.next,Tai_label.Create(l));
  487. dec(tasmlabel(Taicpu(hp).oper[0].sym).refs);
  488. hp.oper[0].sym := l;
  489. inc(l.refs);
  490. { this won't work, since the new label isn't in the labeltable }
  491. { so it will fail the rangecheck. Labeltable should become a }
  492. { hashtable to support this: }
  493. { GetFinalDestination(asml, hp); }
  494. end
  495. else
  496. begin
  497. {$ifdef finaldestdebug}
  498. insertllitem(asml,p1,p1.next,Tai_asm_comment.Create(
  499. strpnew('next label reused'))));
  500. {$endif finaldestdebug}
  501. inc(l.refs);
  502. hp.oper[0].sym := l;
  503. if not GetFinalDestination(asml, hp,succ(level)) then
  504. exit;
  505. end;
  506. End;
  507. GetFinalDestination := true;
  508. End;
  509. Function DoSubAddOpt(var p: Tai): Boolean;
  510. Begin
  511. DoSubAddOpt := False;
  512. If GetLastInstruction(p, hp1) And
  513. (hp1.typ = ait_instruction) And
  514. (Taicpu(hp1).opsize = Taicpu(p).opsize) then
  515. Case Taicpu(hp1).opcode Of
  516. A_DEC:
  517. If (Taicpu(hp1).oper[0].typ = top_reg) And
  518. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg) Then
  519. Begin
  520. Taicpu(p).LoadConst(0,Taicpu(p).oper[0].val+1);
  521. asml.Remove(hp1);
  522. hp1.free;
  523. End;
  524. A_SUB:
  525. If (Taicpu(hp1).oper[0].typ = top_const) And
  526. (Taicpu(hp1).oper[1].typ = top_reg) And
  527. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg) Then
  528. Begin
  529. Taicpu(p).LoadConst(0,Taicpu(p).oper[0].val+Taicpu(hp1).oper[0].val);
  530. asml.Remove(hp1);
  531. hp1.free;
  532. End;
  533. A_ADD:
  534. If (Taicpu(hp1).oper[0].typ = top_const) And
  535. (Taicpu(hp1).oper[1].typ = top_reg) And
  536. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg) Then
  537. Begin
  538. Taicpu(p).LoadConst(0,Taicpu(p).oper[0].val-Taicpu(hp1).oper[0].val);
  539. asml.Remove(hp1);
  540. hp1.free;
  541. If (Taicpu(p).oper[0].val = 0) Then
  542. Begin
  543. hp1 := Tai(p.next);
  544. asml.Remove(p);
  545. p.free;
  546. If Not GetLastInstruction(hp1, p) Then
  547. p := hp1;
  548. DoSubAddOpt := True;
  549. End
  550. End;
  551. End;
  552. End;
  553. Begin
  554. P := BlockStart;
  555. UsedRegs := [];
  556. While (P <> BlockEnd) Do
  557. Begin
  558. UpDateUsedRegs(UsedRegs, Tai(p.next));
  559. Case p.Typ Of
  560. ait_instruction:
  561. Begin
  562. { Handle Jmp Optimizations }
  563. if Taicpu(p).is_jmp then
  564. begin
  565. {the following if-block removes all code between a jmp and the next label,
  566. because it can never be executed}
  567. If (Taicpu(p).opcode = A_JMP) Then
  568. Begin
  569. While GetNextInstruction(p, hp1) and
  570. (hp1.typ <> ait_label) do
  571. If not(hp1.typ in ([ait_label,ait_align]+skipinstr)) Then
  572. Begin
  573. asml.Remove(hp1);
  574. hp1.free;
  575. End
  576. else break;
  577. End;
  578. { remove jumps to a label coming right after them }
  579. If GetNextInstruction(p, hp1) then
  580. Begin
  581. if FindLabel(tasmlabel(Taicpu(p).oper[0].sym), hp1) then
  582. Begin
  583. hp2:=Tai(hp1.next);
  584. asml.remove(p);
  585. p.free;
  586. p:=hp2;
  587. continue;
  588. end
  589. Else
  590. Begin
  591. if hp1.typ = ait_label then
  592. SkipLabels(hp1,hp1);
  593. If (Tai(hp1).typ=ait_instruction) and
  594. (Taicpu(hp1).opcode=A_JMP) and
  595. GetNextInstruction(hp1, hp2) And
  596. FindLabel(tasmlabel(Taicpu(p).oper[0].sym), hp2)
  597. Then
  598. Begin
  599. if Taicpu(p).opcode=A_Jcc then
  600. Taicpu(p).condition:=inverse_cond[Taicpu(p).condition]
  601. else
  602. begin
  603. If (LabDif <> 0) Then
  604. GetFinalDestination(asml, Taicpu(p),0);
  605. p:=Tai(p.next);
  606. continue;
  607. end;
  608. Dec(Tai_label(hp2).l.refs);
  609. Taicpu(p).oper[0].sym:=Taicpu(hp1).oper[0].sym;
  610. Inc(Taicpu(p).oper[0].sym.refs);
  611. asml.remove(hp1);
  612. hp1.free;
  613. If (LabDif <> 0) Then
  614. GetFinalDestination(asml, Taicpu(p),0);
  615. end
  616. else
  617. If (LabDif <> 0) Then
  618. GetFinalDestination(asml, Taicpu(p),0);
  619. end;
  620. end;
  621. end
  622. else
  623. { All other optimizes }
  624. begin
  625. For l := 0 to 2 Do
  626. If (Taicpu(p).oper[l].typ = top_ref) Then
  627. With Taicpu(p).oper[l].ref^ Do
  628. Begin
  629. If (base = R_NO) And
  630. (index <> R_NO) And
  631. (scalefactor in [0,1])
  632. Then
  633. Begin
  634. base := index;
  635. index := R_NO
  636. End
  637. End;
  638. Case Taicpu(p).opcode Of
  639. A_AND:
  640. Begin
  641. If (Taicpu(p).oper[0].typ = top_const) And
  642. (Taicpu(p).oper[1].typ = top_reg) And
  643. GetNextInstruction(p, hp1) And
  644. (Tai(hp1).typ = ait_instruction) And
  645. (Taicpu(hp1).opcode = A_AND) And
  646. (Taicpu(hp1).oper[0].typ = top_const) And
  647. (Taicpu(hp1).oper[1].typ = top_reg) And
  648. (Taicpu(hp1).oper[1].reg = Taicpu(hp1).oper[1].reg)
  649. Then
  650. {change "and const1, reg; and const2, reg" to "and (const1 and const2), reg"}
  651. Begin
  652. Taicpu(p).LoadConst(0,Taicpu(p).oper[0].val And Taicpu(hp1).oper[0].val);
  653. asml.Remove(hp1);
  654. hp1.free;
  655. End
  656. Else
  657. {change "and x, reg; jxx" to "test x, reg", if reg is deallocated before the
  658. jump, but only if it's a conditional jump (PFV) }
  659. If (Taicpu(p).oper[1].typ = top_reg) And
  660. GetNextInstruction(p, hp1) And
  661. (hp1.typ = ait_instruction) And
  662. (Taicpu(hp1).is_jmp) and
  663. (Taicpu(hp1).opcode<>A_JMP) and
  664. Not(Taicpu(p).oper[1].reg in UsedRegs) Then
  665. Taicpu(p).opcode := A_TEST;
  666. End;
  667. A_CMP:
  668. Begin
  669. If (Taicpu(p).oper[0].typ = top_const) And
  670. (Taicpu(p).oper[1].typ in [top_reg,top_ref]) And
  671. (Taicpu(p).oper[0].val = 0) Then
  672. If GetNextInstruction(p, hp1) And
  673. (hp1.typ = ait_instruction) And
  674. (Taicpu(hp1).is_jmp) and
  675. (Taicpu(hp1).opcode=A_Jcc) and
  676. (Taicpu(hp1).condition in [C_LE,C_BE]) and
  677. GetNextInstruction(hp1,hp2) and
  678. (hp2.typ = ait_instruction) and
  679. (Taicpu(hp2).opcode = A_DEC) And
  680. OpsEqual(Taicpu(hp2).oper[0],Taicpu(p).oper[1]) And
  681. GetNextInstruction(hp2, hp3) And
  682. (hp3.typ = ait_instruction) and
  683. (Taicpu(hp3).is_jmp) and
  684. (Taicpu(hp3).opcode = A_JMP) And
  685. GetNextInstruction(hp3, hp4) And
  686. FindLabel(tasmlabel(Taicpu(hp1).oper[0].sym),hp4)
  687. Then
  688. Begin
  689. Taicpu(hp2).Opcode := A_SUB;
  690. Taicpu(hp2).Loadoper(1,Taicpu(hp2).oper[0]);
  691. Taicpu(hp2).LoadConst(0,1);
  692. Taicpu(hp2).ops:=2;
  693. Taicpu(hp3).Opcode := A_Jcc;
  694. Case Taicpu(hp1).condition of
  695. C_LE: Taicpu(hp3).condition := C_GE;
  696. C_BE: Taicpu(hp3).condition := C_AE;
  697. End;
  698. asml.Remove(p);
  699. asml.Remove(hp1);
  700. p.free;
  701. hp1.free;
  702. p := hp2;
  703. continue;
  704. End
  705. Else
  706. {change "cmp $0, %reg" to "test %reg, %reg"}
  707. If (Taicpu(p).oper[1].typ = top_reg) Then
  708. Begin
  709. Taicpu(p).opcode := A_TEST;
  710. Taicpu(p).loadreg(0,Taicpu(p).oper[1].reg);
  711. End;
  712. End;
  713. A_FLD:
  714. Begin
  715. If (Taicpu(p).oper[0].typ = top_reg) And
  716. GetNextInstruction(p, hp1) And
  717. (hp1.typ = Ait_Instruction) And
  718. (Taicpu(hp1).oper[0].typ = top_reg) And
  719. (Taicpu(hp1).oper[1].typ = top_reg) And
  720. (Taicpu(hp1).oper[0].reg = R_ST) And
  721. (Taicpu(hp1).oper[1].reg = R_ST1) Then
  722. { change to
  723. fld reg fxxx reg,st
  724. fxxxp st, st1 (hp1)
  725. Remark: non commutative operations must be reversed!
  726. }
  727. begin
  728. Case Taicpu(hp1).opcode Of
  729. A_FMULP,A_FADDP,
  730. A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
  731. begin
  732. Case Taicpu(hp1).opcode Of
  733. A_FADDP: Taicpu(hp1).opcode := A_FADD;
  734. A_FMULP: Taicpu(hp1).opcode := A_FMUL;
  735. A_FSUBP: Taicpu(hp1).opcode := A_FSUBR;
  736. A_FSUBRP: Taicpu(hp1).opcode := A_FSUB;
  737. A_FDIVP: Taicpu(hp1).opcode := A_FDIVR;
  738. A_FDIVRP: Taicpu(hp1).opcode := A_FDIV;
  739. End;
  740. Taicpu(hp1).oper[0].reg := Taicpu(p).oper[0].reg;
  741. Taicpu(hp1).oper[1].reg := R_ST;
  742. asml.Remove(p);
  743. p.free;
  744. p := hp1;
  745. Continue;
  746. end;
  747. end;
  748. end
  749. else
  750. If (Taicpu(p).oper[0].typ = top_ref) And
  751. GetNextInstruction(p, hp2) And
  752. (hp2.typ = Ait_Instruction) And
  753. (Taicpu(hp2).oper[0].typ = top_reg) And
  754. (Taicpu(hp2).oper[1].typ = top_reg) And
  755. (Taicpu(p).opsize in [S_FS, S_FL]) And
  756. (Taicpu(hp2).oper[0].reg = R_ST) And
  757. (Taicpu(hp2).oper[1].reg = R_ST1) Then
  758. If GetLastInstruction(p, hp1) And
  759. (hp1.typ = Ait_Instruction) And
  760. ((Taicpu(hp1).opcode = A_FLD) Or
  761. (Taicpu(hp1).opcode = A_FST)) And
  762. (Taicpu(hp1).opsize = Taicpu(p).opsize) And
  763. (Taicpu(hp1).oper[0].typ = top_ref) And
  764. RefsEqual(Taicpu(p).oper[0].ref^, Taicpu(hp1).oper[0].ref^) Then
  765. If ((Taicpu(hp2).opcode = A_FMULP) Or
  766. (Taicpu(hp2).opcode = A_FADDP)) Then
  767. { change to
  768. fld/fst mem1 (hp1) fld/fst mem1
  769. fld mem1 (p) fadd/
  770. faddp/ fmul st, st
  771. fmulp st, st1 (hp2) }
  772. Begin
  773. asml.Remove(p);
  774. p.free;
  775. p := hp1;
  776. If (Taicpu(hp2).opcode = A_FADDP) Then
  777. Taicpu(hp2).opcode := A_FADD
  778. Else
  779. Taicpu(hp2).opcode := A_FMUL;
  780. Taicpu(hp2).oper[1].reg := R_ST;
  781. End
  782. Else
  783. { change to
  784. fld/fst mem1 (hp1) fld/fst mem1
  785. fld mem1 (p) fld st}
  786. Begin
  787. Taicpu(p).changeopsize(S_FL);
  788. Taicpu(p).loadreg(0,R_ST);
  789. End
  790. Else
  791. Begin
  792. Case Taicpu(hp2).opcode Of
  793. A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
  794. { change to
  795. fld/fst mem1 (hp1) fld/fst mem1
  796. fld mem2 (p) fxxx mem2
  797. fxxxp st, st1 (hp2) }
  798. Begin
  799. Case Taicpu(hp2).opcode Of
  800. A_FADDP: Taicpu(p).opcode := A_FADD;
  801. A_FMULP: Taicpu(p).opcode := A_FMUL;
  802. A_FSUBP: Taicpu(p).opcode := A_FSUBR;
  803. A_FSUBRP: Taicpu(p).opcode := A_FSUB;
  804. A_FDIVP: Taicpu(p).opcode := A_FDIVR;
  805. A_FDIVRP: Taicpu(p).opcode := A_FDIV;
  806. End;
  807. asml.Remove(hp2);
  808. hp2.free;
  809. End
  810. End
  811. End
  812. End;
  813. A_FSTP,A_FISTP:
  814. if doFpuLoadStoreOpt(asmL,p) then
  815. continue;
  816. A_LEA:
  817. Begin
  818. {removes seg register prefixes from LEA operations, as they
  819. don't do anything}
  820. Taicpu(p).oper[0].ref^.Segment := R_NO;
  821. {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
  822. If (Taicpu(p).oper[0].ref^.Base In [R_EAX..R_EDI]) And
  823. (Taicpu(p).oper[0].ref^.Index = R_NO) And
  824. (Not(Assigned(Taicpu(p).oper[0].ref^.Symbol))) Then
  825. If (Taicpu(p).oper[0].ref^.Base <> Taicpu(p).oper[1].reg)
  826. and (Taicpu(p).oper[0].ref^.Offset = 0)
  827. Then
  828. Begin
  829. hp1 := Taicpu.op_reg_reg(A_MOV, S_L,Taicpu(p).oper[0].ref^.Base,
  830. Taicpu(p).oper[1].reg);
  831. InsertLLItem(AsmL,p.previous,p.next, hp1);
  832. p.free;
  833. p := hp1;
  834. Continue;
  835. End
  836. Else
  837. if (Taicpu(p).oper[0].ref^.Offset = 0) then
  838. Begin
  839. hp1 := Tai(p.Next);
  840. asml.Remove(p);
  841. p.free;
  842. p := hp1;
  843. Continue;
  844. End
  845. else
  846. with Taicpu(p).oper[0].ref^ do
  847. if (Base = Taicpu(p).oper[1].reg) then
  848. begin
  849. l := offset+offsetfixup;
  850. case l of
  851. 1,-1:
  852. begin
  853. if l = 1 then
  854. Taicpu(p).opcode := A_INC
  855. else 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,offset+offsetfixup);
  863. end;
  864. end;
  865. end;
  866. End;
  867. A_MOV:
  868. Begin
  869. TmpUsedRegs := UsedRegs;
  870. If (Taicpu(p).oper[1].typ = top_reg) And
  871. (Taicpu(p).oper[1].reg In [R_EAX, R_EBX, R_EDX, R_EDI]) And
  872. GetNextInstruction(p, hp1) And
  873. (Tai(hp1).typ = ait_instruction) And
  874. (Taicpu(hp1).opcode = A_MOV) And
  875. (Taicpu(hp1).oper[0].typ = top_reg) And
  876. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg)
  877. Then
  878. {we have "mov x, %treg; mov %treg, y}
  879. If not(RegUsedAfterInstruction(Taicpu(p).oper[1].reg, hp1, TmpUsedRegs)) then
  880. {we've got "mov x, %treg; mov %treg, y; with %treg is not used after }
  881. Case Taicpu(p).oper[0].typ Of
  882. top_reg:
  883. Begin
  884. { change "mov %reg, %treg; mov %treg, y"
  885. to "mov %reg, y" }
  886. Taicpu(p).LoadOper(1,Taicpu(hp1).oper[1]);
  887. asml.Remove(hp1);
  888. hp1.free;
  889. continue;
  890. End;
  891. top_ref:
  892. If (Taicpu(hp1).oper[1].typ = top_reg) Then
  893. Begin
  894. { change "mov mem, %treg; mov %treg, %reg"
  895. to "mov mem, %reg" }
  896. Taicpu(p).Loadoper(1,Taicpu(hp1).oper[1]);
  897. asml.Remove(hp1);
  898. hp1.free;
  899. continue;
  900. End;
  901. End
  902. Else
  903. Else
  904. {Change "mov %reg1, %reg2; xxx %reg2, ???" to
  905. "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
  906. penalty}
  907. If (Taicpu(p).oper[0].typ = top_reg) And
  908. (Taicpu(p).oper[1].typ = top_reg) And
  909. GetNextInstruction(p,hp1) And
  910. (Tai(hp1).typ = ait_instruction) And
  911. (Taicpu(hp1).oper[0].typ = top_reg) And
  912. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg)
  913. Then
  914. {we have "mov %reg1, %reg2; XXX %reg2, ???"}
  915. Begin
  916. If ((Taicpu(hp1).opcode = A_OR) Or
  917. (Taicpu(hp1).opcode = A_TEST)) And
  918. (Taicpu(hp1).oper[1].typ = top_reg) And
  919. (Taicpu(hp1).oper[0].reg = Taicpu(hp1).oper[1].reg)
  920. Then
  921. {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
  922. Begin
  923. TmpUsedRegs := UsedRegs;
  924. { reg1 will be used after the first instruction, }
  925. { so update the allocation info }
  926. allocRegBetween(asmL,Taicpu(p).oper[0].reg,p,hp1);
  927. If GetNextInstruction(hp1, hp2) And
  928. (hp2.typ = ait_instruction) And
  929. Taicpu(hp2).is_jmp and
  930. Not(RegUsedAfterInstruction(Taicpu(hp1).oper[0].reg, hp1, TmpUsedRegs))
  931. Then
  932. {change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
  933. "test %reg1, %reg1; jxx"}
  934. Begin
  935. Taicpu(hp1).Loadoper(0,Taicpu(p).oper[0]);
  936. Taicpu(hp1).Loadoper(1,Taicpu(p).oper[0]);
  937. asml.Remove(p);
  938. p.free;
  939. p := hp1;
  940. continue
  941. End
  942. Else
  943. {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
  944. "mov %reg1, %reg2; test/or %reg1, %reg1"}
  945. Begin
  946. Taicpu(hp1).Loadoper(0,Taicpu(p).oper[0]);
  947. Taicpu(hp1).Loadoper(1,Taicpu(p).oper[0]);
  948. End;
  949. End
  950. { Else
  951. If (Taicpu(p.next)^.opcode
  952. In [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
  953. {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
  954. "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
  955. End
  956. Else
  957. {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
  958. x >= RetOffset) as it doesn't do anything (it writes either to a
  959. parameter or to the temporary storage room for the function
  960. result)}
  961. If GetNextInstruction(p, hp1) And
  962. (Tai(hp1).typ = ait_instruction)
  963. Then
  964. If ((Taicpu(hp1).opcode = A_LEAVE) Or
  965. (Taicpu(hp1).opcode = A_RET)) And
  966. (Taicpu(p).oper[1].typ = top_ref) And
  967. (Taicpu(p).oper[1].ref^.base = procinfo^.FramePointer) And
  968. (Taicpu(p).oper[1].ref^.offset >= procinfo^.Return_Offset) And
  969. (Taicpu(p).oper[1].ref^.index = R_NO) And
  970. (Taicpu(p).oper[0].typ = top_reg)
  971. Then
  972. Begin
  973. asml.Remove(p);
  974. p.free;
  975. p := hp1;
  976. RemoveLastDeallocForFuncRes(asmL,p);
  977. End
  978. Else
  979. If (Taicpu(p).oper[0].typ = top_reg) And
  980. (Taicpu(p).oper[1].typ = top_ref) And
  981. (Taicpu(p).opsize = Taicpu(hp1).opsize) And
  982. (Taicpu(hp1).opcode = A_CMP) And
  983. (Taicpu(hp1).oper[1].typ = top_ref) And
  984. RefsEqual(Taicpu(p).oper[1].ref^, Taicpu(hp1).oper[1].ref^) Then
  985. {change "mov reg1, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
  986. begin
  987. Taicpu(hp1).loadreg(1,Taicpu(p).oper[0].reg);
  988. allocRegBetween(asmL,Taicpu(p).oper[0].reg,p,hp1);
  989. end;
  990. { Next instruction is also a MOV ? }
  991. If GetNextInstruction(p, hp1) And
  992. (Tai(hp1).typ = ait_instruction) and
  993. (Taicpu(hp1).opcode = A_MOV) and
  994. (Taicpu(hp1).opsize = Taicpu(p).opsize)
  995. Then
  996. Begin
  997. If (Taicpu(hp1).oper[0].typ = Taicpu(p).oper[1].typ) and
  998. (Taicpu(hp1).oper[1].typ = Taicpu(p).oper[0].typ)
  999. Then
  1000. {mov reg1, mem1 or mov mem1, reg1
  1001. mov mem2, reg2 mov reg2, mem2}
  1002. Begin
  1003. If OpsEqual(Taicpu(hp1).oper[1],Taicpu(p).oper[0]) Then
  1004. {mov reg1, mem1 or mov mem1, reg1
  1005. mov mem2, reg1 mov reg2, mem1}
  1006. Begin
  1007. If OpsEqual(Taicpu(hp1).oper[0],Taicpu(p).oper[1]) Then
  1008. { Removes the second statement from
  1009. mov reg1, mem1/reg2
  1010. mov mem1/reg2, reg1 }
  1011. Begin
  1012. if (Taicpu(p).oper[0].typ = top_reg) then
  1013. AllocRegBetween(asmL,Taicpu(p).oper[0].reg,p,hp1);
  1014. asml.remove(hp1);
  1015. hp1.free;
  1016. End
  1017. Else
  1018. Begin
  1019. TmpUsedRegs := UsedRegs;
  1020. UpdateUsedRegs(TmpUsedRegs, Tai(hp1.next));
  1021. If (Taicpu(p).oper[0].typ = top_reg) And
  1022. { mov reg1, mem1
  1023. mov mem2, reg1 }
  1024. GetNextInstruction(hp1, hp2) And
  1025. (hp2.typ = ait_instruction) And
  1026. (Taicpu(hp2).opcode = A_CMP) And
  1027. (Taicpu(hp2).opsize = Taicpu(p).opsize) and
  1028. (Taicpu(hp2).oper[0].typ = TOp_Ref) And
  1029. (Taicpu(hp2).oper[1].typ = TOp_Reg) And
  1030. RefsEqual(Taicpu(hp2).oper[0].ref^, Taicpu(p).oper[1].ref^) And
  1031. (Taicpu(hp2).oper[1].reg = Taicpu(p).oper[0].reg) And
  1032. Not(RegUsedAfterInstruction(Taicpu(p).oper[0].reg, hp2, TmpUsedRegs)) Then
  1033. { change to
  1034. mov reg1, mem1 mov reg1, mem1
  1035. mov mem2, reg1 cmp reg1, mem2
  1036. cmp mem1, reg1 }
  1037. Begin
  1038. asml.Remove(hp2);
  1039. hp2.free;
  1040. Taicpu(hp1).opcode := A_CMP;
  1041. Taicpu(hp1).loadref(1,newreference(Taicpu(hp1).oper[0].ref^));
  1042. Taicpu(hp1).loadreg(0,Taicpu(p).oper[0].reg);
  1043. End;
  1044. End;
  1045. End
  1046. Else
  1047. Begin
  1048. tmpUsedRegs := UsedRegs;
  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 = Taicpu(p).oper[1].reg) 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 in [R_DI,R_EDI]) and
  1063. not(RegUsedAfterInstruction(R_EDI,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 <> Taicpu(hp2).oper[1].reg) 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,newreference(Taicpu(p).oper[0].ref^));
  1098. Taicpu(hp1).LoadReg(1,Taicpu(hp2).oper[1].reg);
  1099. Taicpu(hp2).LoadRef(1,newreference(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 in (usableregs+[R_EDI])) then
  1103. allocRegBetween(asmL,Taicpu(p).oper[0].ref^.base,p,hp2);
  1104. if (Taicpu(p).oper[0].ref^.index in (usableregs+[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 <> Taicpu(hp2).Oper[1].reg) 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 := TaiRegalloc.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,newreference(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 = Taicpu(p).oper[1].reg)
  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 (Taicpu(p).oper[0].reg = Reg16ToReg8(Taicpu(p).oper[1].reg)) 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 = Taicpu(p).oper[1].reg)
  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,Reg8ToReg16(Taicpu(p).oper[0].reg));
  1215. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ff);
  1216. End;
  1217. End;
  1218. S_BL:
  1219. Begin
  1220. If (Taicpu(p).oper[0].reg = Reg32ToReg8(Taicpu(p).oper[1].reg)) 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 = Taicpu(p).oper[1].reg)
  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,Reg8ToReg32(Taicpu(p).oper[0].reg));
  1243. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ff);
  1244. End
  1245. End;
  1246. S_WL:
  1247. Begin
  1248. If (Taicpu(p).oper[0].reg = Reg32ToReg16(Taicpu(p).oper[1].reg)) 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 = Taicpu(p).oper[1].reg)
  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,Reg16ToReg32(Taicpu(p).oper[0].reg));
  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 = Taicpu(p).oper[1].reg) 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.target=target_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 = Taicpu(hp2).oper[0].reg) 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. reset_reference(tmpref);
  1343. tmpRef.base := stack_pointer;
  1344. tmpRef.offset := l;
  1345. Taicpu(hp2).loadRef(0,newReference(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=Taicpu(p).oper[0].reg) 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. Reset_reference(tmpref);
  1380. TmpRef.base := R_ESP;
  1381. Taicpu(p).LoadRef(0,newReference(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. Reset_reference(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 = Taicpu(p).oper[1].reg) Do
  1425. Begin
  1426. TmpBool1 := False;
  1427. If (Taicpu(hp1).oper[0].typ = Top_Const)
  1428. Then
  1429. Begin
  1430. TmpBool1 := True;
  1431. TmpBool2 := True;
  1432. If Taicpu(hp1).opcode = A_ADD Then
  1433. Inc(TmpRef.offset, Taicpu(hp1).oper[0].val)
  1434. Else
  1435. Dec(TmpRef.offset, Taicpu(hp1).oper[0].val);
  1436. asml.Remove(hp1);
  1437. hp1.free;
  1438. End
  1439. Else
  1440. If (Taicpu(hp1).oper[0].typ = Top_Reg) And
  1441. (Taicpu(hp1).opcode = A_ADD) And
  1442. (TmpRef.base = R_NO) Then
  1443. Begin
  1444. TmpBool1 := True;
  1445. TmpBool2 := True;
  1446. TmpRef.base := Taicpu(hp1).oper[0].reg;
  1447. asml.Remove(hp1);
  1448. hp1.free;
  1449. End;
  1450. End;
  1451. If TmpBool2 Or
  1452. ((aktoptprocessor < ClassP6) And
  1453. (Taicpu(p).oper[0].val <= 3) And
  1454. Not(CS_LittleSize in aktglobalswitches))
  1455. Then
  1456. Begin
  1457. If Not(TmpBool2) And
  1458. (Taicpu(p).oper[0].val = 1)
  1459. Then
  1460. Begin
  1461. hp1 := Taicpu.Op_reg_reg(A_ADD,Taicpu(p).opsize,
  1462. Taicpu(p).oper[1].reg, Taicpu(p).oper[1].reg)
  1463. End
  1464. Else hp1 := Taicpu.op_ref_reg(A_LEA, S_L, newReference(TmpRef),
  1465. Taicpu(p).oper[1].reg);
  1466. InsertLLItem(AsmL,p.previous, p.next, hp1);
  1467. p.free;
  1468. p := hp1;
  1469. End;
  1470. End
  1471. Else
  1472. If (aktoptprocessor < ClassP6) And
  1473. (Taicpu(p).oper[0].typ = top_const) And
  1474. (Taicpu(p).oper[1].typ = top_reg) Then
  1475. If (Taicpu(p).oper[0].val = 1)
  1476. Then
  1477. {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
  1478. but faster on a 486, and Tairable in both U and V pipes on the Pentium
  1479. (unlike shl, which is only Tairable in the U pipe)}
  1480. Begin
  1481. hp1 := Taicpu.Op_reg_reg(A_ADD,Taicpu(p).opsize,
  1482. Taicpu(p).oper[1].reg, Taicpu(p).oper[1].reg);
  1483. InsertLLItem(AsmL,p.previous, p.next, hp1);
  1484. p.free;
  1485. p := hp1;
  1486. End
  1487. Else If (Taicpu(p).opsize = S_L) and
  1488. (Taicpu(p).oper[0].val<= 3) Then
  1489. {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
  1490. "shl $3, %reg" to "lea (,%reg,8), %reg}
  1491. Begin
  1492. Reset_reference(tmpref);
  1493. TmpRef.index := Taicpu(p).oper[1].reg;
  1494. TmpRef.scalefactor := 1 shl Taicpu(p).oper[0].val;
  1495. hp1 := Taicpu.Op_ref_reg(A_LEA,S_L,newReference(TmpRef), Taicpu(p).oper[1].reg);
  1496. InsertLLItem(AsmL,p.previous, p.next, hp1);
  1497. p.free;
  1498. p := hp1;
  1499. End
  1500. End;
  1501. A_SETcc :
  1502. { changes
  1503. setcc (funcres) setcc reg
  1504. movb (funcres), reg to leave/ret
  1505. leave/ret }
  1506. Begin
  1507. If (Taicpu(p).oper[0].typ = top_ref) And
  1508. GetNextInstruction(p, hp1) And
  1509. GetNextInstruction(hp1, hp2) And
  1510. (hp2.typ = ait_instruction) And
  1511. ((Taicpu(hp2).opcode = A_LEAVE) or
  1512. (Taicpu(hp2).opcode = A_RET)) And
  1513. (Taicpu(p).oper[0].ref^.Base = procinfo^.FramePointer) And
  1514. (Taicpu(p).oper[0].ref^.Index = R_NO) And
  1515. (Taicpu(p).oper[0].ref^.Offset >= procinfo^.Return_Offset) And
  1516. (hp1.typ = ait_instruction) And
  1517. (Taicpu(hp1).opcode = A_MOV) And
  1518. (Taicpu(hp1).opsize = S_B) And
  1519. (Taicpu(hp1).oper[0].typ = top_ref) And
  1520. RefsEqual(Taicpu(hp1).oper[0].ref^, Taicpu(p).oper[0].ref^) Then
  1521. Begin
  1522. Taicpu(p).LoadReg(0,Taicpu(hp1).oper[1].reg);
  1523. asml.Remove(hp1);
  1524. hp1.free;
  1525. End
  1526. End;
  1527. A_SUB:
  1528. { * change "subl $2, %esp; pushw x" to "pushl x"}
  1529. { * change "sub/add const1, reg" or "dec reg" followed by
  1530. "sub const2, reg" to one "sub ..., reg" }
  1531. Begin
  1532. If (Taicpu(p).oper[0].typ = top_const) And
  1533. (Taicpu(p).oper[1].typ = top_reg) Then
  1534. If (Taicpu(p).oper[0].val = 2) And
  1535. (Taicpu(p).oper[1].reg = R_ESP) and
  1536. { Don't do the sub/push optimization if the sub }
  1537. { comes from setting up the stack frame (JM) }
  1538. (not getLastInstruction(p,hp1) or
  1539. (hp1.typ <> ait_instruction) or
  1540. (Taicpu(hp1).opcode <> A_MOV) or
  1541. (Taicpu(hp1).oper[0].typ <> top_reg) or
  1542. (Taicpu(hp1).oper[0].reg <> R_ESP) or
  1543. (Taicpu(hp1).oper[1].typ <> top_reg) or
  1544. (Taicpu(hp1).oper[1].reg <> R_EBP)) then
  1545. Begin
  1546. hp1 := Tai(p.next);
  1547. While Assigned(hp1) And
  1548. (Tai(hp1).typ In [ait_instruction]+SkipInstr) And
  1549. not regReadByInstruction(R_ESP,hp1) and
  1550. not regModifiedByInstruction(R_ESP,hp1) do
  1551. hp1 := Tai(hp1.next);
  1552. If Assigned(hp1) And
  1553. (Tai(hp1).typ = ait_instruction) And
  1554. (Taicpu(hp1).opcode = A_PUSH) And
  1555. (Taicpu(hp1).opsize = S_W)
  1556. Then
  1557. Begin
  1558. Taicpu(hp1).changeopsize(S_L);
  1559. if Taicpu(hp1).oper[0].typ=top_reg then
  1560. Taicpu(hp1).LoadReg(0,Reg16ToReg32(Taicpu(hp1).oper[0].reg));
  1561. hp1 := Tai(p.next);
  1562. asml.Remove(p);
  1563. p.free;
  1564. p := hp1;
  1565. Continue
  1566. End;
  1567. If DoSubAddOpt(p) Then continue;
  1568. End
  1569. Else If DoSubAddOpt(p) Then Continue
  1570. End;
  1571. A_XOR:
  1572. If (Taicpu(p).oper[0].typ = top_reg) And
  1573. (Taicpu(p).oper[1].typ = top_reg) And
  1574. (Taicpu(p).oper[0].reg = Taicpu(p).oper[1].reg) then
  1575. { temporarily change this to 'mov reg,0' to make it easier }
  1576. { for the CSE. Will be changed back in pass 2 }
  1577. begin
  1578. Taicpu(p).opcode := A_MOV;
  1579. Taicpu(p).loadconst(0,0);
  1580. end;
  1581. End;
  1582. end; { if is_jmp }
  1583. End;
  1584. { ait_label:
  1585. Begin
  1586. If labelCanBeSkipped(Tai_label(p))
  1587. Then
  1588. Begin
  1589. hp1 := Tai(p.next);
  1590. asml.Remove(p);
  1591. p.free;
  1592. p := hp1;
  1593. Continue
  1594. End;
  1595. End;}
  1596. End;
  1597. p:=Tai(p.next);
  1598. end;
  1599. end;
  1600. function isFoldableArithOp(hp1: Taicpu; reg: tregister): boolean;
  1601. begin
  1602. IsFoldableArithOp := False;
  1603. case hp1.opcode of
  1604. A_ADD,A_SUB,A_OR,A_XOR,A_AND,A_SHL,A_SHR,A_SAR:
  1605. isFoldableArithOp :=
  1606. ((Taicpu(hp1).oper[0].typ = top_const) or
  1607. ((Taicpu(hp1).oper[0].typ = top_reg) and
  1608. (Taicpu(hp1).oper[0].reg <> reg))) and
  1609. (Taicpu(hp1).oper[1].typ = top_reg) and
  1610. (Taicpu(hp1).oper[1].reg = reg);
  1611. A_INC,A_DEC:
  1612. isFoldableArithOp :=
  1613. (Taicpu(hp1).oper[0].typ = top_reg) and
  1614. (Taicpu(hp1).oper[0].reg = reg);
  1615. end;
  1616. end;
  1617. Procedure PeepHoleOptPass2(AsmL: TAAsmOutput; BlockStart, BlockEnd: Tai);
  1618. {$ifdef USECMOV}
  1619. function CanBeCMOV(p : Tai) : boolean;
  1620. begin
  1621. CanBeCMOV:=assigned(p) and (p.typ=ait_instruction) and
  1622. (Taicpu(p).opcode=A_MOV) and
  1623. (Taicpu(p).opsize in [S_L,S_W]) and
  1624. (Taicpu(p).oper[0].typ in [top_reg,top_ref]) and
  1625. (Taicpu(p).oper[1].typ in [top_reg]);
  1626. end;
  1627. {$endif USECMOV}
  1628. var
  1629. p,hp1,hp2: Tai;
  1630. {$ifdef USECMOV}
  1631. l : longint;
  1632. condition : tasmcond;
  1633. hp3: Tai;
  1634. {$endif USECMOV}
  1635. UsedRegs, TmpUsedRegs: TRegSet;
  1636. Begin
  1637. P := BlockStart;
  1638. UsedRegs := [];
  1639. While (P <> BlockEnd) Do
  1640. Begin
  1641. UpdateUsedRegs(UsedRegs, Tai(p.next));
  1642. Case p.Typ Of
  1643. Ait_Instruction:
  1644. Begin
  1645. Case Taicpu(p).opcode Of
  1646. {$ifdef USECMOV}
  1647. A_Jcc:
  1648. if (aktspecificoptprocessor=ClassP6) then
  1649. begin
  1650. { check for
  1651. jCC xxx
  1652. <several movs>
  1653. xxx:
  1654. }
  1655. l:=0;
  1656. GetNextInstruction(p, hp1);
  1657. while assigned(hp1) And
  1658. CanBeCMOV(hp1) do
  1659. begin
  1660. inc(l);
  1661. GetNextInstruction(hp1,hp1);
  1662. end;
  1663. if assigned(hp1) then
  1664. begin
  1665. if FindLabel(tasmlabel(Taicpu(p).oper[0].sym),hp1) then
  1666. begin
  1667. if (l<=4) and (l>0) then
  1668. begin
  1669. condition:=inverse_cond[Taicpu(p).condition];
  1670. GetNextInstruction(p,hp1);
  1671. asml.remove(p);
  1672. p.free;
  1673. p:=hp1;
  1674. repeat
  1675. Taicpu(hp1).opcode:=A_CMOVcc;
  1676. Taicpu(hp1).condition:=condition;
  1677. GetNextInstruction(hp1,hp1);
  1678. until not(assigned(hp1)) or
  1679. not(CanBeCMOV(hp1));
  1680. asml.remove(hp1);
  1681. hp1.free;
  1682. continue;
  1683. end;
  1684. end
  1685. else
  1686. begin
  1687. { check further for
  1688. jCC xxx
  1689. <several movs>
  1690. jmp yyy
  1691. xxx:
  1692. <several movs>
  1693. yyy:
  1694. }
  1695. { hp2 points to jmp xxx }
  1696. hp2:=hp1;
  1697. { skip hp1 to xxx }
  1698. GetNextInstruction(hp1, hp1);
  1699. if assigned(hp2) and
  1700. assigned(hp1) and
  1701. (l<=3) and
  1702. (hp2.typ=ait_instruction) and
  1703. (Taicpu(hp2).is_jmp) and
  1704. (Taicpu(hp2).condition=C_None) and
  1705. FindLabel(tasmlabel(Taicpu(p).oper[0].sym),hp1) then
  1706. begin
  1707. l:=0;
  1708. while assigned(hp1) And
  1709. CanBeCMOV(hp1) do
  1710. begin
  1711. inc(l);
  1712. GetNextInstruction(hp1, hp1);
  1713. end;
  1714. end;
  1715. {
  1716. if assigned(hp1) and
  1717. FindLabel(tasmlabel(Taicpu(hp2).oper[0].sym),hp1) then
  1718. begin
  1719. condition:=inverse_cond[Taicpu(p).condition];
  1720. GetNextInstruction(p,hp1);
  1721. asml.remove(p);
  1722. p.free;
  1723. p:=hp1;
  1724. repeat
  1725. Taicpu(hp1).opcode:=A_CMOVcc;
  1726. Taicpu(hp1).condition:=condition;
  1727. GetNextInstruction(hp1,hp1);
  1728. until not(assigned(hp1)) or
  1729. not(CanBeCMOV(hp1));
  1730. hp2:=hp1.next;
  1731. condition:=inverse_cond[condition];
  1732. asml.remove(hp1.next)
  1733. hp1.next.free;
  1734. asml.remove(hp1);
  1735. hp1.free;
  1736. continue;
  1737. end;
  1738. }
  1739. end;
  1740. end;
  1741. end;
  1742. {$endif USECMOV}
  1743. A_FSTP,A_FISTP:
  1744. if doFpuLoadStoreOpt(asmL,p) then
  1745. continue;
  1746. A_IMUL:
  1747. begin
  1748. if ((Taicpu(p).oper[0].typ = top_const) or
  1749. (Taicpu(p).oper[0].typ = top_symbol)) and
  1750. (Taicpu(p).oper[1].typ = top_reg) and
  1751. ((Taicpu(p).oper[2].typ = top_none) or
  1752. ((Taicpu(p).oper[2].typ = top_reg) and
  1753. (Taicpu(p).oper[2].reg = Taicpu(p).oper[1].reg))) and
  1754. getLastInstruction(p,hp1) and
  1755. (hp1.typ = ait_instruction) and
  1756. (Taicpu(hp1).opcode = A_MOV) and
  1757. (Taicpu(hp1).oper[0].typ = top_reg) and
  1758. (Taicpu(hp1).oper[1].typ = top_reg) and
  1759. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg) then
  1760. { change "mov reg1,reg2; imul y,reg2" to "imul y,reg1,reg2" }
  1761. begin
  1762. Taicpu(p).ops := 3;
  1763. Taicpu(p).loadreg(1,Taicpu(hp1).oper[0].reg);
  1764. Taicpu(p).loadreg(2,Taicpu(hp1).oper[1].reg);
  1765. asml.remove(hp1);
  1766. hp1.free;
  1767. end;
  1768. end;
  1769. A_MOV:
  1770. Begin
  1771. If (Taicpu(p).oper[0].typ = top_reg) And
  1772. (Taicpu(p).oper[1].typ = top_reg) And
  1773. GetNextInstruction(p, hp1) And
  1774. (hp1.typ = ait_Instruction) And
  1775. ((Taicpu(hp1).opcode = A_MOV) or
  1776. (Taicpu(hp1).opcode = A_MOVZX) or
  1777. (Taicpu(hp1).opcode = A_MOVSX)) And
  1778. (Taicpu(hp1).oper[0].typ = top_ref) And
  1779. (Taicpu(hp1).oper[1].typ = top_reg) And
  1780. ((Taicpu(hp1).oper[0].ref^.Base = Taicpu(p).oper[1].reg) Or
  1781. (Taicpu(hp1).oper[0].ref^.Index = Taicpu(p).oper[1].reg)) And
  1782. (Reg32(Taicpu(hp1).oper[1].reg) = Taicpu(p).oper[1].reg) Then
  1783. {mov reg1, reg2
  1784. mov/zx/sx (reg2, ..), reg2 to mov/zx/sx (reg1, ..), reg2}
  1785. Begin
  1786. If (Taicpu(hp1).oper[0].ref^.Base = Taicpu(p).oper[1].reg) Then
  1787. Taicpu(hp1).oper[0].ref^.Base := Taicpu(p).oper[0].reg;
  1788. If (Taicpu(hp1).oper[0].ref^.Index = Taicpu(p).oper[1].reg) Then
  1789. Taicpu(hp1).oper[0].ref^.Index := Taicpu(p).oper[0].reg;
  1790. asml.Remove(p);
  1791. p.free;
  1792. p := hp1;
  1793. Continue;
  1794. End
  1795. Else If (Taicpu(p).oper[0].typ = top_ref) And
  1796. GetNextInstruction(p,hp1) And
  1797. (hp1.typ = ait_instruction) And
  1798. IsFoldableArithOp(Taicpu(hp1),Taicpu(p).oper[1].reg) And
  1799. GetNextInstruction(hp1,hp2) And
  1800. (hp2.typ = ait_instruction) And
  1801. (Taicpu(hp2).opcode = A_MOV) And
  1802. (Taicpu(hp2).oper[0].typ = top_reg) And
  1803. (Taicpu(hp2).oper[0].reg = Taicpu(p).oper[1].reg) And
  1804. (Taicpu(hp2).oper[1].typ = top_ref) Then
  1805. Begin
  1806. TmpUsedRegs := UsedRegs;
  1807. UpdateUsedRegs(TmpUsedRegs,Tai(hp1.next));
  1808. If (RefsEqual(Taicpu(hp2).oper[1].ref^, Taicpu(p).oper[0].ref^) And
  1809. Not(RegUsedAfterInstruction(Taicpu(p).oper[1].reg,
  1810. hp2, TmpUsedRegs)))
  1811. Then
  1812. { change mov (ref), reg }
  1813. { add/sub/or/... reg2/$const, reg }
  1814. { mov reg, (ref) }
  1815. { # release reg }
  1816. { to add/sub/or/... reg2/$const, (ref) }
  1817. Begin
  1818. case Taicpu(hp1).opcode of
  1819. A_INC,A_DEC:
  1820. Taicpu(hp1).LoadRef(0,newreference(Taicpu(p).oper[0].ref^))
  1821. else
  1822. Taicpu(hp1).LoadRef(1,newreference(Taicpu(p).oper[0].ref^));
  1823. end;
  1824. asml.Remove(p);
  1825. asml.Remove(hp2);
  1826. p.free;
  1827. hp2.free;
  1828. p := hp1
  1829. End;
  1830. End
  1831. End;
  1832. A_TEST, A_OR:
  1833. {removes the line marked with (x) from the sequence
  1834. And/or/xor/add/sub/... $x, %y
  1835. test/or %y, %y (x)
  1836. j(n)z _Label
  1837. as the first instruction already adjusts the ZF}
  1838. Begin
  1839. If OpsEqual(Taicpu(p).oper[0],Taicpu(p).oper[1]) Then
  1840. If GetLastInstruction(p, hp1) And
  1841. (Tai(hp1).typ = ait_instruction) Then
  1842. Case Taicpu(hp1).opcode Of
  1843. A_ADD, A_SUB, A_OR, A_XOR, A_AND{, A_SHL, A_SHR}:
  1844. Begin
  1845. If OpsEqual(Taicpu(hp1).oper[1],Taicpu(p).oper[0]) Then
  1846. Begin
  1847. hp1 := Tai(p.next);
  1848. asml.remove(p);
  1849. p.free;
  1850. p := Tai(hp1);
  1851. continue
  1852. End;
  1853. End;
  1854. A_DEC, A_INC, A_NEG:
  1855. Begin
  1856. If OpsEqual(Taicpu(hp1).oper[0],Taicpu(p).oper[0]) Then
  1857. Begin
  1858. Case Taicpu(hp1).opcode Of
  1859. A_DEC, A_INC:
  1860. {replace inc/dec with add/sub 1, because inc/dec doesn't set the carry flag}
  1861. Begin
  1862. Case Taicpu(hp1).opcode Of
  1863. A_DEC: Taicpu(hp1).opcode := A_SUB;
  1864. A_INC: Taicpu(hp1).opcode := A_ADD;
  1865. End;
  1866. Taicpu(hp1).Loadoper(1,Taicpu(hp1).oper[0]);
  1867. Taicpu(hp1).LoadConst(0,1);
  1868. Taicpu(hp1).ops:=2;
  1869. End
  1870. End;
  1871. hp1 := Tai(p.next);
  1872. asml.remove(p);
  1873. p.free;
  1874. p := Tai(hp1);
  1875. continue
  1876. End;
  1877. End
  1878. End
  1879. End;
  1880. End;
  1881. End;
  1882. End;
  1883. p := Tai(p.next)
  1884. End;
  1885. End;
  1886. Procedure PostPeepHoleOpts(AsmL: TAAsmOutput; BlockStart, BlockEnd: Tai);
  1887. var
  1888. p,hp1,hp2: Tai;
  1889. Begin
  1890. P := BlockStart;
  1891. While (P <> BlockEnd) Do
  1892. Begin
  1893. Case p.Typ Of
  1894. Ait_Instruction:
  1895. Begin
  1896. Case Taicpu(p).opcode Of
  1897. A_CALL:
  1898. If (AktOptProcessor < ClassP6) And
  1899. GetNextInstruction(p, hp1) And
  1900. (hp1.typ = ait_instruction) And
  1901. (Taicpu(hp1).opcode = A_JMP) And
  1902. (Taicpu(hp1).oper[0].typ = top_symbol) Then
  1903. Begin
  1904. hp2 := Taicpu.Op_sym(A_PUSH,S_L,Taicpu(hp1).oper[0].sym);
  1905. InsertLLItem(AsmL, p.previous, p, hp2);
  1906. Taicpu(p).opcode := A_JMP;
  1907. Taicpu(p).is_jmp := true;
  1908. asml.Remove(hp1);
  1909. hp1.free;
  1910. End;
  1911. A_MOV:
  1912. if (Taicpu(p).oper[0].typ = Top_Const) And
  1913. (Taicpu(p).oper[0].val = 0) And
  1914. (Taicpu(p).oper[1].typ = Top_Reg) Then
  1915. { change "mov $0, %reg" into "xor %reg, %reg" }
  1916. Begin
  1917. Taicpu(p).opcode := A_XOR;
  1918. Taicpu(p).LoadReg(0,Taicpu(p).oper[1].reg);
  1919. End;
  1920. A_MOVZX:
  1921. { if register vars are on, it's possible there is code like }
  1922. { "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx" }
  1923. { so we can't safely replace the movzx then with xor/mov, }
  1924. { since that would change the flags (JM) }
  1925. if not(cs_regalloc in aktglobalswitches) then
  1926. Begin
  1927. If (Taicpu(p).oper[1].typ = top_reg) Then
  1928. If (Taicpu(p).oper[0].typ = top_reg)
  1929. Then
  1930. Case Taicpu(p).opsize of
  1931. S_BL:
  1932. Begin
  1933. If IsGP32Reg(Taicpu(p).oper[1].reg) And
  1934. Not(CS_LittleSize in aktglobalswitches) And
  1935. (aktoptprocessor = ClassP5)
  1936. Then
  1937. {Change "movzbl %reg1, %reg2" to
  1938. "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
  1939. PentiumMMX}
  1940. Begin
  1941. hp1 := Taicpu.op_reg_reg(A_XOR, S_L,
  1942. Taicpu(p).oper[1].reg, Taicpu(p).oper[1].reg);
  1943. InsertLLItem(AsmL,p.previous, p, hp1);
  1944. Taicpu(p).opcode := A_MOV;
  1945. Taicpu(p).changeopsize(S_B);
  1946. Taicpu(p).LoadReg(1,Reg32ToReg8(Taicpu(p).oper[1].reg));
  1947. End;
  1948. End;
  1949. End
  1950. Else
  1951. If (Taicpu(p).oper[0].typ = top_ref) And
  1952. (Taicpu(p).oper[0].ref^.base <> Taicpu(p).oper[1].reg) And
  1953. (Taicpu(p).oper[0].ref^.index <> Taicpu(p).oper[1].reg) And
  1954. Not(CS_LittleSize in aktglobalswitches) And
  1955. IsGP32Reg(Taicpu(p).oper[1].reg) And
  1956. (aktoptprocessor = ClassP5) And
  1957. (Taicpu(p).opsize = S_BL)
  1958. Then
  1959. {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
  1960. Pentium and PentiumMMX}
  1961. Begin
  1962. hp1 := Taicpu.Op_reg_reg(A_XOR, S_L, Taicpu(p).oper[1].reg,
  1963. Taicpu(p).oper[1].reg);
  1964. Taicpu(p).opcode := A_MOV;
  1965. Taicpu(p).changeopsize(S_B);
  1966. Taicpu(p).LoadReg(1,Reg32ToReg8(Taicpu(p).oper[1].reg));
  1967. InsertLLItem(AsmL,p.previous, p, hp1);
  1968. End;
  1969. End;
  1970. End;
  1971. End;
  1972. End;
  1973. p := Tai(p.next)
  1974. End;
  1975. End;
  1976. End.
  1977. {
  1978. $Log$
  1979. Revision 1.14 2001-08-01 09:46:55 jonas
  1980. * fixed endless loop with web bug 1571 (merged)
  1981. Revision 1.13 2001/04/13 01:22:19 peter
  1982. * symtable change to classes
  1983. * range check generation and errors fixed, make cycle DEBUG=1 works
  1984. * memory leaks fixed
  1985. Revision 1.12 2001/04/06 14:06:03 jonas
  1986. * fixed incompatibility between new regvar handling and -Op2
  1987. Revision 1.11 2001/04/02 21:20:39 peter
  1988. * resulttype rewrite
  1989. Revision 1.10 2001/02/08 12:13:40 jonas
  1990. * fixed web bug 1391
  1991. Revision 1.9 2001/01/27 21:29:35 florian
  1992. * behavior -Oa optimized
  1993. Revision 1.8 2001/01/10 10:29:36 jonas
  1994. * really fixed problems with -Op2 opts (merged)
  1995. Revision 1.7 2001/01/07 15:49:49 jonas
  1996. * fixed bug in call/jmp optimization with -Op1 and -Op2
  1997. Revision 1.6 2000/12/25 00:07:33 peter
  1998. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1999. tlinkedlist objects)
  2000. Revision 1.5 2000/12/16 16:00:12 jonas
  2001. * removed warnings about possible range check errors
  2002. Revision 1.4 2000/11/29 00:30:49 florian
  2003. * unused units removed from uses clause
  2004. * some changes for widestrings
  2005. Revision 1.3 2000/11/14 09:53:18 jonas
  2006. * added missing allocregbetween() (merged)
  2007. Revision 1.2 2000/10/24 10:40:54 jonas
  2008. + register renaming ("fixes" bug1088)
  2009. * changed command line options meanings for optimizer:
  2010. O2 now means peepholopts, CSE and register renaming in 1 pass
  2011. O3 is the same, but repeated until no further optimizations are
  2012. possible or until 5 passes have been done (to avoid endless loops)
  2013. * changed aopt386 so it does this looping
  2014. * added some procedures from csopt386 to the interface because they're
  2015. used by rropt386 as well
  2016. * some changes to csopt386 and daopt386 so that newly added instructions
  2017. by the CSE get optimizer info (they were simply skipped previously),
  2018. this fixes some bugs
  2019. Revision 1.1 2000/10/15 09:47:43 peter
  2020. * moved to i386/
  2021. Revision 1.13 2000/10/02 13:01:29 jonas
  2022. * fixed bug regarding removal of "test/or reg,reg": apparently, shr/shl
  2023. doesn't set the zero flag according to the contents of the register
  2024. after the shift :( (mergfed from fixes branch)
  2025. Revision 1.12 2000/09/24 15:06:23 peter
  2026. * use defines.inc
  2027. Revision 1.11 2000/09/18 11:28:36 jonas
  2028. * fixed web bug 1133 (merged from fixes branch)
  2029. Revision 1.10 2000/08/18 10:09:13 jonas
  2030. * fix for web bug1099 (merged from fixes branch)
  2031. Revision 1.9 2000/08/05 13:33:08 peter
  2032. * $ifdef go32v2 -> target_info.target=go32v2
  2033. Revision 1.8 2000/08/05 10:35:51 jonas
  2034. * readded l1 variable (between ifdef go32v2 to avoid hints/notes)
  2035. Revision 1.7 2000/08/04 22:00:52 peter
  2036. * merges from fixes
  2037. Revision 1.6 2000/07/31 08:44:05 jonas
  2038. - removed imul support from -dfoldarithops since "imull [reg32],[mem32]"
  2039. doesn't exist (merged from fixes branch)
  2040. Revision 1.5 2000/07/28 13:56:23 jonas
  2041. * fixed bug in shr/shl optimization when -Og is used (merged from fixes
  2042. branch)
  2043. Revision 1.4 2000/07/21 15:19:55 jonas
  2044. * daopt386: changes to getnextinstruction/getlastinstruction so they
  2045. ignore labels who have is_addr set
  2046. + daopt386/csopt386: remove loads of registers which are overwritten
  2047. before their contents are used (especially usefull for removing superfluous
  2048. maybe_loadself outputs and push/pops transformed by below optimization
  2049. + popt386: transform pop/pop/pop/.../push/push/push to sequences of
  2050. 'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
  2051. currently because I don't know whether it's safe to do this under Win32/
  2052. Linux (because of problems we had when using esp as frame pointer on
  2053. those os'es)
  2054. Revision 1.3 2000/07/14 05:11:49 michael
  2055. + Patch to 1.1
  2056. Revision 1.2 2000/07/13 11:32:45 michael
  2057. + removed logs
  2058. }