popt386.pas 105 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209
  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,cgbase,
  30. {$ifdef finaldestdebug}
  31. cobjects,
  32. {$endif finaldestdebug}
  33. tainst,cpubase,optbase,cpuasm,DAOpt386,cginfo,rgobj;
  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. reference_reset(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, TmpRef, Taicpu(p).oper[1].reg)
  150. Else
  151. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, 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, TmpRef, Taicpu(p).oper[1].reg)
  166. Else
  167. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, 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, 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. reference_reset(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, TmpRef,
  204. Taicpu(p).oper[2].reg);
  205. End
  206. Else
  207. Begin
  208. TmpRef.base := Taicpu(p).oper[1].reg;
  209. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, TmpRef, Taicpu(p).oper[1].reg);
  210. End;
  211. InsertLLItem(AsmL,p.previous, p.next, hp1);
  212. p.free;
  213. p := Tai(hp1.next);
  214. End
  215. End;
  216. 9: Begin
  217. {imul 9, reg1, reg2 to
  218. lea (reg1,reg1,8), reg2
  219. imul 9, reg1 to
  220. lea (reg1,reg1,8), reg1}
  221. TmpRef.base := Taicpu(p).oper[1].reg;
  222. TmpRef.Index := Taicpu(p).oper[1].reg;
  223. TmpRef.ScaleFactor := 8;
  224. If (Taicpu(p).oper[2].typ = Top_None) Then
  225. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, TmpRef, Taicpu(p).oper[1].reg)
  226. Else
  227. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, TmpRef, Taicpu(p).oper[2].reg);
  228. InsertLLItem(AsmL,p.previous, p.next, hp1);
  229. p.free;
  230. p := hp1;
  231. End;
  232. 10: Begin
  233. {imul 10, reg1, reg2 to
  234. lea (reg1,reg1,4), reg2
  235. add reg2, reg2
  236. imul 10, reg1 to
  237. lea (reg1,reg1,4), reg1
  238. add reg1, reg1}
  239. If (aktoptprocessor <= Class386) Then
  240. Begin
  241. If (Taicpu(p).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, TmpRef, Taicpu(p).oper[2].reg)
  254. Else
  255. hp1 := Taicpu.op_ref_reg(A_LEA, S_L, 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, 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, TmpRef, Taicpu(p).oper[1].reg);
  283. End;
  284. InsertLLItem(AsmL,p, p.next, hp1);
  285. reference_reset(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, 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, 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(p).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) and
  672. 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) Then
  687. Begin
  688. Taicpu(hp2).Opcode := A_SUB;
  689. Taicpu(hp2).Loadoper(1,Taicpu(hp2).oper[0]);
  690. Taicpu(hp2).LoadConst(0,1);
  691. Taicpu(hp2).ops:=2;
  692. Taicpu(hp3).Opcode := A_Jcc;
  693. Case Taicpu(hp1).condition of
  694. C_LE: Taicpu(hp3).condition := C_GE;
  695. C_BE: Taicpu(hp3).condition := C_AE;
  696. End;
  697. asml.Remove(p);
  698. asml.Remove(hp1);
  699. p.free;
  700. hp1.free;
  701. p := hp2;
  702. continue;
  703. End
  704. End;
  705. A_FLD:
  706. Begin
  707. If (Taicpu(p).oper[0].typ = top_reg) And
  708. GetNextInstruction(p, hp1) And
  709. (hp1.typ = Ait_Instruction) And
  710. (Taicpu(hp1).oper[0].typ = top_reg) And
  711. (Taicpu(hp1).oper[1].typ = top_reg) And
  712. (Taicpu(hp1).oper[0].reg = R_ST) And
  713. (Taicpu(hp1).oper[1].reg = R_ST1) Then
  714. { change to
  715. fld reg fxxx reg,st
  716. fxxxp st, st1 (hp1)
  717. Remark: non commutative operations must be reversed!
  718. }
  719. begin
  720. Case Taicpu(hp1).opcode Of
  721. A_FMULP,A_FADDP,
  722. A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
  723. begin
  724. Case Taicpu(hp1).opcode Of
  725. A_FADDP: Taicpu(hp1).opcode := A_FADD;
  726. A_FMULP: Taicpu(hp1).opcode := A_FMUL;
  727. A_FSUBP: Taicpu(hp1).opcode := A_FSUBR;
  728. A_FSUBRP: Taicpu(hp1).opcode := A_FSUB;
  729. A_FDIVP: Taicpu(hp1).opcode := A_FDIVR;
  730. A_FDIVRP: Taicpu(hp1).opcode := A_FDIV;
  731. End;
  732. Taicpu(hp1).oper[0].reg := Taicpu(p).oper[0].reg;
  733. Taicpu(hp1).oper[1].reg := R_ST;
  734. asml.Remove(p);
  735. p.free;
  736. p := hp1;
  737. Continue;
  738. end;
  739. end;
  740. end
  741. else
  742. If (Taicpu(p).oper[0].typ = top_ref) And
  743. GetNextInstruction(p, hp2) And
  744. (hp2.typ = Ait_Instruction) And
  745. (Taicpu(hp2).oper[0].typ = top_reg) And
  746. (Taicpu(hp2).oper[1].typ = top_reg) And
  747. (Taicpu(p).opsize in [S_FS, S_FL]) And
  748. (Taicpu(hp2).oper[0].reg = R_ST) And
  749. (Taicpu(hp2).oper[1].reg = R_ST1) Then
  750. If GetLastInstruction(p, hp1) And
  751. (hp1.typ = Ait_Instruction) And
  752. ((Taicpu(hp1).opcode = A_FLD) Or
  753. (Taicpu(hp1).opcode = A_FST)) And
  754. (Taicpu(hp1).opsize = Taicpu(p).opsize) And
  755. (Taicpu(hp1).oper[0].typ = top_ref) And
  756. RefsEqual(Taicpu(p).oper[0].ref^, Taicpu(hp1).oper[0].ref^) Then
  757. If ((Taicpu(hp2).opcode = A_FMULP) Or
  758. (Taicpu(hp2).opcode = A_FADDP)) Then
  759. { change to
  760. fld/fst mem1 (hp1) fld/fst mem1
  761. fld mem1 (p) fadd/
  762. faddp/ fmul st, st
  763. fmulp st, st1 (hp2) }
  764. Begin
  765. asml.Remove(p);
  766. p.free;
  767. p := hp1;
  768. If (Taicpu(hp2).opcode = A_FADDP) Then
  769. Taicpu(hp2).opcode := A_FADD
  770. Else
  771. Taicpu(hp2).opcode := A_FMUL;
  772. Taicpu(hp2).oper[1].reg := R_ST;
  773. End
  774. Else
  775. { change to
  776. fld/fst mem1 (hp1) fld/fst mem1
  777. fld mem1 (p) fld st}
  778. Begin
  779. Taicpu(p).changeopsize(S_FL);
  780. Taicpu(p).loadreg(0,R_ST);
  781. End
  782. Else
  783. Begin
  784. Case Taicpu(hp2).opcode Of
  785. A_FMULP,A_FADDP,A_FSUBP,A_FDIVP,A_FSUBRP,A_FDIVRP:
  786. { change to
  787. fld/fst mem1 (hp1) fld/fst mem1
  788. fld mem2 (p) fxxx mem2
  789. fxxxp st, st1 (hp2) }
  790. Begin
  791. Case Taicpu(hp2).opcode Of
  792. A_FADDP: Taicpu(p).opcode := A_FADD;
  793. A_FMULP: Taicpu(p).opcode := A_FMUL;
  794. A_FSUBP: Taicpu(p).opcode := A_FSUBR;
  795. A_FSUBRP: Taicpu(p).opcode := A_FSUB;
  796. A_FDIVP: Taicpu(p).opcode := A_FDIVR;
  797. A_FDIVRP: Taicpu(p).opcode := A_FDIV;
  798. End;
  799. asml.Remove(hp2);
  800. hp2.free;
  801. End
  802. End
  803. End
  804. End;
  805. A_FSTP,A_FISTP:
  806. if doFpuLoadStoreOpt(asmL,p) then
  807. continue;
  808. A_LEA:
  809. Begin
  810. {removes seg register prefixes from LEA operations, as they
  811. don't do anything}
  812. Taicpu(p).oper[0].ref^.Segment := R_NO;
  813. {changes "lea (%reg1), %reg2" into "mov %reg1, %reg2"}
  814. If (Taicpu(p).oper[0].ref^.Base In [R_EAX..R_EDI]) And
  815. (Taicpu(p).oper[0].ref^.Index = R_NO) And
  816. (Not(Assigned(Taicpu(p).oper[0].ref^.Symbol))) Then
  817. If (Taicpu(p).oper[0].ref^.Base <> Taicpu(p).oper[1].reg)
  818. and (Taicpu(p).oper[0].ref^.Offset = 0)
  819. Then
  820. Begin
  821. hp1 := Taicpu.op_reg_reg(A_MOV, S_L,Taicpu(p).oper[0].ref^.Base,
  822. Taicpu(p).oper[1].reg);
  823. InsertLLItem(AsmL,p.previous,p.next, hp1);
  824. p.free;
  825. p := hp1;
  826. Continue;
  827. End
  828. Else
  829. if (Taicpu(p).oper[0].ref^.Offset = 0) then
  830. Begin
  831. hp1 := Tai(p.Next);
  832. asml.Remove(p);
  833. p.free;
  834. p := hp1;
  835. Continue;
  836. End
  837. else
  838. with Taicpu(p).oper[0].ref^ do
  839. if (Base = Taicpu(p).oper[1].reg) then
  840. begin
  841. l := offset+offsetfixup;
  842. case l of
  843. 1,-1:
  844. begin
  845. if l = 1 then
  846. Taicpu(p).opcode := A_INC
  847. else Taicpu(p).opcode := A_DEC;
  848. Taicpu(p).loadreg(0,Taicpu(p).oper[1].reg);
  849. Taicpu(p).ops := 1;
  850. end;
  851. else
  852. begin
  853. Taicpu(p).opcode := A_ADD;
  854. Taicpu(p).loadconst(0,offset+offsetfixup);
  855. end;
  856. end;
  857. end;
  858. End;
  859. A_MOV:
  860. Begin
  861. TmpUsedRegs := UsedRegs;
  862. If (Taicpu(p).oper[1].typ = top_reg) And
  863. (Taicpu(p).oper[1].reg In [R_EAX, R_EBX, R_EDX, R_EDI]) And
  864. GetNextInstruction(p, hp1) And
  865. (Tai(hp1).typ = ait_instruction) And
  866. (Taicpu(hp1).opcode = A_MOV) And
  867. (Taicpu(hp1).oper[0].typ = top_reg) And
  868. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg)
  869. Then
  870. {we have "mov x, %treg; mov %treg, y}
  871. If not(RegUsedAfterInstruction(Taicpu(p).oper[1].reg, hp1, TmpUsedRegs)) then
  872. {we've got "mov x, %treg; mov %treg, y; with %treg is not used after }
  873. Case Taicpu(p).oper[0].typ Of
  874. top_reg:
  875. Begin
  876. { change "mov %reg, %treg; mov %treg, y"
  877. to "mov %reg, y" }
  878. Taicpu(p).LoadOper(1,Taicpu(hp1).oper[1]);
  879. asml.Remove(hp1);
  880. hp1.free;
  881. continue;
  882. End;
  883. top_ref:
  884. If (Taicpu(hp1).oper[1].typ = top_reg) Then
  885. Begin
  886. { change "mov mem, %treg; mov %treg, %reg"
  887. to "mov mem, %reg" }
  888. Taicpu(p).Loadoper(1,Taicpu(hp1).oper[1]);
  889. asml.Remove(hp1);
  890. hp1.free;
  891. continue;
  892. End;
  893. End
  894. Else
  895. Else
  896. {Change "mov %reg1, %reg2; xxx %reg2, ???" to
  897. "mov %reg1, %reg2; xxx %reg1, ???" to avoid a write/read
  898. penalty}
  899. If (Taicpu(p).oper[0].typ = top_reg) And
  900. (Taicpu(p).oper[1].typ = top_reg) And
  901. GetNextInstruction(p,hp1) And
  902. (Tai(hp1).typ = ait_instruction) And
  903. (Taicpu(hp1).oper[0].typ = top_reg) And
  904. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg)
  905. Then
  906. {we have "mov %reg1, %reg2; XXX %reg2, ???"}
  907. Begin
  908. If ((Taicpu(hp1).opcode = A_OR) Or
  909. (Taicpu(hp1).opcode = A_TEST)) And
  910. (Taicpu(hp1).oper[1].typ = top_reg) And
  911. (Taicpu(hp1).oper[0].reg = Taicpu(hp1).oper[1].reg)
  912. Then
  913. {we have "mov %reg1, %reg2; test/or %reg2, %reg2"}
  914. Begin
  915. TmpUsedRegs := UsedRegs;
  916. { reg1 will be used after the first instruction, }
  917. { so update the allocation info }
  918. allocRegBetween(asmL,Taicpu(p).oper[0].reg,p,hp1);
  919. If GetNextInstruction(hp1, hp2) And
  920. (hp2.typ = ait_instruction) And
  921. Taicpu(hp2).is_jmp and
  922. Not(RegUsedAfterInstruction(Taicpu(hp1).oper[0].reg, hp1, TmpUsedRegs))
  923. Then
  924. {change "mov %reg1, %reg2; test/or %reg2, %reg2; jxx" to
  925. "test %reg1, %reg1; jxx"}
  926. Begin
  927. Taicpu(hp1).Loadoper(0,Taicpu(p).oper[0]);
  928. Taicpu(hp1).Loadoper(1,Taicpu(p).oper[0]);
  929. asml.Remove(p);
  930. p.free;
  931. p := hp1;
  932. continue
  933. End
  934. Else
  935. {change "mov %reg1, %reg2; test/or %reg2, %reg2" to
  936. "mov %reg1, %reg2; test/or %reg1, %reg1"}
  937. Begin
  938. Taicpu(hp1).Loadoper(0,Taicpu(p).oper[0]);
  939. Taicpu(hp1).Loadoper(1,Taicpu(p).oper[0]);
  940. End;
  941. End
  942. { Else
  943. If (Taicpu(p.next)^.opcode
  944. In [A_PUSH, A_OR, A_XOR, A_AND, A_TEST])}
  945. {change "mov %reg1, %reg2; push/or/xor/... %reg2, ???" to
  946. "mov %reg1, %reg2; push/or/xor/... %reg1, ???"}
  947. End
  948. Else
  949. {leave out the mov from "mov reg, x(%frame_pointer); leave/ret" (with
  950. x >= RetOffset) as it doesn't do anything (it writes either to a
  951. parameter or to the temporary storage room for the function
  952. result)}
  953. If GetNextInstruction(p, hp1) And
  954. (Tai(hp1).typ = ait_instruction)
  955. Then
  956. If ((Taicpu(hp1).opcode = A_LEAVE) Or
  957. (Taicpu(hp1).opcode = A_RET)) And
  958. (Taicpu(p).oper[1].typ = top_ref) And
  959. (Taicpu(p).oper[1].ref^.base = procinfo^.FramePointer) And
  960. (Taicpu(p).oper[1].ref^.offset >= procinfo^.Return_Offset) And
  961. (Taicpu(p).oper[1].ref^.index = R_NO) And
  962. (Taicpu(p).oper[0].typ = top_reg)
  963. Then
  964. Begin
  965. asml.Remove(p);
  966. p.free;
  967. p := hp1;
  968. RemoveLastDeallocForFuncRes(asmL,p);
  969. End
  970. Else
  971. If (Taicpu(p).oper[0].typ = top_reg) And
  972. (Taicpu(p).oper[1].typ = top_ref) And
  973. (Taicpu(p).opsize = Taicpu(hp1).opsize) And
  974. (Taicpu(hp1).opcode = A_CMP) And
  975. (Taicpu(hp1).oper[1].typ = top_ref) And
  976. RefsEqual(Taicpu(p).oper[1].ref^, Taicpu(hp1).oper[1].ref^) Then
  977. {change "mov reg1, mem1; cmp x, mem1" to "mov reg, mem1; cmp x, reg1"}
  978. begin
  979. Taicpu(hp1).loadreg(1,Taicpu(p).oper[0].reg);
  980. allocRegBetween(asmL,Taicpu(p).oper[0].reg,p,hp1);
  981. end;
  982. { Next instruction is also a MOV ? }
  983. If GetNextInstruction(p, hp1) And
  984. (Tai(hp1).typ = ait_instruction) and
  985. (Taicpu(hp1).opcode = A_MOV) and
  986. (Taicpu(hp1).opsize = Taicpu(p).opsize)
  987. Then
  988. Begin
  989. If (Taicpu(hp1).oper[0].typ = Taicpu(p).oper[1].typ) and
  990. (Taicpu(hp1).oper[1].typ = Taicpu(p).oper[0].typ)
  991. Then
  992. {mov reg1, mem1 or mov mem1, reg1
  993. mov mem2, reg2 mov reg2, mem2}
  994. Begin
  995. If OpsEqual(Taicpu(hp1).oper[1],Taicpu(p).oper[0]) Then
  996. {mov reg1, mem1 or mov mem1, reg1
  997. mov mem2, reg1 mov reg2, mem1}
  998. Begin
  999. If OpsEqual(Taicpu(hp1).oper[0],Taicpu(p).oper[1]) Then
  1000. { Removes the second statement from
  1001. mov reg1, mem1/reg2
  1002. mov mem1/reg2, reg1 }
  1003. Begin
  1004. if (Taicpu(p).oper[0].typ = top_reg) then
  1005. AllocRegBetween(asmL,Taicpu(p).oper[0].reg,p,hp1);
  1006. asml.remove(hp1);
  1007. hp1.free;
  1008. End
  1009. Else
  1010. Begin
  1011. TmpUsedRegs := UsedRegs;
  1012. UpdateUsedRegs(TmpUsedRegs, Tai(hp1.next));
  1013. If (Taicpu(p).oper[1].typ = top_ref) And
  1014. { mov reg1, mem1
  1015. mov mem2, reg1 }
  1016. GetNextInstruction(hp1, hp2) And
  1017. (hp2.typ = ait_instruction) And
  1018. (Taicpu(hp2).opcode = A_CMP) And
  1019. (Taicpu(hp2).opsize = Taicpu(p).opsize) and
  1020. (Taicpu(hp2).oper[0].typ = TOp_Ref) And
  1021. (Taicpu(hp2).oper[1].typ = TOp_Reg) And
  1022. RefsEqual(Taicpu(hp2).oper[0].ref^, Taicpu(p).oper[1].ref^) And
  1023. (Taicpu(hp2).oper[1].reg = Taicpu(p).oper[0].reg) And
  1024. Not(RegUsedAfterInstruction(Taicpu(p).oper[0].reg, hp2, TmpUsedRegs)) Then
  1025. { change to
  1026. mov reg1, mem1 mov reg1, mem1
  1027. mov mem2, reg1 cmp reg1, mem2
  1028. cmp mem1, reg1 }
  1029. Begin
  1030. asml.Remove(hp2);
  1031. hp2.free;
  1032. Taicpu(hp1).opcode := A_CMP;
  1033. Taicpu(hp1).loadref(1,Taicpu(hp1).oper[0].ref^);
  1034. Taicpu(hp1).loadreg(0,Taicpu(p).oper[0].reg);
  1035. End;
  1036. End;
  1037. End
  1038. Else
  1039. Begin
  1040. tmpUsedRegs := UsedRegs;
  1041. If GetNextInstruction(hp1, hp2) And
  1042. (Taicpu(p).oper[0].typ = top_ref) And
  1043. (Taicpu(p).oper[1].typ = top_reg) And
  1044. (Taicpu(hp1).oper[0].typ = top_reg) And
  1045. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg) And
  1046. (Taicpu(hp1).oper[1].typ = top_ref) And
  1047. (Tai(hp2).typ = ait_instruction) And
  1048. (Taicpu(hp2).opcode = A_MOV) And
  1049. (Taicpu(hp2).opsize = Taicpu(p).opsize) and
  1050. (Taicpu(hp2).oper[1].typ = top_reg) And
  1051. (Taicpu(hp2).oper[0].typ = top_ref) And
  1052. RefsEqual(Taicpu(hp2).oper[0].ref^, Taicpu(hp1).oper[1].ref^) Then
  1053. If not regInRef(Taicpu(hp2).oper[1].reg,Taicpu(hp2).oper[0].ref^) and
  1054. (Taicpu(p).oper[1].reg in [R_DI,R_EDI]) and
  1055. not(RegUsedAfterInstruction(R_EDI,hp1,tmpUsedRegs)) Then
  1056. { mov mem1, %edi
  1057. mov %edi, mem2
  1058. mov mem2, reg2
  1059. to:
  1060. mov mem1, reg2
  1061. mov reg2, mem2}
  1062. Begin
  1063. AllocRegBetween(asmL,reg32(Taicpu(hp2).oper[1].reg),p,hp2);
  1064. Taicpu(p).Loadoper(1,Taicpu(hp2).oper[1]);
  1065. Taicpu(hp1).loadoper(0,Taicpu(hp2).oper[1]);
  1066. asml.Remove(hp2);
  1067. hp2.free;
  1068. End
  1069. Else
  1070. If (Taicpu(p).oper[1].reg <> Taicpu(hp2).oper[1].reg) And
  1071. not(RegInRef(Taicpu(p).oper[1].reg,Taicpu(p).oper[0].ref^)) And
  1072. not(RegInRef(Taicpu(hp2).oper[1].reg,Taicpu(hp2).oper[0].ref^))
  1073. Then
  1074. { mov mem1, reg1 mov mem1, reg1
  1075. mov reg1, mem2 mov reg1, mem2
  1076. mov mem2, reg2 mov mem2, reg1
  1077. to: to:
  1078. mov mem1, reg1 mov mem1, reg1
  1079. mov mem1, reg2 mov reg1, mem2
  1080. mov reg1, mem2
  1081. or (if mem1 depends on reg1
  1082. and/or if mem2 depends on reg2)
  1083. to:
  1084. mov mem1, reg1
  1085. mov reg1, mem2
  1086. mov reg1, reg2
  1087. }
  1088. Begin
  1089. Taicpu(hp1).LoadRef(0,Taicpu(p).oper[0].ref^);
  1090. Taicpu(hp1).LoadReg(1,Taicpu(hp2).oper[1].reg);
  1091. Taicpu(hp2).LoadRef(1,Taicpu(hp2).oper[0].ref^);
  1092. Taicpu(hp2).LoadReg(0,Taicpu(p).oper[1].reg);
  1093. allocRegBetween(asmL,Taicpu(p).oper[1].reg,p,hp2);
  1094. if (Taicpu(p).oper[0].ref^.base in (rg.usableregsint+[R_EDI])) then
  1095. allocRegBetween(asmL,Taicpu(p).oper[0].ref^.base,p,hp2);
  1096. if (Taicpu(p).oper[0].ref^.index in (rg.usableregsint+[R_EDI])) then
  1097. allocRegBetween(asmL,Taicpu(p).oper[0].ref^.index,p,hp2);
  1098. End
  1099. Else
  1100. If (Taicpu(hp1).Oper[0].reg <> Taicpu(hp2).Oper[1].reg) Then
  1101. begin
  1102. Taicpu(hp2).LoadReg(0,Taicpu(hp1).Oper[0].reg);
  1103. allocRegBetween(asmL,Taicpu(p).oper[1].reg,p,hp2);
  1104. end
  1105. else
  1106. begin
  1107. asml.Remove(hp2);
  1108. hp2.free;
  1109. end
  1110. End;
  1111. End
  1112. Else
  1113. (* {movl [mem1],reg1
  1114. movl [mem1],reg2
  1115. to:
  1116. movl [mem1],reg1
  1117. movl reg1,reg2 }
  1118. If (Taicpu(p).oper[0].typ = top_ref) and
  1119. (Taicpu(p).oper[1].typ = top_reg) and
  1120. (Taicpu(hp1).oper[0].typ = top_ref) and
  1121. (Taicpu(hp1).oper[1].typ = top_reg) and
  1122. (Taicpu(p).opsize = Taicpu(hp1).opsize) and
  1123. RefsEqual(TReference(Taicpu(p).oper[0]^),Taicpu(hp1).oper[0]^.ref^) and
  1124. (Taicpu(p).oper[1].reg<>Taicpu(hp1).oper[0]^.ref^.base) and
  1125. (Taicpu(p).oper[1].reg<>Taicpu(hp1).oper[0]^.ref^.index) then
  1126. Taicpu(hp1).LoadReg(0,Taicpu(p).oper[1].reg)
  1127. Else*)
  1128. { movl const1,[mem1]
  1129. movl [mem1],reg1
  1130. to:
  1131. movl const1,reg1
  1132. movl reg1,[mem1] }
  1133. If (Taicpu(p).oper[0].typ = top_const) and
  1134. (Taicpu(p).oper[1].typ = top_ref) and
  1135. (Taicpu(hp1).oper[0].typ = top_ref) and
  1136. (Taicpu(hp1).oper[1].typ = top_reg) and
  1137. (Taicpu(p).opsize = Taicpu(hp1).opsize) and
  1138. RefsEqual(Taicpu(hp1).oper[0].ref^,Taicpu(p).oper[1].ref^) then
  1139. Begin
  1140. allocregbetween(asml,Taicpu(hp1).oper[1].reg,p,hp1);
  1141. { allocregbetween doesn't insert this because at }
  1142. { this time, no regalloc info is available in }
  1143. { the optinfo field, so do it manually (JM) }
  1144. hp2 := TaiRegalloc.Alloc(Taicpu(hp1).oper[1].reg);
  1145. insertllitem(asml,p.previous,p,hp2);
  1146. Taicpu(hp1).LoadReg(0,Taicpu(hp1).oper[1].reg);
  1147. Taicpu(hp1).LoadRef(1,Taicpu(p).oper[1].ref^);
  1148. Taicpu(p).LoadReg(1,Taicpu(hp1).oper[0].reg);
  1149. End
  1150. End;
  1151. End;
  1152. A_MOVZX:
  1153. Begin
  1154. {removes superfluous And's after movzx's}
  1155. If (Taicpu(p).oper[1].typ = top_reg) And
  1156. GetNextInstruction(p, hp1) And
  1157. (Tai(hp1).typ = ait_instruction) And
  1158. (Taicpu(hp1).opcode = A_AND) And
  1159. (Taicpu(hp1).oper[0].typ = top_const) And
  1160. (Taicpu(hp1).oper[1].typ = top_reg) And
  1161. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg)
  1162. Then
  1163. Case Taicpu(p).opsize Of
  1164. S_BL, S_BW:
  1165. If (Taicpu(hp1).oper[0].val = $ff) Then
  1166. Begin
  1167. asml.Remove(hp1);
  1168. hp1.free;
  1169. End;
  1170. S_WL:
  1171. If (Taicpu(hp1).oper[0].val = $ffff) Then
  1172. Begin
  1173. asml.Remove(hp1);
  1174. hp1.free;
  1175. End;
  1176. End;
  1177. {changes some movzx constructs to faster synonims (all examples
  1178. are given with eax/ax, but are also valid for other registers)}
  1179. If (Taicpu(p).oper[1].typ = top_reg) Then
  1180. If (Taicpu(p).oper[0].typ = top_reg) Then
  1181. Case Taicpu(p).opsize of
  1182. S_BW:
  1183. Begin
  1184. If (Taicpu(p).oper[0].reg = rg.makeregsize(Taicpu(p).oper[1].reg,OS_8)) And
  1185. Not(CS_LittleSize In aktglobalswitches)
  1186. Then
  1187. {Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
  1188. Begin
  1189. Taicpu(p).opcode := A_AND;
  1190. Taicpu(p).changeopsize(S_W);
  1191. Taicpu(p).LoadConst(0,$ff);
  1192. End
  1193. Else
  1194. If GetNextInstruction(p, hp1) And
  1195. (Tai(hp1).typ = ait_instruction) And
  1196. (Taicpu(hp1).opcode = A_AND) And
  1197. (Taicpu(hp1).oper[0].typ = top_const) And
  1198. (Taicpu(hp1).oper[1].typ = top_reg) And
  1199. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg)
  1200. Then
  1201. {Change "movzbw %reg1, %reg2; andw $const, %reg2"
  1202. to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
  1203. Begin
  1204. Taicpu(p).opcode := A_MOV;
  1205. Taicpu(p).changeopsize(S_W);
  1206. Taicpu(p).LoadReg(0,rg.makeregsize(Taicpu(p).oper[0].reg,OS_16));
  1207. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ff);
  1208. End;
  1209. End;
  1210. S_BL:
  1211. Begin
  1212. If (Taicpu(p).oper[0].reg = rg.makeregsize(Taicpu(p).oper[1].reg,OS_8)) And
  1213. Not(CS_LittleSize in aktglobalswitches)
  1214. Then
  1215. {Change "movzbl %al, %eax" to "andl $0x0ffh, %eax"}
  1216. Begin
  1217. Taicpu(p).opcode := A_AND;
  1218. Taicpu(p).changeopsize(S_L);
  1219. Taicpu(p).loadconst(0,$ff)
  1220. End
  1221. Else
  1222. If GetNextInstruction(p, hp1) And
  1223. (Tai(hp1).typ = ait_instruction) And
  1224. (Taicpu(hp1).opcode = A_AND) And
  1225. (Taicpu(hp1).oper[0].typ = top_const) And
  1226. (Taicpu(hp1).oper[1].typ = top_reg) And
  1227. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg)
  1228. Then
  1229. {Change "movzbl %reg1, %reg2; andl $const, %reg2"
  1230. to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
  1231. Begin
  1232. Taicpu(p).opcode := A_MOV;
  1233. Taicpu(p).changeopsize(S_L);
  1234. Taicpu(p).LoadReg(0,rg.makeregsize(Taicpu(p).oper[0].reg,OS_32));
  1235. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ff);
  1236. End
  1237. End;
  1238. S_WL:
  1239. Begin
  1240. If (Taicpu(p).oper[0].reg = rg.makeregsize(Taicpu(p).oper[1].reg,OS_16)) And
  1241. Not(CS_LittleSize In aktglobalswitches)
  1242. Then
  1243. {Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax"}
  1244. Begin
  1245. Taicpu(p).opcode := A_AND;
  1246. Taicpu(p).changeopsize(S_L);
  1247. Taicpu(p).LoadConst(0,$ffff);
  1248. End
  1249. Else
  1250. If GetNextInstruction(p, hp1) And
  1251. (Tai(hp1).typ = ait_instruction) And
  1252. (Taicpu(hp1).opcode = A_AND) And
  1253. (Taicpu(hp1).oper[0].typ = top_const) And
  1254. (Taicpu(hp1).oper[1].typ = top_reg) And
  1255. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg)
  1256. Then
  1257. {Change "movzwl %reg1, %reg2; andl $const, %reg2"
  1258. to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
  1259. Begin
  1260. Taicpu(p).opcode := A_MOV;
  1261. Taicpu(p).changeopsize(S_L);
  1262. Taicpu(p).LoadReg(0,rg.makeregsize(Taicpu(p).oper[0].reg,OS_32));
  1263. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ffff);
  1264. End;
  1265. End;
  1266. End
  1267. Else
  1268. If (Taicpu(p).oper[0].typ = top_ref) Then
  1269. Begin
  1270. If GetNextInstruction(p, hp1) And
  1271. (Tai(hp1).typ = ait_instruction) And
  1272. (Taicpu(hp1).opcode = A_AND) And
  1273. (Taicpu(hp1).oper[0].typ = Top_Const) And
  1274. (Taicpu(hp1).oper[1].typ = Top_Reg) And
  1275. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg) Then
  1276. Begin
  1277. Taicpu(p).opcode := A_MOV;
  1278. Case Taicpu(p).opsize Of
  1279. S_BL:
  1280. Begin
  1281. Taicpu(p).changeopsize(S_L);
  1282. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ff);
  1283. End;
  1284. S_WL:
  1285. Begin
  1286. Taicpu(p).changeopsize(S_L);
  1287. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ffff);
  1288. End;
  1289. S_BW:
  1290. Begin
  1291. Taicpu(p).changeopsize(S_W);
  1292. Taicpu(hp1).LoadConst(0,Taicpu(hp1).oper[0].val And $ff);
  1293. End;
  1294. End;
  1295. End;
  1296. End;
  1297. End;
  1298. A_POP:
  1299. Begin
  1300. if target_info.target=target_i386_go32v2 then
  1301. begin
  1302. { Transform a series of pop/pop/pop/push/push/push to }
  1303. { 'movl x(%esp),%reg' for go32v2 (not for the rest, }
  1304. { because I'm not sure whether they can cope with }
  1305. { 'movl x(%esp),%reg' with x > 0, I believe we had }
  1306. { such a problem when using esp as frame pointer (JM) }
  1307. if (Taicpu(p).oper[0].typ = top_reg) then
  1308. begin
  1309. hp1 := p;
  1310. hp2 := p;
  1311. l := 0;
  1312. while getNextInstruction(hp1,hp1) and
  1313. (hp1.typ = ait_instruction) and
  1314. (Taicpu(hp1).opcode = A_POP) and
  1315. (Taicpu(hp1).oper[0].typ = top_reg) do
  1316. begin
  1317. hp2 := hp1;
  1318. inc(l,4);
  1319. end;
  1320. getLastInstruction(p,hp3);
  1321. l1 := 0;
  1322. while (hp2 <> hp3) and
  1323. assigned(hp1) and
  1324. (hp1.typ = ait_instruction) and
  1325. (Taicpu(hp1).opcode = A_PUSH) and
  1326. (Taicpu(hp1).oper[0].typ = top_reg) and
  1327. (Taicpu(hp1).oper[0].reg = Taicpu(hp2).oper[0].reg) do
  1328. begin
  1329. { change it to a two op operation }
  1330. Taicpu(hp2).oper[1].typ:=top_none;
  1331. Taicpu(hp2).ops:=2;
  1332. Taicpu(hp2).opcode := A_MOV;
  1333. Taicpu(hp2).Loadoper(1,Taicpu(hp1).oper[0]);
  1334. reference_reset(tmpref);
  1335. tmpRef.base := STACK_POINTER_REG;
  1336. tmpRef.offset := l;
  1337. Taicpu(hp2).loadRef(0,tmpRef);
  1338. hp4 := hp1;
  1339. getNextInstruction(hp1,hp1);
  1340. asml.remove(hp4);
  1341. hp4.free;
  1342. getLastInstruction(hp2,hp2);
  1343. dec(l,4);
  1344. inc(l1);
  1345. end;
  1346. if l <> -4 then
  1347. begin
  1348. inc(l,4);
  1349. for l1 := l1 downto 1 do
  1350. begin
  1351. getNextInstruction(hp2,hp2);
  1352. dec(Taicpu(hp2).oper[0].ref^.offset,l);
  1353. end
  1354. end
  1355. end
  1356. end
  1357. else
  1358. begin
  1359. if (Taicpu(p).oper[0].typ = top_reg) And
  1360. GetNextInstruction(p, hp1) And
  1361. (Tai(hp1).typ=ait_instruction) and
  1362. (Taicpu(hp1).opcode=A_PUSH) and
  1363. (Taicpu(hp1).oper[0].typ = top_reg) And
  1364. (Taicpu(hp1).oper[0].reg=Taicpu(p).oper[0].reg) then
  1365. Begin
  1366. { change it to a two op operation }
  1367. Taicpu(p).oper[1].typ:=top_none;
  1368. Taicpu(p).ops:=2;
  1369. Taicpu(p).opcode := A_MOV;
  1370. Taicpu(p).Loadoper(1,Taicpu(p).oper[0]);
  1371. reference_reset(tmpref);
  1372. TmpRef.base := R_ESP;
  1373. Taicpu(p).LoadRef(0,TmpRef);
  1374. asml.Remove(hp1);
  1375. hp1.free;
  1376. End;
  1377. end;
  1378. end;
  1379. A_PUSH:
  1380. Begin
  1381. If (Taicpu(p).opsize = S_W) And
  1382. (Taicpu(p).oper[0].typ = Top_Const) And
  1383. GetNextInstruction(p, hp1) And
  1384. (Tai(hp1).typ = ait_instruction) And
  1385. (Taicpu(hp1).opcode = A_PUSH) And
  1386. (Taicpu(hp1).oper[0].typ = Top_Const) And
  1387. (Taicpu(hp1).opsize = S_W) Then
  1388. Begin
  1389. Taicpu(p).changeopsize(S_L);
  1390. Taicpu(p).LoadConst(0,Taicpu(p).oper[0].val shl 16 + word(Taicpu(hp1).oper[0].val));
  1391. asml.Remove(hp1);
  1392. hp1.free;
  1393. End;
  1394. End;
  1395. A_SHL, A_SAL:
  1396. Begin
  1397. If (Taicpu(p).oper[0].typ = Top_Const) And
  1398. (Taicpu(p).oper[1].typ = Top_Reg) And
  1399. (Taicpu(p).opsize = S_L) And
  1400. (Taicpu(p).oper[0].val <= 3)
  1401. {Changes "shl const, %reg32; add const/reg, %reg32" to one lea statement}
  1402. Then
  1403. Begin
  1404. TmpBool1 := True; {should we check the next instruction?}
  1405. TmpBool2 := False; {have we found an add/sub which could be
  1406. integrated in the lea?}
  1407. reference_reset(tmpref);
  1408. TmpRef.index := Taicpu(p).oper[1].reg;
  1409. TmpRef.scalefactor := 1 shl Taicpu(p).oper[0].val;
  1410. While TmpBool1 And
  1411. GetNextInstruction(p, hp1) And
  1412. (Tai(hp1).typ = ait_instruction) And
  1413. ((((Taicpu(hp1).opcode = A_ADD) Or
  1414. (Taicpu(hp1).opcode = A_SUB)) And
  1415. (Taicpu(hp1).oper[1].typ = Top_Reg) And
  1416. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg)) or
  1417. (((Taicpu(hp1).opcode = A_INC) or
  1418. (Taicpu(hp1).opcode = A_DEC)) and
  1419. (Taicpu(hp1).oper[0].typ = Top_Reg) and
  1420. (Taicpu(hp1).oper[0].reg = Taicpu(p).oper[1].reg))) Do
  1421. Begin
  1422. TmpBool1 := False;
  1423. If (Taicpu(hp1).oper[0].typ = Top_Const)
  1424. Then
  1425. Begin
  1426. TmpBool1 := True;
  1427. TmpBool2 := True;
  1428. case Taicpu(hp1).opcode of
  1429. A_ADD:
  1430. inc(TmpRef.offset, longint(Taicpu(hp1).oper[0].val));
  1431. A_SUB:
  1432. dec(TmpRef.offset, longint(Taicpu(hp1).oper[0].val));
  1433. end;
  1434. asml.Remove(hp1);
  1435. hp1.free;
  1436. End
  1437. Else
  1438. If (Taicpu(hp1).oper[0].typ = Top_Reg) And
  1439. (((Taicpu(hp1).opcode = A_ADD) And
  1440. (TmpRef.base = R_NO)) or
  1441. (Taicpu(hp1).opcode = A_INC) or
  1442. (Taicpu(hp1).opcode = A_DEC)) Then
  1443. Begin
  1444. TmpBool1 := True;
  1445. TmpBool2 := True;
  1446. case Taicpu(hp1).opcode of
  1447. A_ADD:
  1448. TmpRef.base := Taicpu(hp1).oper[0].reg;
  1449. A_INC:
  1450. inc(TmpRef.offset);
  1451. A_DEC:
  1452. dec(TmpRef.offset);
  1453. end;
  1454. asml.Remove(hp1);
  1455. hp1.free;
  1456. End;
  1457. End;
  1458. If TmpBool2 Or
  1459. ((aktoptprocessor < ClassP6) And
  1460. (Taicpu(p).oper[0].val <= 3) And
  1461. Not(CS_LittleSize in aktglobalswitches))
  1462. Then
  1463. Begin
  1464. If Not(TmpBool2) And
  1465. (Taicpu(p).oper[0].val = 1)
  1466. Then
  1467. Begin
  1468. hp1 := Taicpu.Op_reg_reg(A_ADD,Taicpu(p).opsize,
  1469. Taicpu(p).oper[1].reg, Taicpu(p).oper[1].reg)
  1470. End
  1471. Else hp1 := Taicpu.op_ref_reg(A_LEA, S_L, TmpRef,
  1472. Taicpu(p).oper[1].reg);
  1473. InsertLLItem(AsmL,p.previous, p.next, hp1);
  1474. p.free;
  1475. p := hp1;
  1476. End;
  1477. End
  1478. Else
  1479. If (aktoptprocessor < ClassP6) And
  1480. (Taicpu(p).oper[0].typ = top_const) And
  1481. (Taicpu(p).oper[1].typ = top_reg) Then
  1482. If (Taicpu(p).oper[0].val = 1)
  1483. Then
  1484. {changes "shl $1, %reg" to "add %reg, %reg", which is the same on a 386,
  1485. but faster on a 486, and Tairable in both U and V pipes on the Pentium
  1486. (unlike shl, which is only Tairable in the U pipe)}
  1487. Begin
  1488. hp1 := Taicpu.Op_reg_reg(A_ADD,Taicpu(p).opsize,
  1489. Taicpu(p).oper[1].reg, Taicpu(p).oper[1].reg);
  1490. InsertLLItem(AsmL,p.previous, p.next, hp1);
  1491. p.free;
  1492. p := hp1;
  1493. End
  1494. Else If (Taicpu(p).opsize = S_L) and
  1495. (Taicpu(p).oper[0].val<= 3) Then
  1496. {changes "shl $2, %reg" to "lea (,%reg,4), %reg"
  1497. "shl $3, %reg" to "lea (,%reg,8), %reg}
  1498. Begin
  1499. reference_reset(tmpref);
  1500. TmpRef.index := Taicpu(p).oper[1].reg;
  1501. TmpRef.scalefactor := 1 shl Taicpu(p).oper[0].val;
  1502. hp1 := Taicpu.Op_ref_reg(A_LEA,S_L,TmpRef, Taicpu(p).oper[1].reg);
  1503. InsertLLItem(AsmL,p.previous, p.next, hp1);
  1504. p.free;
  1505. p := hp1;
  1506. End
  1507. End;
  1508. A_SETcc :
  1509. { changes
  1510. setcc (funcres) setcc reg
  1511. movb (funcres), reg to leave/ret
  1512. leave/ret }
  1513. Begin
  1514. If (Taicpu(p).oper[0].typ = top_ref) And
  1515. GetNextInstruction(p, hp1) And
  1516. GetNextInstruction(hp1, hp2) And
  1517. (hp2.typ = ait_instruction) And
  1518. ((Taicpu(hp2).opcode = A_LEAVE) or
  1519. (Taicpu(hp2).opcode = A_RET)) And
  1520. (Taicpu(p).oper[0].ref^.Base = procinfo^.FramePointer) And
  1521. (Taicpu(p).oper[0].ref^.Index = R_NO) And
  1522. (Taicpu(p).oper[0].ref^.Offset >= procinfo^.Return_Offset) And
  1523. (hp1.typ = ait_instruction) And
  1524. (Taicpu(hp1).opcode = A_MOV) And
  1525. (Taicpu(hp1).opsize = S_B) And
  1526. (Taicpu(hp1).oper[0].typ = top_ref) And
  1527. RefsEqual(Taicpu(hp1).oper[0].ref^, Taicpu(p).oper[0].ref^) Then
  1528. Begin
  1529. Taicpu(p).LoadReg(0,Taicpu(hp1).oper[1].reg);
  1530. asml.Remove(hp1);
  1531. hp1.free;
  1532. End
  1533. End;
  1534. A_SUB:
  1535. { * change "subl $2, %esp; pushw x" to "pushl x"}
  1536. { * change "sub/add const1, reg" or "dec reg" followed by
  1537. "sub const2, reg" to one "sub ..., reg" }
  1538. Begin
  1539. If (Taicpu(p).oper[0].typ = top_const) And
  1540. (Taicpu(p).oper[1].typ = top_reg) Then
  1541. If (Taicpu(p).oper[0].val = 2) And
  1542. (Taicpu(p).oper[1].reg = R_ESP) and
  1543. { Don't do the sub/push optimization if the sub }
  1544. { comes from setting up the stack frame (JM) }
  1545. (not getLastInstruction(p,hp1) or
  1546. (hp1.typ <> ait_instruction) or
  1547. (Taicpu(hp1).opcode <> A_MOV) or
  1548. (Taicpu(hp1).oper[0].typ <> top_reg) or
  1549. (Taicpu(hp1).oper[0].reg <> R_ESP) or
  1550. (Taicpu(hp1).oper[1].typ <> top_reg) or
  1551. (Taicpu(hp1).oper[1].reg <> R_EBP)) then
  1552. Begin
  1553. hp1 := Tai(p.next);
  1554. While Assigned(hp1) And
  1555. (Tai(hp1).typ In [ait_instruction]+SkipInstr) And
  1556. not regReadByInstruction(R_ESP,hp1) and
  1557. not regModifiedByInstruction(R_ESP,hp1) do
  1558. hp1 := Tai(hp1.next);
  1559. If Assigned(hp1) And
  1560. (Tai(hp1).typ = ait_instruction) And
  1561. (Taicpu(hp1).opcode = A_PUSH) And
  1562. (Taicpu(hp1).opsize = S_W)
  1563. Then
  1564. Begin
  1565. Taicpu(hp1).changeopsize(S_L);
  1566. if Taicpu(hp1).oper[0].typ=top_reg then
  1567. Taicpu(hp1).LoadReg(0,rg.makeregsize(Taicpu(hp1).oper[0].reg,OS_32));
  1568. hp1 := Tai(p.next);
  1569. asml.Remove(p);
  1570. p.free;
  1571. p := hp1;
  1572. Continue
  1573. End;
  1574. If DoSubAddOpt(p) Then continue;
  1575. End
  1576. Else If DoSubAddOpt(p) Then Continue
  1577. End;
  1578. A_XOR:
  1579. If (Taicpu(p).oper[0].typ = top_reg) And
  1580. (Taicpu(p).oper[1].typ = top_reg) And
  1581. (Taicpu(p).oper[0].reg = Taicpu(p).oper[1].reg) then
  1582. { temporarily change this to 'mov reg,0' to make it easier }
  1583. { for the CSE. Will be changed back in pass 2 }
  1584. begin
  1585. Taicpu(p).opcode := A_MOV;
  1586. Taicpu(p).loadconst(0,0);
  1587. end;
  1588. End;
  1589. end; { if is_jmp }
  1590. End;
  1591. { ait_label:
  1592. Begin
  1593. If labelCanBeSkipped(Tai_label(p))
  1594. Then
  1595. Begin
  1596. hp1 := Tai(p.next);
  1597. asml.Remove(p);
  1598. p.free;
  1599. p := hp1;
  1600. Continue
  1601. End;
  1602. End;}
  1603. End;
  1604. p:=Tai(p.next);
  1605. end;
  1606. end;
  1607. function isFoldableArithOp(hp1: Taicpu; reg: tregister): boolean;
  1608. begin
  1609. IsFoldableArithOp := False;
  1610. case hp1.opcode of
  1611. A_ADD,A_SUB,A_OR,A_XOR,A_AND,A_SHL,A_SHR,A_SAR:
  1612. isFoldableArithOp :=
  1613. ((Taicpu(hp1).oper[0].typ = top_const) or
  1614. ((Taicpu(hp1).oper[0].typ = top_reg) and
  1615. (Taicpu(hp1).oper[0].reg <> reg))) and
  1616. (Taicpu(hp1).oper[1].typ = top_reg) and
  1617. (Taicpu(hp1).oper[1].reg = reg);
  1618. A_INC,A_DEC:
  1619. isFoldableArithOp :=
  1620. (Taicpu(hp1).oper[0].typ = top_reg) and
  1621. (Taicpu(hp1).oper[0].reg = reg);
  1622. end;
  1623. end;
  1624. Procedure PeepHoleOptPass2(AsmL: TAAsmOutput; BlockStart, BlockEnd: Tai);
  1625. {$ifdef USECMOV}
  1626. function CanBeCMOV(p : Tai) : boolean;
  1627. begin
  1628. CanBeCMOV:=assigned(p) and (p.typ=ait_instruction) and
  1629. (Taicpu(p).opcode=A_MOV) and
  1630. (Taicpu(p).opsize in [S_L,S_W]) and
  1631. (Taicpu(p).oper[0].typ in [top_reg,top_ref]) and
  1632. (Taicpu(p).oper[1].typ in [top_reg]);
  1633. end;
  1634. {$endif USECMOV}
  1635. var
  1636. p,hp1,hp2: Tai;
  1637. {$ifdef USECMOV}
  1638. l : longint;
  1639. condition : tasmcond;
  1640. hp3: Tai;
  1641. {$endif USECMOV}
  1642. UsedRegs, TmpUsedRegs: TRegSet;
  1643. Begin
  1644. P := BlockStart;
  1645. UsedRegs := [];
  1646. While (P <> BlockEnd) Do
  1647. Begin
  1648. UpdateUsedRegs(UsedRegs, Tai(p.next));
  1649. Case p.Typ Of
  1650. Ait_Instruction:
  1651. Begin
  1652. Case Taicpu(p).opcode Of
  1653. {$ifdef USECMOV}
  1654. A_Jcc:
  1655. if (aktspecificoptprocessor=ClassP6) then
  1656. begin
  1657. { check for
  1658. jCC xxx
  1659. <several movs>
  1660. xxx:
  1661. }
  1662. l:=0;
  1663. GetNextInstruction(p, hp1);
  1664. while assigned(hp1) And
  1665. CanBeCMOV(hp1) do
  1666. begin
  1667. inc(l);
  1668. GetNextInstruction(hp1,hp1);
  1669. end;
  1670. if assigned(hp1) then
  1671. begin
  1672. if FindLabel(tasmlabel(Taicpu(p).oper[0].sym),hp1) then
  1673. begin
  1674. if (l<=4) and (l>0) then
  1675. begin
  1676. condition:=inverse_cond[Taicpu(p).condition];
  1677. GetNextInstruction(p,hp1);
  1678. asml.remove(p);
  1679. p.free;
  1680. p:=hp1;
  1681. repeat
  1682. Taicpu(hp1).opcode:=A_CMOVcc;
  1683. Taicpu(hp1).condition:=condition;
  1684. GetNextInstruction(hp1,hp1);
  1685. until not(assigned(hp1)) or
  1686. not(CanBeCMOV(hp1));
  1687. asml.remove(hp1);
  1688. hp1.free;
  1689. continue;
  1690. end;
  1691. end
  1692. else
  1693. begin
  1694. { check further for
  1695. jCC xxx
  1696. <several movs>
  1697. jmp yyy
  1698. xxx:
  1699. <several movs>
  1700. yyy:
  1701. }
  1702. { hp2 points to jmp xxx }
  1703. hp2:=hp1;
  1704. { skip hp1 to xxx }
  1705. GetNextInstruction(hp1, hp1);
  1706. if assigned(hp2) and
  1707. assigned(hp1) and
  1708. (l<=3) and
  1709. (hp2.typ=ait_instruction) and
  1710. (Taicpu(hp2).is_jmp) and
  1711. (Taicpu(hp2).condition=C_None) and
  1712. FindLabel(tasmlabel(Taicpu(p).oper[0].sym),hp1) then
  1713. begin
  1714. l:=0;
  1715. while assigned(hp1) And
  1716. CanBeCMOV(hp1) do
  1717. begin
  1718. inc(l);
  1719. GetNextInstruction(hp1, hp1);
  1720. end;
  1721. end;
  1722. {
  1723. if assigned(hp1) and
  1724. FindLabel(tasmlabel(Taicpu(hp2).oper[0].sym),hp1) then
  1725. begin
  1726. condition:=inverse_cond[Taicpu(p).condition];
  1727. GetNextInstruction(p,hp1);
  1728. asml.remove(p);
  1729. p.free;
  1730. p:=hp1;
  1731. repeat
  1732. Taicpu(hp1).opcode:=A_CMOVcc;
  1733. Taicpu(hp1).condition:=condition;
  1734. GetNextInstruction(hp1,hp1);
  1735. until not(assigned(hp1)) or
  1736. not(CanBeCMOV(hp1));
  1737. hp2:=hp1.next;
  1738. condition:=inverse_cond[condition];
  1739. asml.remove(hp1.next)
  1740. hp1.next.free;
  1741. asml.remove(hp1);
  1742. hp1.free;
  1743. continue;
  1744. end;
  1745. }
  1746. end;
  1747. end;
  1748. end;
  1749. {$endif USECMOV}
  1750. A_FSTP,A_FISTP:
  1751. if doFpuLoadStoreOpt(asmL,p) then
  1752. continue;
  1753. A_IMUL:
  1754. begin
  1755. if ((Taicpu(p).oper[0].typ = top_const) or
  1756. (Taicpu(p).oper[0].typ = top_symbol)) and
  1757. (Taicpu(p).oper[1].typ = top_reg) and
  1758. ((Taicpu(p).oper[2].typ = top_none) or
  1759. ((Taicpu(p).oper[2].typ = top_reg) and
  1760. (Taicpu(p).oper[2].reg = Taicpu(p).oper[1].reg))) and
  1761. getLastInstruction(p,hp1) and
  1762. (hp1.typ = ait_instruction) and
  1763. (Taicpu(hp1).opcode = A_MOV) and
  1764. (Taicpu(hp1).oper[0].typ = top_reg) and
  1765. (Taicpu(hp1).oper[1].typ = top_reg) and
  1766. (Taicpu(hp1).oper[1].reg = Taicpu(p).oper[1].reg) then
  1767. { change "mov reg1,reg2; imul y,reg2" to "imul y,reg1,reg2" }
  1768. begin
  1769. Taicpu(p).ops := 3;
  1770. Taicpu(p).loadreg(1,Taicpu(hp1).oper[0].reg);
  1771. Taicpu(p).loadreg(2,Taicpu(hp1).oper[1].reg);
  1772. asml.remove(hp1);
  1773. hp1.free;
  1774. end;
  1775. end;
  1776. A_MOV:
  1777. Begin
  1778. If (Taicpu(p).oper[0].typ = top_reg) And
  1779. (Taicpu(p).oper[1].typ = top_reg) And
  1780. GetNextInstruction(p, hp1) And
  1781. (hp1.typ = ait_Instruction) And
  1782. ((Taicpu(hp1).opcode = A_MOV) or
  1783. (Taicpu(hp1).opcode = A_MOVZX) or
  1784. (Taicpu(hp1).opcode = A_MOVSX)) And
  1785. (Taicpu(hp1).oper[0].typ = top_ref) And
  1786. (Taicpu(hp1).oper[1].typ = top_reg) And
  1787. ((Taicpu(hp1).oper[0].ref^.Base = Taicpu(p).oper[1].reg) Or
  1788. (Taicpu(hp1).oper[0].ref^.Index = Taicpu(p).oper[1].reg)) And
  1789. (Reg32(Taicpu(hp1).oper[1].reg) = Taicpu(p).oper[1].reg) Then
  1790. {mov reg1, reg2
  1791. mov/zx/sx (reg2, ..), reg2 to mov/zx/sx (reg1, ..), reg2}
  1792. Begin
  1793. If (Taicpu(hp1).oper[0].ref^.Base = Taicpu(p).oper[1].reg) Then
  1794. Taicpu(hp1).oper[0].ref^.Base := Taicpu(p).oper[0].reg;
  1795. If (Taicpu(hp1).oper[0].ref^.Index = Taicpu(p).oper[1].reg) Then
  1796. Taicpu(hp1).oper[0].ref^.Index := Taicpu(p).oper[0].reg;
  1797. asml.Remove(p);
  1798. p.free;
  1799. p := hp1;
  1800. Continue;
  1801. End
  1802. Else If (Taicpu(p).oper[0].typ = top_ref) And
  1803. GetNextInstruction(p,hp1) And
  1804. (hp1.typ = ait_instruction) And
  1805. IsFoldableArithOp(Taicpu(hp1),Taicpu(p).oper[1].reg) And
  1806. GetNextInstruction(hp1,hp2) And
  1807. (hp2.typ = ait_instruction) And
  1808. (Taicpu(hp2).opcode = A_MOV) And
  1809. (Taicpu(hp2).oper[0].typ = top_reg) And
  1810. (Taicpu(hp2).oper[0].reg = Taicpu(p).oper[1].reg) And
  1811. (Taicpu(hp2).oper[1].typ = top_ref) Then
  1812. Begin
  1813. TmpUsedRegs := UsedRegs;
  1814. UpdateUsedRegs(TmpUsedRegs,Tai(hp1.next));
  1815. If (RefsEqual(Taicpu(hp2).oper[1].ref^, Taicpu(p).oper[0].ref^) And
  1816. Not(RegUsedAfterInstruction(Taicpu(p).oper[1].reg,
  1817. hp2, TmpUsedRegs)))
  1818. Then
  1819. { change mov (ref), reg }
  1820. { add/sub/or/... reg2/$const, reg }
  1821. { mov reg, (ref) }
  1822. { # release reg }
  1823. { to add/sub/or/... reg2/$const, (ref) }
  1824. Begin
  1825. case Taicpu(hp1).opcode of
  1826. A_INC,A_DEC:
  1827. Taicpu(hp1).LoadRef(0,Taicpu(p).oper[0].ref^)
  1828. else
  1829. Taicpu(hp1).LoadRef(1,Taicpu(p).oper[0].ref^);
  1830. end;
  1831. asml.Remove(p);
  1832. asml.Remove(hp2);
  1833. p.free;
  1834. hp2.free;
  1835. p := hp1
  1836. End;
  1837. End
  1838. End;
  1839. End;
  1840. End;
  1841. End;
  1842. p := Tai(p.next)
  1843. End;
  1844. End;
  1845. Procedure PostPeepHoleOpts(AsmL: TAAsmOutput; BlockStart, BlockEnd: Tai);
  1846. var
  1847. p,hp1,hp2: Tai;
  1848. Begin
  1849. P := BlockStart;
  1850. While (P <> BlockEnd) Do
  1851. Begin
  1852. Case p.Typ Of
  1853. Ait_Instruction:
  1854. Begin
  1855. Case Taicpu(p).opcode Of
  1856. A_CALL:
  1857. If (AktOptProcessor < ClassP6) And
  1858. GetNextInstruction(p, hp1) And
  1859. (hp1.typ = ait_instruction) And
  1860. (Taicpu(hp1).opcode = A_JMP) And
  1861. (Taicpu(hp1).oper[0].typ = top_symbol) Then
  1862. Begin
  1863. hp2 := Taicpu.Op_sym(A_PUSH,S_L,Taicpu(hp1).oper[0].sym);
  1864. InsertLLItem(AsmL, p.previous, p, hp2);
  1865. Taicpu(p).opcode := A_JMP;
  1866. Taicpu(p).is_jmp := true;
  1867. asml.Remove(hp1);
  1868. hp1.free;
  1869. End;
  1870. A_CMP:
  1871. Begin
  1872. if (Taicpu(p).oper[0].typ = top_const) and
  1873. (Taicpu(p).oper[0].val = 0) and
  1874. (Taicpu(p).oper[1].typ = top_reg) then
  1875. {change "cmp $0, %reg" to "test %reg, %reg"}
  1876. begin
  1877. Taicpu(p).opcode := A_TEST;
  1878. Taicpu(p).loadreg(0,Taicpu(p).oper[1].reg);
  1879. continue;
  1880. end;
  1881. End;
  1882. A_MOV:
  1883. if (Taicpu(p).oper[0].typ = Top_Const) And
  1884. (Taicpu(p).oper[0].val = 0) And
  1885. (Taicpu(p).oper[1].typ = Top_Reg) Then
  1886. { change "mov $0, %reg" into "xor %reg, %reg" }
  1887. Begin
  1888. Taicpu(p).opcode := A_XOR;
  1889. Taicpu(p).LoadReg(0,Taicpu(p).oper[1].reg);
  1890. End;
  1891. A_MOVZX:
  1892. { if register vars are on, it's possible there is code like }
  1893. { "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx" }
  1894. { so we can't safely replace the movzx then with xor/mov, }
  1895. { since that would change the flags (JM) }
  1896. if not(cs_regalloc in aktglobalswitches) then
  1897. Begin
  1898. If (Taicpu(p).oper[1].typ = top_reg) Then
  1899. If (Taicpu(p).oper[0].typ = top_reg)
  1900. Then
  1901. Case Taicpu(p).opsize of
  1902. S_BL:
  1903. Begin
  1904. If IsGP32Reg(Taicpu(p).oper[1].reg) And
  1905. Not(CS_LittleSize in aktglobalswitches) And
  1906. (aktoptprocessor = ClassP5)
  1907. Then
  1908. {Change "movzbl %reg1, %reg2" to
  1909. "xorl %reg2, %reg2; movb %reg1, %reg2" for Pentium and
  1910. PentiumMMX}
  1911. Begin
  1912. hp1 := Taicpu.op_reg_reg(A_XOR, S_L,
  1913. Taicpu(p).oper[1].reg, Taicpu(p).oper[1].reg);
  1914. InsertLLItem(AsmL,p.previous, p, hp1);
  1915. Taicpu(p).opcode := A_MOV;
  1916. Taicpu(p).changeopsize(S_B);
  1917. Taicpu(p).LoadReg(1,rg.makeregsize(Taicpu(p).oper[1].reg,OS_8));
  1918. End;
  1919. End;
  1920. End
  1921. Else
  1922. If (Taicpu(p).oper[0].typ = top_ref) And
  1923. (Taicpu(p).oper[0].ref^.base <> Taicpu(p).oper[1].reg) And
  1924. (Taicpu(p).oper[0].ref^.index <> Taicpu(p).oper[1].reg) And
  1925. Not(CS_LittleSize in aktglobalswitches) And
  1926. IsGP32Reg(Taicpu(p).oper[1].reg) And
  1927. (aktoptprocessor = ClassP5) And
  1928. (Taicpu(p).opsize = S_BL)
  1929. Then
  1930. {changes "movzbl mem, %reg" to "xorl %reg, %reg; movb mem, %reg8" for
  1931. Pentium and PentiumMMX}
  1932. Begin
  1933. hp1 := Taicpu.Op_reg_reg(A_XOR, S_L, Taicpu(p).oper[1].reg,
  1934. Taicpu(p).oper[1].reg);
  1935. Taicpu(p).opcode := A_MOV;
  1936. Taicpu(p).changeopsize(S_B);
  1937. Taicpu(p).LoadReg(1,rg.makeregsize(Taicpu(p).oper[1].reg,OS_8));
  1938. InsertLLItem(AsmL,p.previous, p, hp1);
  1939. End;
  1940. End;
  1941. A_TEST, A_OR:
  1942. {removes the line marked with (x) from the sequence
  1943. And/or/xor/add/sub/... $x, %y
  1944. test/or %y, %y (x)
  1945. j(n)z _Label
  1946. as the first instruction already adjusts the ZF}
  1947. Begin
  1948. If OpsEqual(Taicpu(p).oper[0],Taicpu(p).oper[1]) Then
  1949. If GetLastInstruction(p, hp1) And
  1950. (Tai(hp1).typ = ait_instruction) Then
  1951. Case Taicpu(hp1).opcode Of
  1952. A_ADD, A_SUB, A_OR, A_XOR, A_AND{, A_SHL, A_SHR}:
  1953. Begin
  1954. If OpsEqual(Taicpu(hp1).oper[1],Taicpu(p).oper[0]) Then
  1955. Begin
  1956. hp1 := Tai(p.next);
  1957. asml.remove(p);
  1958. p.free;
  1959. p := Tai(hp1);
  1960. continue
  1961. End;
  1962. End;
  1963. A_DEC, A_INC, A_NEG:
  1964. Begin
  1965. If OpsEqual(Taicpu(hp1).oper[0],Taicpu(p).oper[0]) Then
  1966. Begin
  1967. Case Taicpu(hp1).opcode Of
  1968. A_DEC, A_INC:
  1969. {replace inc/dec with add/sub 1, because inc/dec doesn't set the carry flag}
  1970. Begin
  1971. Case Taicpu(hp1).opcode Of
  1972. A_DEC: Taicpu(hp1).opcode := A_SUB;
  1973. A_INC: Taicpu(hp1).opcode := A_ADD;
  1974. End;
  1975. Taicpu(hp1).Loadoper(1,Taicpu(hp1).oper[0]);
  1976. Taicpu(hp1).LoadConst(0,1);
  1977. Taicpu(hp1).ops:=2;
  1978. End
  1979. End;
  1980. hp1 := Tai(p.next);
  1981. asml.remove(p);
  1982. p.free;
  1983. p := Tai(hp1);
  1984. continue
  1985. End;
  1986. End
  1987. End
  1988. End;
  1989. End;
  1990. End;
  1991. End;
  1992. p := Tai(p.next)
  1993. End;
  1994. End;
  1995. End.
  1996. {
  1997. $Log$
  1998. Revision 1.23 2002-04-21 15:40:49 carl
  1999. * changeregsize -> rg.makeregsize
  2000. Revision 1.22 2002/04/20 21:37:07 carl
  2001. + generic FPC_CHECKPOINTER
  2002. + first parameter offset in stack now portable
  2003. * rename some constants
  2004. + move some cpu stuff to other units
  2005. - remove unused constents
  2006. * fix stacksize for some targets
  2007. * fix generic size problems which depend now on EXTEND_SIZE constant
  2008. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  2009. Revision 1.21 2002/04/15 19:44:21 peter
  2010. * fixed stackcheck that would be called recursively when a stack
  2011. error was found
  2012. * generic rg.makeregsize(reg,size) for i386 register resizing
  2013. * removed some more routines from cga unit
  2014. * fixed returnvalue handling
  2015. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  2016. Revision 1.20 2002/04/02 20:30:16 jonas
  2017. + support for folding inc/dec in shl/add/sub sequences toa single lea
  2018. instruction
  2019. Revision 1.19 2002/04/02 13:01:58 jonas
  2020. * fixed nasty bug in "and" peepholeoptimization that caused wrong
  2021. optimizations after Peter's big location patch
  2022. Revision 1.18 2002/03/31 20:26:40 jonas
  2023. + a_loadfpu_* and a_loadmm_* methods in tcg
  2024. * register allocation is now handled by a class and is mostly processor
  2025. independent (+rgobj.pas and i386/rgcpu.pas)
  2026. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  2027. * some small improvements and fixes to the optimizer
  2028. * some register allocation fixes
  2029. * some fpuvaroffset fixes in the unary minus node
  2030. * push/popusedregisters is now called rg.save/restoreusedregisters and
  2031. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  2032. also better optimizable)
  2033. * fixed and optimized register saving/restoring for new/dispose nodes
  2034. * LOC_FPU locations now also require their "register" field to be set to
  2035. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  2036. - list field removed of the tnode class because it's not used currently
  2037. and can cause hard-to-find bugs
  2038. Revision 1.17 2001/12/29 15:29:59 jonas
  2039. * powerpc/cgcpu.pas compiles :)
  2040. * several powerpc-related fixes
  2041. * cpuasm unit is now based on common tainst unit
  2042. + nppcmat unit for powerpc (almost complete)
  2043. Revision 1.16 2001/10/12 13:53:24 jonas
  2044. * fixed small crashing bug ("merged")
  2045. * some more optimizations are now only done once at the end of the optimizing
  2046. cycle instead of every iteration
  2047. Revision 1.15 2001/08/26 13:37:01 florian
  2048. * some cg reorganisation
  2049. * some PPC updates
  2050. Revision 1.14 2001/08/01 09:46:55 jonas
  2051. * fixed endless loop with web bug 1571 (merged)
  2052. Revision 1.13 2001/04/13 01:22:19 peter
  2053. * symtable change to classes
  2054. * range check generation and errors fixed, make cycle DEBUG=1 works
  2055. * memory leaks fixed
  2056. Revision 1.12 2001/04/06 14:06:03 jonas
  2057. * fixed incompatibility between new regvar handling and -Op2
  2058. Revision 1.11 2001/04/02 21:20:39 peter
  2059. * resulttype rewrite
  2060. Revision 1.10 2001/02/08 12:13:40 jonas
  2061. * fixed web bug 1391
  2062. Revision 1.9 2001/01/27 21:29:35 florian
  2063. * behavior -Oa optimized
  2064. Revision 1.8 2001/01/10 10:29:36 jonas
  2065. * really fixed problems with -Op2 opts (merged)
  2066. Revision 1.7 2001/01/07 15:49:49 jonas
  2067. * fixed bug in call/jmp optimization with -Op1 and -Op2
  2068. Revision 1.6 2000/12/25 00:07:33 peter
  2069. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  2070. tlinkedlist objects)
  2071. Revision 1.5 2000/12/16 16:00:12 jonas
  2072. * removed warnings about possible range check errors
  2073. Revision 1.4 2000/11/29 00:30:49 florian
  2074. * unused units removed from uses clause
  2075. * some changes for widestrings
  2076. Revision 1.3 2000/11/14 09:53:18 jonas
  2077. * added missing allocregbetween() (merged)
  2078. Revision 1.2 2000/10/24 10:40:54 jonas
  2079. + register renaming ("fixes" bug1088)
  2080. * changed command line options meanings for optimizer:
  2081. O2 now means peepholopts, CSE and register renaming in 1 pass
  2082. O3 is the same, but repeated until no further optimizations are
  2083. possible or until 5 passes have been done (to avoid endless loops)
  2084. * changed aopt386 so it does this looping
  2085. * added some procedures from csopt386 to the interface because they're
  2086. used by rropt386 as well
  2087. * some changes to csopt386 and daopt386 so that newly added instructions
  2088. by the CSE get optimizer info (they were simply skipped previously),
  2089. this fixes some bugs
  2090. Revision 1.1 2000/10/15 09:47:43 peter
  2091. * moved to i386/
  2092. Revision 1.13 2000/10/02 13:01:29 jonas
  2093. * fixed bug regarding removal of "test/or reg,reg": apparently, shr/shl
  2094. doesn't set the zero flag according to the contents of the register
  2095. after the shift :( (mergfed from fixes branch)
  2096. Revision 1.12 2000/09/24 15:06:23 peter
  2097. * use defines.inc
  2098. Revision 1.11 2000/09/18 11:28:36 jonas
  2099. * fixed web bug 1133 (merged from fixes branch)
  2100. Revision 1.10 2000/08/18 10:09:13 jonas
  2101. * fix for web bug1099 (merged from fixes branch)
  2102. Revision 1.9 2000/08/05 13:33:08 peter
  2103. * $ifdef go32v2 -> target_info.target=go32v2
  2104. Revision 1.8 2000/08/05 10:35:51 jonas
  2105. * readded l1 variable (between ifdef go32v2 to avoid hints/notes)
  2106. Revision 1.7 2000/08/04 22:00:52 peter
  2107. * merges from fixes
  2108. Revision 1.6 2000/07/31 08:44:05 jonas
  2109. - removed imul support from -dfoldarithops since "imull [reg32],[mem32]"
  2110. doesn't exist (merged from fixes branch)
  2111. Revision 1.5 2000/07/28 13:56:23 jonas
  2112. * fixed bug in shr/shl optimization when -Og is used (merged from fixes
  2113. branch)
  2114. Revision 1.4 2000/07/21 15:19:55 jonas
  2115. * daopt386: changes to getnextinstruction/getlastinstruction so they
  2116. ignore labels who have is_addr set
  2117. + daopt386/csopt386: remove loads of registers which are overwritten
  2118. before their contents are used (especially usefull for removing superfluous
  2119. maybe_loadself outputs and push/pops transformed by below optimization
  2120. + popt386: transform pop/pop/pop/.../push/push/push to sequences of
  2121. 'movl x(%esp),%reg' (only active when compiling a go32v2 compiler
  2122. currently because I don't know whether it's safe to do this under Win32/
  2123. Linux (because of problems we had when using esp as frame pointer on
  2124. those os'es)
  2125. Revision 1.3 2000/07/14 05:11:49 michael
  2126. + Patch to 1.1
  2127. Revision 1.2 2000/07/13 11:32:45 michael
  2128. + removed logs
  2129. }