csopt386.pas 89 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251
  1. {
  2. Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
  3. development team
  4. This unit contains the common subexpression elimination procedure.
  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 CSOpt386;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses aasmbase,aasmtai,aasmdata,aasmcpu, cpuinfo, cpubase, optbase, cgbase;
  22. function CSE(asml: TAsmList; first, last: tai; pass: longint): boolean;
  23. function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
  24. function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
  25. function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
  26. function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
  27. function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
  28. implementation
  29. uses
  30. {$ifdef csdebug}
  31. cutils,
  32. {$else}
  33. {$ifdef replaceregdebug}cutils,{$endif}
  34. {$endif}
  35. globtype, verbose, procinfo, globals, daopt386, rgobj, rropt386,cgutils;
  36. {
  37. function TaiInSequence(P: tai; Const Seq: TContent): Boolean;
  38. var P1: tai;
  39. Counter: Byte;
  40. TmpResult: Boolean;
  41. begin
  42. TmpResult := False;
  43. P1 := Seq.StartMod;
  44. Counter := 1;
  45. while not(TmpResult) and
  46. (Counter <= Seq.NrofMods) do
  47. begin
  48. if (P = P1) then TmpResult := True;
  49. inc(Counter);
  50. p1 := tai(p1.Next);
  51. end;
  52. TaiInSequence := TmpResult;
  53. end;
  54. }
  55. function modifiesConflictingMemLocation(p1: tai; supreg: tsuperregister; c: tregContent;
  56. var regsStillValid: tregset; onlymem: boolean; var invalsmemwrite: boolean): boolean;
  57. var
  58. p, hp: taicpu;
  59. tmpRef: treference;
  60. r,regCounter: tsuperregister;
  61. opCount: longint;
  62. dummy: boolean;
  63. begin
  64. modifiesConflictingMemLocation := false;
  65. invalsmemwrite := false;
  66. if p1.typ <> ait_instruction then
  67. exit;
  68. p := taicpu(p1);
  69. case p.opcode of
  70. A_MOV,A_MOVSX,A_MOVZX:
  71. if p.oper[1]^.typ = top_ref then
  72. for regCounter := RS_EAX to RS_EDI do
  73. begin
  74. if p.oper[0]^.typ<>top_reg then
  75. break;
  76. if writeToMemDestroysContents(getsupreg(p.oper[0]^.reg),p.oper[1]^.ref^,
  77. regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  78. begin
  79. exclude(regsStillValid,regCounter);
  80. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  81. end;
  82. if (regcounter = supreg) then
  83. invalsmemwrite := invalsmemwrite or dummy;
  84. end
  85. else
  86. { if is_reg_var[getsupreg(p.oper[1]^.reg)] then }
  87. if not onlymem then
  88. for regCounter := RS_EAX to RS_EDI do
  89. begin
  90. if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  91. begin
  92. exclude(regsStillValid,regCounter);
  93. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  94. end
  95. end;
  96. A_DIV, A_IDIV, A_MUL, A_IMUL:
  97. begin
  98. if not onlymem then
  99. if (p.ops = 1) then
  100. begin
  101. for regCounter := RS_EAX to RS_EDI do
  102. begin
  103. if writeToRegDestroysContents(RS_EDX,regCounter,c[regCounter]) then
  104. begin
  105. exclude(regsStillValid,RS_EDX);
  106. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  107. end;
  108. if writeToRegDestroysContents(RS_EAX,regCounter,c[regCounter]) then
  109. begin
  110. exclude(regsStillValid,RS_EAX);
  111. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  112. end;
  113. end
  114. end
  115. else
  116. { only possible for imul }
  117. { last operand is always destination }
  118. for regCounter := RS_EAX to RS_EDI do
  119. begin
  120. if writeDestroysContents(p.oper[p.ops-1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  121. begin
  122. exclude(regsStillValid,regCounter);
  123. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  124. end
  125. end
  126. end;
  127. else
  128. for opCount := 1 to maxinschanges do
  129. case InsProp[p.opcode].Ch[opCount] of
  130. Ch_MOp1,CH_WOp1,CH_RWOp1:
  131. if not(onlymem) or
  132. (p.oper[0]^.typ = top_ref) then
  133. { or ((p.oper[0]^.typ = top_reg) and }
  134. { is_reg_var[getsupreg(p.oper[0]^.reg)]) then }
  135. for regCounter := RS_EAX to RS_EDI do
  136. begin
  137. if writeDestroysContents(p.oper[0]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  138. begin
  139. exclude(regsStillValid,regCounter);
  140. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  141. end;
  142. if (regcounter = supreg) then
  143. invalsmemwrite := invalsmemwrite or dummy;
  144. end;
  145. Ch_MOp2,CH_WOp2,CH_RWOp2:
  146. if not(onlymem) or
  147. (p.oper[1]^.typ = top_ref) then
  148. { or ((p.oper[1]^.typ = top_reg) and }
  149. { is_reg_var[getsupreg(p.oper[1]^.reg)]) then }
  150. for regCounter := RS_EAX to RS_EDI do
  151. begin
  152. if writeDestroysContents(p.oper[1]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  153. begin
  154. exclude(regsStillValid,regCounter);
  155. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  156. end;
  157. if (regcounter = supreg) then
  158. invalsmemwrite := invalsmemwrite or dummy;
  159. end;
  160. Ch_MOp3,CH_WOp3,CH_RWOp3:
  161. if not(onlymem) or
  162. (p.oper[2]^.typ = top_ref) then
  163. { or ((p.oper[2]^.typ = top_reg) and }
  164. { is_reg_var[getsupreg(p.oper[2]^.reg)]) then }
  165. for regCounter := RS_EAX to RS_EDI do
  166. begin
  167. if writeDestroysContents(p.oper[2]^,regCounter,topsize2tcgsize[p.opsize],c[regCounter],dummy) then
  168. begin
  169. exclude(regsStillValid,regCounter);
  170. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  171. end;
  172. if (regcounter = supreg) then
  173. invalsmemwrite := invalsmemwrite or dummy;
  174. end;
  175. Ch_WMemEDI:
  176. begin
  177. fillchar(tmpref,sizeof(tmpref),0);
  178. tmpRef.base := NR_EDI;
  179. tmpRef.index := NR_EDI;
  180. for regCounter := RS_EAX to RS_EDI do
  181. if writeToMemDestroysContents(RS_INVALID,tmpRef,regCounter,OS_32,c[regCounter],dummy) then
  182. begin
  183. exclude(regsStillValid,regCounter);
  184. modifiesConflictingMemLocation := not(supreg in regsStillValid);
  185. end;
  186. if (regcounter = supreg) then
  187. invalsmemwrite := invalsmemwrite or dummy;
  188. end;
  189. end;
  190. end;
  191. end;
  192. function isSimpleMemLoc(const ref: treference): boolean;
  193. begin
  194. { isSimpleMemLoc :=
  195. (ref.index = RS_NO) and
  196. not(ref.base in (rg.usableregsint+[RS_EDI]));}
  197. isSimpleMemLoc :=
  198. (ref.index = NR_NO) and
  199. ((ref.base = NR_NO) or
  200. not(getsupreg(ref.base) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]));
  201. end;
  202. {checks whether the current instruction sequence (starting with p) and the
  203. one between StartMod and EndMod of Reg are the same. if so, the number of
  204. instructions that match is stored in Found and true is returned, otherwise
  205. Found holds the number of instructions between StartMod and EndMod and false
  206. is returned}
  207. function CheckSequence(p: tai; var prev: tai; supreg: tsuperregister; var Found: Longint;
  208. var reginfo: toptreginfo; findPrevSeqs: boolean): Boolean;
  209. var
  210. regsNotRead, regsStillValid : tregset;
  211. checkingPrevSequences,
  212. passedFlagsModifyingInstr,
  213. invalsmemwrite : boolean;
  214. function getPrevSequence(p: tai; supreg: tsuperregister; currentPrev: tai; var newPrev: tai): tsuperregister;
  215. const
  216. current_reg: tsuperregister = RS_INVALID;
  217. function stillValid(p: tai): boolean;
  218. var
  219. hp: tai;
  220. begin
  221. { only regvars are still used at jump instructions }
  222. if (cs_opt_regvar in aktoptimizerswitches) and
  223. (p.typ = ait_instruction) and
  224. taicpu(p).is_jmp then
  225. regsstillvalid := regsstillvalid - ptaiprop(p.optinfo)^.usedregs;
  226. stillValid :=
  227. (p.typ = ait_instruction) and
  228. (taicpu(p).opcode <> a_jmp) and
  229. (ptaiprop(p.optinfo)^.regs[supreg].wstate =
  230. ptaiprop(currentPrev.optinfo)^.regs[supreg].wstate) and
  231. { in case destroyreg is called with doIncState = false }
  232. (ptaiprop(p.optinfo)^.regs[supreg].typ =
  233. ptaiprop(currentPrev.optinfo)^.regs[supreg].typ) and
  234. (supreg in (regsNotRead * regsStillValid));
  235. { stop if the register was still used right before a (conditional) }
  236. { jump, since in that case its current contents could still be }
  237. { used in the other path of the jump) }
  238. if (p.typ = ait_instruction) and
  239. (taicpu(p).is_jmp) and
  240. getlastinstruction(p,hp) then
  241. stillValid := stillValid and
  242. not(supreg in ptaiprop(hp.optinfo)^.usedregs);
  243. passedFlagsModifyingInstr := passedFlagsModifyingInstr or
  244. instrWritesFlags(currentPrev);
  245. end;
  246. function findChangedRegister(p: tai): tsuperregister;
  247. var
  248. regCounter, loopstart: tsuperregister;
  249. begin
  250. if (current_reg <> RS_INVALID) then
  251. loopstart := succ(current_reg)
  252. else
  253. loopstart := RS_EAX;
  254. for regCounter := loopstart to RS_EDI do
  255. with ptaiprop(p.optinfo)^.regs[regCounter] do
  256. if ((startmod <>
  257. ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or
  258. (nrofMods <>
  259. ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and
  260. (ptaiprop(p.optinfo)^.regs[regCounter].typ in [con_ref,con_noRemoveRef]) then
  261. begin
  262. findChangedRegister := regCounter;
  263. current_reg := regCounter;
  264. exit;
  265. end;
  266. current_reg := RS_INVALID;
  267. findChangedRegister := RS_INVALID;
  268. end;
  269. var
  270. hp, prevFound: tai;
  271. tmpResult, regCounter: tsuperregister;
  272. invalsmemwrite: boolean;
  273. begin
  274. if (current_reg <> RS_EDI) and
  275. (current_reg <> RS_INVALID) then
  276. begin
  277. tmpResult := findChangedRegister(currentPrev);
  278. if tmpResult <> RS_INVALID then
  279. begin
  280. getPrevSequence := tmpResult;
  281. exit;
  282. end;
  283. end;
  284. getPrevSequence := RS_INVALID;
  285. passedFlagsModifyingInstr := passedFlagsModifyingInstr or
  286. instrWritesFlags(currentPrev);
  287. if (cs_opt_regvar in aktoptimizerswitches) and
  288. (currentprev.typ = ait_instruction) and
  289. taicpu(currentprev).is_jmp then
  290. regsstillvalid := regsstillvalid - ptaiprop(currentprev.optinfo)^.usedregs;
  291. if not getLastInstruction(currentPrev,hp) then
  292. exit;
  293. prevFound := currentPrev;
  294. tmpResult := RS_INVALID;
  295. while (tmpResult = RS_INVALID) and
  296. stillValid(hp) and
  297. (ptaiprop(prevFound.optinfo)^.canBeRemoved or
  298. not(modifiesConflictingMemLocation(prevFound,supreg,
  299. ptaiprop(p.optinfo)^.regs,regsStillValid,false, invalsmemwrite))) do
  300. begin
  301. { only update the regsread for the instructions we already passed }
  302. if not(ptaiprop(prevFound.optinfo)^.canBeRemoved) then
  303. for regCounter := RS_EAX to RS_EDI do
  304. if regReadByInstruction(regCounter,prevFound) then
  305. exclude(regsNotRead,regCounter);
  306. { in case getPreviousInstruction fails and sets hp to nil in the }
  307. { next iteration }
  308. prevFound := hp;
  309. if not(ptaiprop(hp.optinfo)^.canBeRemoved) then
  310. tmpResult := findChangedRegister(hp);
  311. if not getLastInstruction(hp,hp) then
  312. break;
  313. end;
  314. getPrevSequence := tmpResult;
  315. if tmpResult <> RS_INVALID then
  316. newPrev := prevFound;
  317. end;
  318. function getNextRegToTest(var prev: tai; currentReg: tsuperregister): tsuperregister;
  319. begin
  320. if not checkingPrevSequences then
  321. begin
  322. if (currentreg = RS_INVALID) then
  323. currentreg := RS_EAX
  324. else
  325. inc(currentreg);
  326. while (currentReg <= RS_EDI) and
  327. not(ptaiprop(prev.optinfo)^.regs[currentReg].typ in [con_ref,con_noRemoveRef]) do
  328. inc(currentReg);
  329. if currentReg > RS_EDI then
  330. begin
  331. if (taicpu(p).oper[0]^.typ <> top_ref) or
  332. isSimpleMemLoc(taicpu(p).oper[0]^.ref^) then
  333. begin
  334. checkingPrevSequences := true;
  335. end
  336. else
  337. getNextRegToTest := RS_INVALID;
  338. end
  339. else
  340. getNextRegToTest := currentReg;
  341. end;
  342. if checkingPrevSequences then
  343. if findPrevSeqs then
  344. getNextRegToTest :=
  345. getPrevSequence(p,supreg,prev,prev)
  346. else
  347. getNextRegToTest := RS_INVALID;
  348. end;
  349. function changedreginvalidatedbetween(const oldreginfo: toptreginfo; var newreginfo: toptreginfo; startp,endp,current: tai): boolean;
  350. var
  351. orgdiffregs,diffregs: tregset;
  352. runner: tai;
  353. invalsmemwrite: boolean;
  354. begin
  355. diffregs := newreginfo.newregsencountered - oldreginfo.newregsencountered;
  356. orgdiffregs := diffregs;
  357. if diffregs <> [] then
  358. begin
  359. runner := startp;
  360. repeat
  361. modifiesConflictingMemLocation(runner,RS_EAX { dummy },ptaiprop(current.optinfo)^.regs,diffregs,true,invalsmemwrite);
  362. if orgdiffregs <> diffregs then
  363. begin
  364. changedreginvalidatedbetween := true;
  365. newreginfo := oldreginfo;
  366. exit;
  367. end;
  368. getnextinstruction(runner,runner);
  369. until (runner = endp);
  370. end;
  371. changedreginvalidatedbetween := false;
  372. end;
  373. var
  374. prevreginfo: toptreginfo;
  375. hp2, hp3{, EndMod}, prevhp3, highPrev, orgPrev, pprev: tai;
  376. {Cnt,} OldNrofMods: Longint;
  377. startRegInfo, OrgRegInfo, HighRegInfo: toptreginfo;
  378. regModified, lastregloadremoved: array[RS_EAX..RS_ESP] of boolean;
  379. HighFound, OrgRegFound: longint;
  380. regcounter, regCounter2, tmpreg, base, index: tsuperregister;
  381. OrgRegResult: Boolean;
  382. TmpResult, flagResultsNeeded, stopchecking: Boolean;
  383. begin {CheckSequence}
  384. TmpResult := False;
  385. FillChar(OrgRegInfo, Sizeof(OrgRegInfo), 0);
  386. FillChar(startRegInfo, sizeof(startRegInfo), 0);
  387. OrgRegFound := 0;
  388. HighFound := 0;
  389. OrgRegResult := False;
  390. with startRegInfo do
  391. begin
  392. newRegsEncountered := [RS_EBP, RS_ESP];
  393. fillword(new2oldreg,sizeof(new2oldreg),RS_INVALID);
  394. new2OldReg[RS_EBP] := RS_EBP;
  395. new2OldReg[RS_ESP] := RS_ESP;
  396. oldRegsEncountered := newRegsEncountered;
  397. end;
  398. checkingPrevSequences := false;
  399. passedFlagsModifyingInstr := false;
  400. flagResultsNeeded := false;
  401. regsNotRead := [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESP,RS_EBP,RS_EDI,RS_ESI];
  402. regsStillValid := regsNotRead;
  403. GetLastInstruction(p, prev);
  404. pprev := prev;
  405. tmpreg:=RS_INVALID;
  406. regCounter := getNextRegToTest(prev,tmpreg);
  407. while (regcounter <> RS_INVALID) do
  408. begin
  409. fillchar(regModified,sizeof(regModified),0);
  410. fillchar(lastregloadremoved,sizeof(lastregloadremoved),0);
  411. reginfo := startRegInfo;
  412. Found := 0;
  413. hp2 := ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod;
  414. if (prev <> ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod) then
  415. OldNrofMods := ptaiprop(prev.optinfo)^.Regs[regcounter].NrofMods
  416. else
  417. OldNrofMods := 1;
  418. hp3 := p;
  419. if checkingprevsequences then
  420. prevreginfo := reginfo;
  421. stopchecking := false;
  422. while (Found <> OldNrofMods) and
  423. { old new }
  424. InstructionsEquivalent(hp2, hp3, reginfo) and
  425. (not(checkingprevsequences) or
  426. not(changedreginvalidatedbetween(prevreginfo,reginfo,prev,p,hp3))) do
  427. begin
  428. if checkingprevsequences then
  429. begin
  430. prevreginfo := reginfo;
  431. end;
  432. if (hp3.typ = ait_instruction) and
  433. ((taicpu(hp3).opcode = A_MOV) or
  434. (taicpu(hp3).opcode = A_MOVZX) or
  435. (taicpu(hp3).opcode = A_LEA) or
  436. (taicpu(hp3).opcode = A_MOVSX)) and
  437. (taicpu(hp3).oper[1]^.typ = top_reg) and
  438. not(regInOp(getsupreg(taicpu(hp3).oper[1]^.reg),taicpu(hp3).oper[0]^)) then
  439. begin
  440. tmpreg := getsupreg(taicpu(hp3).oper[1]^.reg);
  441. lastregloadremoved[tmpreg] := ptaiprop(hp2.optinfo)^.canberemoved;
  442. reginfo.lastReload[tmpreg] := hp3;
  443. case taicpu(hp3).oper[0]^.typ of
  444. top_ref:
  445. begin
  446. base := getsupreg(taicpu(hp3).oper[0]^.ref^.base);
  447. index := getsupreg(taicpu(hp3).oper[0]^.ref^.index);
  448. if (found <> 0) and
  449. ((taicpu(hp3).oper[0]^.ref^.base = NR_NO) or
  450. regModified[base] or
  451. (base = getsupreg(current_procinfo.framepointer))) and
  452. ((taicpu(hp3).oper[0]^.ref^.index = NR_NO) or
  453. regModified[index]) and
  454. not(regInRef(tmpReg,taicpu(hp3).oper[0]^.ref^)) then
  455. begin
  456. with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
  457. if nrofMods > (oldNrofMods - found) then
  458. oldNrofMods := found + nrofMods;
  459. { next is safe because instructions are equivalent }
  460. with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
  461. if nrofMods > (oldNrofMods - found) then
  462. oldNrofMods := found + nrofMods;
  463. end;
  464. end;
  465. top_reg:
  466. if regModified[getsupreg(taicpu(hp3).oper[0]^.reg)] then
  467. begin
  468. with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
  469. if nrofMods > (oldNrofMods - found) then
  470. oldNrofMods := found + nrofMods;
  471. with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
  472. if nrofMods > (oldNrofMods - found) then
  473. oldNrofMods := found + nrofMods;
  474. end;
  475. end;
  476. end;
  477. for regCounter2 := RS_EAX to RS_EDI do
  478. regModified[regCounter2] := regModified[regCounter2] or
  479. regModifiedByInstruction(regCounter2,hp3);
  480. if flagResultsNeeded then
  481. flagResultsNeeded := not instrReadsFlags(hp3);
  482. if not flagResultsNeeded then
  483. flagResultsNeeded := ptaiprop(hp3.optinfo)^.FlagsUsed;
  484. inc(Found);
  485. prevhp3 := hp3;
  486. if (Found <> OldNrofMods) then
  487. if not GetNextInstruction(hp2, hp2) or
  488. not GetNextInstruction(hp3, hp3) then
  489. break;
  490. end;
  491. if assigned(hp3) then
  492. begin
  493. prevhp3 := hp3;
  494. getnextinstruction(hp3,hp3);
  495. end;
  496. if not assigned(hp3) or
  497. { a marker has no optinfo, which is used below }
  498. (hp3.typ = ait_marker) then
  499. hp3 := prevhp3;
  500. {
  501. a) movl -4(%ebp),%edx
  502. movl -12(%ebp),%ecx
  503. ...
  504. movl -8(%ebp),%eax
  505. movl -12(%ebp),%edx (marked as removable)
  506. movl (%eax,%edx),%eax (replaced by "movl (%eax,%ecx),%eax")
  507. ...
  508. movl -8(%ebp),%eax
  509. movl -12(%ebp),%edx
  510. movl (%eax,%edx),%eax
  511. movl (%edx),%edx
  512. -> the "movl -12(ebp),%edx" can't be removed in the last sequence, because
  513. edx has not been replaced with ecx there, and edx is still used after the
  514. sequence
  515. b) tests/webtbs/tw4266.pp
  516. }
  517. for regCounter2 := RS_EAX to RS_EDI do
  518. if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
  519. (regCounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
  520. { case a) above }
  521. ((not regLoadedWithNewValue(regCounter2,false,hp3) and
  522. lastregloadremoved[regcounter2]) or
  523. { case b) above }
  524. ((ptaiprop(pprev.optinfo)^.regs[regcounter2].wstate <>
  525. ptaiprop(hp2.optinfo)^.regs[regcounter2].wstate))) then
  526. begin
  527. found := 0;
  528. end;
  529. if checkingPrevSequences then
  530. begin
  531. for regCounter2 := RS_EAX to RS_EDI do
  532. if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
  533. (reginfo.new2OldReg[regCounter2] <> regCounter2) and
  534. (not(regCounter2 in (regsNotRead * regsStillValid)) or
  535. not(reginfo.new2OldReg[regCounter2] in regsStillValid)) then
  536. begin
  537. found := 0;
  538. break;
  539. end;
  540. if passedFlagsModifyingInstr and flagResultsNeeded then
  541. found := 0;
  542. end;
  543. TmpResult := true;
  544. if (found <> OldNrofMods) then
  545. TmpResult := false
  546. else if assigned(hp3) then
  547. for regcounter2 := RS_EAX to RS_EDI do
  548. if (regcounter2 in reginfo.regsLoadedforRef) and
  549. regModified[regcounter2] and
  550. (regcounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
  551. not regLoadedWithNewValue(regcounter2,false,hp3) then
  552. begin
  553. TmpResult := False;
  554. if (found > 0) then
  555. {this is correct because we only need to turn off the CanBeRemoved flag
  556. when an instruction has already been processed by CheckSequence
  557. (otherwise CanBeRemoved can't be true and thus can't have to be turned off).
  558. if it has already been processed by CheckSequence and flagged to be
  559. removed, it means that it has been checked against a previous sequence
  560. and that it was equal (otherwise CheckSequence would have returned false
  561. and the instruction wouldn't have been removed). if this "if found > 0"
  562. check is left out, incorrect optimizations are performed.}
  563. Found := ptaiprop(tai(p).optinfo)^.Regs[supreg].NrofMods;
  564. break;
  565. end;
  566. if TmpResult and
  567. (Found > HighFound) then
  568. begin
  569. highPrev := prev;
  570. HighFound := Found;
  571. HighRegInfo := reginfo;
  572. end;
  573. if (regcounter = supreg) then
  574. begin
  575. orgPrev := prev;
  576. OrgRegFound := Found;
  577. OrgRegResult := TmpResult;
  578. OrgRegInfo := reginfo
  579. end;
  580. regCounter := getNextRegToTest(prev,regCounter);
  581. end;
  582. if (HighFound > 0) and
  583. (not(OrgRegResult) Or
  584. (HighFound > OrgRegFound))
  585. then
  586. begin
  587. {$ifndef fpc}
  588. TmpResult := True;
  589. {$else fpc}
  590. CheckSequence := True;
  591. {$endif fpc}
  592. prev := highPrev;
  593. reginfo := HighRegInfo;
  594. Found := HighFound
  595. end
  596. else
  597. begin
  598. {$ifndef fpc}
  599. TmpResult := OrgRegResult;
  600. {$else fpc}
  601. CheckSequence := OrgRegResult;
  602. {$endif fpc}
  603. prev := orgPrev;
  604. Found := OrgRegFound;
  605. reginfo := OrgRegInfo;
  606. end;
  607. {$ifndef fpc}
  608. CheckSequence := TmpResult;
  609. {$endif fpc}
  610. end; {CheckSequence}
  611. procedure SetAlignReg(p: tai);
  612. Const alignSearch = 12;
  613. var regsUsable: TRegSet;
  614. prevInstrCount, nextInstrCount: Longint;
  615. prevState, nextWState,nextRState: Array[RS_EAX..RS_EDI] of byte;
  616. regCounter, lastRemoved: tsuperregister;
  617. prev, next: tai;
  618. {$ifdef alignregdebug}
  619. temp: tai;
  620. {$endif alignregdebug}
  621. begin
  622. regsUsable := [RS_EAX,RS_ECX,RS_EDX,RS_EBX,{R_ESP,RS_EBP,}RS_ESI,RS_EDI];
  623. for regCounter := RS_EAX to RS_EDI do
  624. begin
  625. prevState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
  626. nextWState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].wState;
  627. nextRState[regCounter] := ptaiprop(p.optinfo)^.Regs[regCounter].rState;
  628. end;
  629. getLastInstruction(p,prev);
  630. getNextInstruction(p,next);
  631. lastRemoved := getsupreg(tai_align(p).reg);
  632. nextInstrCount := 0;
  633. prevInstrCount := 0;
  634. while ((assigned(prev) and
  635. assigned(prev.optinfo) and
  636. (prevInstrCount < alignSearch)) or
  637. (assigned(next) and
  638. assigned(next.optinfo) and
  639. (nextInstrCount < alignSearch))) and
  640. (regsUsable <> []) do
  641. begin
  642. {$ifdef alignregdebug}
  643. if assigned(prev) then
  644. begin
  645. temp := tai_comment.Create(strpnew('got here'));
  646. temp.next := prev.next;
  647. temp.previous := prev;
  648. prev.next := temp;
  649. if assigned(temp.next) then
  650. temp.next.previous := temp;
  651. end;
  652. {$endif alignregdebug}
  653. if assigned(prev) and assigned(prev.optinfo) and
  654. (prevInstrCount < alignSearch) then
  655. begin
  656. if (prev.typ = ait_instruction) and
  657. (insProp[taicpu(prev).opcode].ch[1] <> Ch_ALL) and
  658. (taicpu(prev).opcode <> A_JMP) then
  659. begin
  660. inc(prevInstrCount);
  661. for regCounter := RS_EAX to RS_EDI do
  662. begin
  663. if (regCounter in regsUsable) and
  664. (ptaiprop(prev.optinfo)^.Regs[regCounter].wState <>
  665. prevState[regCounter]) then
  666. begin
  667. lastRemoved := regCounter;
  668. exclude(regsUsable,regCounter);
  669. {$ifdef alignregdebug}
  670. temp := tai_comment.Create(strpnew(
  671. std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
  672. temp.next := prev.next;
  673. temp.previous := prev;
  674. prev.next := temp;
  675. if assigned(temp.next) then
  676. temp.next.previous := temp;
  677. if regsUsable = [] then
  678. begin
  679. temp := tai_comment.Create(strpnew(
  680. 'regsUsable empty here')));
  681. temp.next := prev.next;
  682. temp.previous := prev;
  683. prev.next := temp;
  684. if assigned(temp.next) then
  685. temp.next.previous := temp;
  686. end;
  687. {$endif alignregdebug}
  688. end;
  689. prevState[regCounter] :=
  690. ptaiprop(prev.optinfo)^.Regs[regCounter].wState;
  691. end;
  692. getLastInstruction(prev,prev);
  693. end
  694. else
  695. if GetLastInstruction(prev,prev) and
  696. assigned(prev.optinfo) then
  697. for regCounter := RS_EAX to RS_EDI do
  698. prevState[regCounter] :=
  699. ptaiprop(prev.optinfo)^.Regs[regCounter].wState
  700. end;
  701. if assigned(next) and assigned(next.optinfo) and
  702. (nextInstrCount < alignSearch) then
  703. begin
  704. if (next.typ = ait_instruction) and
  705. (insProp[taicpu(next).opcode].ch[1] <> Ch_ALL) and
  706. (taicpu(next).opcode <> A_JMP) then
  707. begin
  708. inc(nextInstrCount);
  709. for regCounter := RS_EAX to RS_EDI do
  710. begin
  711. if (regCounter in regsUsable) and
  712. ((ptaiprop(next.optinfo)^.Regs[regCounter].wState <>
  713. nextWState[regCounter]) or
  714. (ptaiprop(next.optinfo)^.Regs[regCounter].rState <>
  715. nextRState[regCounter])) then
  716. begin
  717. lastRemoved := regCounter;
  718. exclude(regsUsable,regCounter);
  719. {$ifdef alignregdebug}
  720. temp := tai_comment.Create(strpnew(
  721. std_regname(newreg(R_INTREGISTER,regCounter,R_SUBWHOLE))+' removed')));
  722. temp.next := next.next;
  723. temp.previous := next;
  724. next.next := temp;
  725. if assigned(temp.next) then
  726. temp.next.previous := temp;
  727. if regsUsable = [] then
  728. begin
  729. temp := tai_comment.Create(strpnew(
  730. 'regsUsable empty here')));
  731. temp.next := next.next;
  732. temp.previous := next;
  733. next.next := temp;
  734. if assigned(temp.next) then
  735. temp.next.previous := temp;
  736. end;
  737. {$endif alignregdebug}
  738. end;
  739. nextWState[regCounter] :=
  740. ptaiprop(next.optinfo)^.Regs[regCounter].wState;
  741. nextRState[regCounter] :=
  742. ptaiprop(next.optinfo)^.Regs[regCounter].rState;
  743. end
  744. end
  745. else
  746. for regCounter := RS_EAX to RS_EDI do
  747. begin
  748. nextWState[regCounter] :=
  749. ptaiprop(next.optinfo)^.Regs[regCounter].wState;
  750. nextRState[regCounter] :=
  751. ptaiprop(next.optinfo)^.Regs[regCounter].rState;
  752. end;
  753. getNextInstruction(next,next);
  754. end;
  755. end;
  756. if regsUsable <> [] then
  757. for regCounter := RS_EAX to RS_EDI do
  758. if regCounter in regsUsable then
  759. begin
  760. lastRemoved := regCounter;
  761. break
  762. end;
  763. {$ifdef alignregdebug}
  764. next := tai_comment.Create(strpnew(std_regname(newreg(R_INTREGISTER,lastremoved,R_SUBWHOLE))+
  765. ' chosen as alignment register')));
  766. next.next := p.next;
  767. next.previous := p;
  768. p.next := next;
  769. if assigned(next.next) then
  770. next.next.previous := next;
  771. {$endif alignregdebug}
  772. tai_align(p).reg := newreg(R_INTREGISTER,lastRemoved,R_SUBWHOLE);
  773. end;
  774. procedure clearmemwrites(p: tai; supreg: tsuperregister);
  775. var
  776. beginmemwrite: tai;
  777. begin
  778. beginmemwrite := ptaiprop(p.optinfo)^.regs[supreg].memwrite;
  779. repeat
  780. ptaiprop(p.optinfo)^.regs[supreg].memwrite := nil;
  781. until not getnextinstruction(p,p) or
  782. (ptaiprop(p.optinfo)^.regs[supreg].memwrite <> beginmemwrite);
  783. end;
  784. procedure ClearRegContentsFrom(asml: TAsmList; supreg: tsuperregister; p, endP: tai);
  785. { first clears the contents of reg from p till endP. then the contents are }
  786. { cleared until the first instruction that changes reg }
  787. var
  788. {$ifdef replaceregdebug}
  789. hp: tai;
  790. l: longint;
  791. {$endif replaceregdebug}
  792. regcounter: tsuperregister;
  793. oldStartmod: tai;
  794. regstoclear: tregset;
  795. begin
  796. {$ifdef replaceregdebug}
  797. l := random(1000);
  798. hp := tai_comment.Create(strpnew(
  799. 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' from here... '+tostr(l)));
  800. insertllitem(asml,p.previous,p,hp);
  801. {$endif replaceregdebug}
  802. ptaiprop(p.optinfo)^.Regs[supreg].typ := con_unknown;
  803. regstoclear := [supreg];
  804. while (p <> endP) do
  805. begin
  806. for regcounter := RS_EAX to RS_EDI do
  807. begin
  808. if (regcounter <> supreg) and
  809. assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
  810. reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
  811. clearmemwrites(p,regcounter);
  812. { needs double loop to cheack for each dependency combination? }
  813. if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
  814. sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
  815. include(regstoclear,regcounter);
  816. if regcounter in regstoclear then
  817. with ptaiprop(p.optinfo)^.Regs[regcounter] do
  818. begin
  819. typ := con_unknown;
  820. memwrite := nil;
  821. startmod := nil;
  822. nrofmods := 0;
  823. end;
  824. end;
  825. getNextInstruction(p,p);
  826. end;
  827. oldStartmod := ptaiprop(p.optinfo)^.Regs[supreg].startmod;
  828. repeat
  829. for regcounter := RS_EAX to RS_EDI do
  830. begin
  831. { needs double loop to cheack for each dependency combination? }
  832. if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
  833. sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
  834. include(regstoclear,regcounter);
  835. with ptaiprop(p.optinfo)^.Regs[supreg] do
  836. if regcounter in regstoclear then
  837. begin
  838. typ := con_unknown;
  839. memwrite := nil;
  840. end;
  841. end;
  842. until not getNextInstruction(p,p) or
  843. (ptaiprop(p.optinfo)^.Regs[supreg].startmod <> oldStartmod);
  844. {$ifdef replaceregdebug}
  845. if assigned(p) then
  846. begin
  847. hp := tai_comment.Create(strpnew(
  848. 'cleared '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
  849. insertllitem(asml,p.previous,p,hp);
  850. end;
  851. {$endif replaceregdebug}
  852. end;
  853. procedure RestoreRegContentsTo(asml: TAsmList; supreg: tsuperregister; const c: TContent; p, endP: tai);
  854. var
  855. {$ifdef replaceregdebug}
  856. l: longint;
  857. {$endif replaceregdebug}
  858. hp: tai;
  859. validregs, prevvalidregs: tregset;
  860. regcounter: tsuperregister;
  861. tmpState, newrstate: byte;
  862. prevcontenttyp: byte;
  863. memconflict: boolean;
  864. invalsmemwrite: boolean;
  865. begin
  866. {$ifdef replaceregdebug}
  867. l := random(1000);
  868. hp := tai_comment.Create(strpnew(
  869. 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' with data from here... '+tostr(l)));
  870. insertllitem(asml,p.previous,p,hp);
  871. {$endif replaceregdebug}
  872. { ptaiprop(p.optinfo)^.Regs[reg] := c;}
  873. newrstate := c.rstate;
  874. incstate(newrstate,$7f);
  875. memconflict := false;
  876. invalsmemwrite := false;
  877. validregs := [RS_EAX..RS_EDI];
  878. prevvalidregs := validregs;
  879. while (p <> endP) and
  880. not(memconflict) and
  881. not(invalsmemwrite) do
  882. begin
  883. if not(ptaiprop(p.optinfo)^.canberemoved) and
  884. regreadbyinstruction(supreg,p) then
  885. incstate(newrstate,1);
  886. // is this a write to memory that destroys the contents we are restoring?
  887. memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
  888. if (validregs <> prevvalidregs) then
  889. begin
  890. prevvalidregs := validregs >< prevvalidregs;
  891. for regcounter := RS_EAX to RS_EDI do
  892. if regcounter in prevvalidregs then
  893. clearRegContentsFrom(asml,regcounter,p,endP);
  894. end;
  895. prevvalidregs := validregs;
  896. if (not memconflict and not invalsmemwrite) then
  897. begin
  898. ptaiprop(p.optinfo)^.Regs[supreg] := c;
  899. ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
  900. end
  901. else
  902. begin
  903. clearRegContentsFrom(asml,supreg,p,endP);
  904. {$ifdef replaceregdebug}
  905. if assigned(p) then
  906. begin
  907. hp := tai_comment.Create(strpnew(
  908. 'stopping restoring of '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+'because memory conflict... '+tostr(l)));
  909. insertllitem(asml,p,p.next,hp);
  910. end;
  911. {$endif replaceregdebug}
  912. exit
  913. end;
  914. getNextInstruction(p,p);
  915. end;
  916. tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState;
  917. if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then
  918. begin
  919. incstate(ptaiprop(p.optinfo)^.regs[supreg].rstate,63);
  920. if not getnextinstruction(p,hp) then
  921. exit;
  922. if (ptaiprop(hp.optinfo)^.regs[supreg].rstate = ptaiprop(p.optinfo)^.regs[supreg].rstate) then
  923. internalerror(2004122710);
  924. end;
  925. repeat
  926. newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState;
  927. prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ;
  928. // is this a write to memory that destroys the contents we are restoring?
  929. memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
  930. if (validregs <> prevvalidregs) then
  931. begin
  932. prevvalidregs := validregs >< prevvalidregs;
  933. for regcounter := RS_EAX to RS_EDI do
  934. if regcounter in prevvalidregs then
  935. clearRegContentsFrom(asml,regcounter,p,p);
  936. end;
  937. prevvalidregs := validregs;
  938. if (not memconflict and not invalsmemwrite) then
  939. begin
  940. ptaiprop(p.optinfo)^.Regs[supreg] := c;
  941. ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
  942. end;
  943. until invalsmemwrite or
  944. memconflict or
  945. not getNextInstruction(p,p) or
  946. (ptaiprop(p.optinfo)^.Regs[supreg].wState <> tmpState) or
  947. (p.typ = ait_label) or
  948. ((prevcontenttyp <> con_invalid) and
  949. (ptaiprop(p.optinfo)^.Regs[supreg].typ = con_invalid));
  950. if assigned(p) and
  951. (p.typ <> ait_marker) then
  952. if ((p.typ = ait_label) or
  953. memconflict or
  954. invalsmemwrite) then
  955. clearRegContentsFrom(asml,supreg,p,p)
  956. else if (ptaiprop(p.optinfo)^.Regs[supreg].rstate = newrstate) then
  957. incstate(ptaiprop(p.optinfo)^.Regs[supreg].rstate,20);
  958. {$ifdef replaceregdebug}
  959. if assigned(p) then
  960. begin
  961. hp := tai_comment.Create(strpnew(
  962. 'restored '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+' till here... '+tostr(l)));
  963. insertllitem(asml,p,p.next,hp);
  964. end;
  965. {$endif replaceregdebug}
  966. end;
  967. function NoHardCodedRegs(p: taicpu; orgReg, newReg: tsuperregister): boolean;
  968. var
  969. chCount: byte;
  970. begin
  971. case p.opcode of
  972. A_IMUL: noHardCodedRegs := p.ops <> 1;
  973. A_SHL,A_SHR,A_SHLD,A_SHRD: noHardCodedRegs :=
  974. (p.oper[0]^.typ <> top_reg) or
  975. ((orgReg <> RS_ECX) and (newReg <> RS_ECX));
  976. else
  977. begin
  978. NoHardCodedRegs := true;
  979. with InsProp[p.opcode] do
  980. for chCount := 1 to maxinschanges do
  981. if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
  982. begin
  983. NoHardCodedRegs := false;
  984. break
  985. end;
  986. end;
  987. end;
  988. end;
  989. function ChangeReg(var Reg: TRegister; newReg, orgReg: tsuperregister): boolean;
  990. begin
  991. changereg := false;
  992. if (reg <> NR_NO) and
  993. (getregtype(reg) = R_INTREGISTER) and
  994. (getsupreg(reg) = newreg) then
  995. begin
  996. changereg := true;
  997. setsupreg(reg,orgreg);
  998. end;
  999. end;
  1000. function changeOp(var o: toper; newReg, orgReg: tsuperregister): boolean;
  1001. var
  1002. tmpresult: boolean;
  1003. begin
  1004. changeOp := false;
  1005. case o.typ of
  1006. top_reg: changeOp := changeReg(o.reg,newReg,orgReg);
  1007. top_ref:
  1008. begin
  1009. tmpresult := changeReg(o.ref^.base,newReg,orgReg);
  1010. changeop := changeReg(o.ref^.index,newReg,orgReg) or tmpresult;
  1011. end;
  1012. end;
  1013. end;
  1014. procedure updateStates(orgReg,newReg: tsuperregister; hp: tai; writeStateToo: boolean);
  1015. var
  1016. prev: tai;
  1017. newOrgRegRState, newOrgRegWState: byte;
  1018. begin
  1019. if getLastInstruction(hp,prev) then
  1020. with ptaiprop(prev.optinfo)^ do
  1021. begin
  1022. newOrgRegRState := byte(longint(regs[orgReg].rState) +
  1023. longint(ptaiprop(hp.optinfo)^.regs[newReg].rState) - regs[newReg].rstate);
  1024. if writeStateToo then
  1025. newOrgRegWState := byte(longint(regs[orgReg].wState) +
  1026. longint(ptaiprop(hp.optinfo)^.regs[newReg].wState) - regs[newReg].wstate);
  1027. end
  1028. else
  1029. with ptaiprop(hp.optinfo)^.regs[newReg] do
  1030. begin
  1031. newOrgRegRState := rState;
  1032. if writeStateToo then
  1033. newOrgRegWState := wState;
  1034. end;
  1035. with ptaiprop(hp.optinfo)^.regs[orgReg] do
  1036. begin
  1037. rState := newOrgRegRState;
  1038. if writeStateToo then
  1039. wState := newOrgRegwState;
  1040. end;
  1041. end;
  1042. function doReplaceReg(hp: taicpu; newReg, orgReg: tsuperregister): boolean;
  1043. var
  1044. opCount: longint;
  1045. tmpResult: boolean;
  1046. begin
  1047. tmpresult := false;
  1048. for opCount := 0 to hp.ops-1 do
  1049. tmpResult :=
  1050. changeOp(hp.oper[opCount]^,newReg,orgReg) or tmpResult;
  1051. doReplaceReg := tmpResult;
  1052. end;
  1053. function RegSizesOK(oldReg,newReg: tsuperregister; p: taicpu): boolean;
  1054. { oldreg and newreg must be 32bit components }
  1055. var
  1056. opCount: longint;
  1057. tmpreg: tsuperregister;
  1058. begin
  1059. RegSizesOK := true;
  1060. { if only one of them is a general purpose register ... }
  1061. if (IsGP32reg(oldReg) xor IsGP32Reg(newReg)) then
  1062. begin
  1063. for opCount := 0 to p.ops-1 do
  1064. if (p.oper[opCount]^.typ = top_reg) and
  1065. (getsubreg(p.oper[opCount]^.reg) in [R_SUBL,R_SUBH]) then
  1066. begin
  1067. tmpreg := getsupreg(p.oper[opCount]^.reg);
  1068. if (tmpreg = oldreg) or
  1069. (tmpreg = newreg) then
  1070. begin
  1071. RegSizesOK := false;
  1072. break
  1073. end
  1074. end;
  1075. end;
  1076. end;
  1077. function doReplaceReadReg(p: taicpu; newReg,orgReg: tsuperregister): boolean;
  1078. var
  1079. opCount: longint;
  1080. begin
  1081. doReplaceReadReg := false;
  1082. { handle special case }
  1083. case p.opcode of
  1084. A_IMUL:
  1085. begin
  1086. case p.ops of
  1087. 1: internalerror(1301001);
  1088. 2,3:
  1089. begin
  1090. if changeOp(p.oper[0]^,newReg,orgReg) then
  1091. begin
  1092. { updateStates(orgReg,newReg,p,false);}
  1093. doReplaceReadReg := true;
  1094. end;
  1095. if p.ops = 3 then
  1096. if changeOp(p.oper[1]^,newReg,orgReg) then
  1097. begin
  1098. { updateStates(orgReg,newReg,p,false);}
  1099. doReplaceReadReg := true;
  1100. end;
  1101. end;
  1102. end;
  1103. end;
  1104. A_DIV,A_IDIV,A_MUL: internalerror(1301002);
  1105. else
  1106. begin
  1107. for opCount := 0 to p.ops-1 do
  1108. if p.oper[opCount]^.typ = top_ref then
  1109. if changeOp(p.oper[opCount]^,newReg,orgReg) then
  1110. begin
  1111. { updateStates(orgReg,newReg,p,false);}
  1112. doReplaceReadReg := true;
  1113. end;
  1114. for opCount := 1 to maxinschanges do
  1115. case InsProp[p.opcode].Ch[opCount] of
  1116. Ch_ROp1:
  1117. if p.oper[0]^.typ = top_reg then
  1118. if changeReg(p.oper[0]^.reg,newReg,orgReg) then
  1119. begin
  1120. { updateStates(orgReg,newReg,p,false);}
  1121. doReplaceReadReg := true;
  1122. end;
  1123. Ch_ROp2:
  1124. if p.oper[1]^.typ = top_reg then
  1125. if changeReg(p.oper[1]^.reg,newReg,orgReg) then
  1126. begin
  1127. { updateStates(orgReg,newReg,p,false);}
  1128. doReplaceReadReg := true;
  1129. end;
  1130. Ch_ROp3:
  1131. if p.oper[2]^.typ = top_reg then
  1132. if changeReg(p.oper[2]^.reg,newReg,orgReg) then
  1133. begin
  1134. { updateStates(orgReg,newReg,p,false);}
  1135. doReplaceReadReg := true;
  1136. end;
  1137. end;
  1138. end;
  1139. end;
  1140. end;
  1141. procedure updateState(supreg: tsuperregister; p: tai);
  1142. { this procedure updates the read and write states of the instructions }
  1143. { coming after p. It's called when the read/write state of p has been }
  1144. { changed and this change has to be propagated to the following }
  1145. { instructions as well }
  1146. var
  1147. newRState, newWState: byte;
  1148. prevRState, prevWState: byte;
  1149. doRState, doWState: boolean;
  1150. begin
  1151. { get the new read/write states from p }
  1152. with ptaiprop(p.optinfo)^.regs[supreg] do
  1153. begin
  1154. newRState := rState;
  1155. newWState := wState;
  1156. end;
  1157. if not GetNextInstruction(p,p) then
  1158. exit;
  1159. { get the old read/write states from the next instruction, to know }
  1160. { when we can stop updating }
  1161. with ptaiprop(p.optinfo)^.regs[supreg] do
  1162. begin
  1163. prevRState := rState;
  1164. prevWState := wState;
  1165. end;
  1166. { adjust the states if this next instruction reads/writes the register }
  1167. if regReadByInstruction(supreg,p) then
  1168. incState(newRState,1);
  1169. if regModifiedByInstruction(supreg,p) then
  1170. incState(newWState,1);
  1171. { do we still have to update the read and/or write states? }
  1172. doRState := true;
  1173. doWState := true;
  1174. repeat
  1175. { update the states }
  1176. with ptaiprop(p.optinfo)^.regs[supreg] do
  1177. begin
  1178. if doRState then
  1179. rState := newRState;
  1180. if doWState then
  1181. wState := newWState;
  1182. end;
  1183. if not getNextInstruction(p,p) then
  1184. break;
  1185. with ptaiprop(p.optinfo)^.regs[supreg] do
  1186. begin
  1187. { stop updating the read state if it changes }
  1188. doRState :=
  1189. doRState and (rState = prevRState);
  1190. { if, by accident, this changed state is the same as the one }
  1191. { we've been using, change it to a value that's definitely }
  1192. { different from the previous and next state }
  1193. if not doRState and
  1194. (rState = newRState) then
  1195. begin
  1196. incState(newRState,1);
  1197. prevRState := rState;
  1198. doRState := true;
  1199. end;
  1200. { ditto for the write state }
  1201. doWState :=
  1202. doWState and (WState = prevWState);
  1203. if not doWState and
  1204. (wState = newWState) then
  1205. begin
  1206. incState(newWState,1);
  1207. prevWState := wState;
  1208. doWState := true;
  1209. end;
  1210. end;
  1211. { stop when we don't have to update either state anymore }
  1212. until not(doRState or doWState);
  1213. end;
  1214. function storeBack(start, current: tai; orgReg, newReg: tsuperregister): boolean;
  1215. { returns true if p1 contains an instruction that stores the contents }
  1216. { of newReg back to orgReg }
  1217. begin
  1218. storeback := false;
  1219. if (current.typ = ait_instruction) and
  1220. (taicpu(current).opcode = A_MOV) and
  1221. (taicpu(current).oper[0]^.typ = top_reg) and
  1222. (getsupreg(taicpu(current).oper[0]^.reg) = newReg) and
  1223. (taicpu(current).oper[1]^.typ = top_reg) and
  1224. (getsupreg(taicpu(current).oper[1]^.reg) = orgReg) then
  1225. case taicpu(current).opsize of
  1226. S_B:
  1227. storeback := true;
  1228. S_W:
  1229. storeback := taicpu(start).opsize <> S_B;
  1230. S_L:
  1231. storeback := taicpu(start).opsize = S_L;
  1232. else
  1233. internalerror(2003121501);
  1234. end;
  1235. end;
  1236. function canreplacereg(orgsupreg, newsupreg: tsuperregister; p: tai;
  1237. orgRegCanBeModified: boolean; var resnewregmodified, resorgregread, resremovelast: boolean; var returnendp: tai): boolean;
  1238. var
  1239. endP, hp: tai;
  1240. removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: boolean;
  1241. begin
  1242. canreplacereg := false;
  1243. tmpResult := true;
  1244. sequenceEnd := false;
  1245. newRegModified := false;
  1246. orgRegRead := false;
  1247. removeLast := false;
  1248. endP := p;
  1249. while tmpResult and not sequenceEnd do
  1250. begin
  1251. tmpResult :=
  1252. getNextInstruction(endP,endP) and
  1253. (endp.typ = ait_instruction) and
  1254. not(taicpu(endp).is_jmp);
  1255. if tmpresult and not assigned(endp.optinfo) then
  1256. begin
  1257. { hp := tai_comment.Create(strpnew('next no optinfo'));
  1258. hp.next := endp;
  1259. hp.previous := endp.previous;
  1260. endp.previous := hp;
  1261. if assigned(hp.previous) then
  1262. hp.previous.next := hp;}
  1263. exit;
  1264. end;
  1265. if tmpResult and
  1266. { don't take into account instructions that will be removed }
  1267. not (ptaiprop(endp.optinfo)^.canBeRemoved) then
  1268. begin
  1269. { if the newsupreg gets stored back to the oldReg, we can change }
  1270. { "mov %oldReg,%newReg; <operations on %newReg>; mov %newReg, }
  1271. { %oldReg" to "<operations on %oldReg>" }
  1272. removeLast := storeBack(p,endP, orgsupreg, newsupreg);
  1273. sequenceEnd :=
  1274. { no support for (i)div, mul and imul with hardcoded operands }
  1275. noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1276. { if newsupreg gets loaded with a new value, we can stop }
  1277. { replacing newsupreg with oldReg here (possibly keeping }
  1278. { the original contents of oldReg so we still know them }
  1279. { afterwards) }
  1280. (RegLoadedWithNewValue(newsupreg,true,taicpu(endP)) or
  1281. { we can also stop if we reached the end of the use of }
  1282. { newReg's current contents }
  1283. (GetNextInstruction(endp,hp) and
  1284. FindRegDealloc(newsupreg,hp)));
  1285. { to be able to remove the first and last instruction of }
  1286. { movl %reg1, %reg2 }
  1287. { <operations on %reg2> (replacing reg2 with reg1 here) }
  1288. { movl %reg2, %reg1 }
  1289. { %reg2 must not be use afterwards (it can be as the }
  1290. { result of a peepholeoptimization) }
  1291. removeLast := removeLast and sequenceEnd;
  1292. newRegModified :=
  1293. newRegModified or
  1294. (not(regLoadedWithNewValue(newsupreg,true,taicpu(endP))) and
  1295. RegModifiedByInstruction(newsupreg,endP));
  1296. orgRegRead := newRegModified and RegReadByInstruction(orgsupreg,endP);
  1297. sequenceEnd := SequenceEnd and
  1298. (removeLast or
  1299. { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
  1300. { gets modified if orgsupreg is still read afterwards (since after }
  1301. { replacing, this would mean that orgsupreg first gets modified and then }
  1302. { gets read in the assumption it still contains the unmodified value) }
  1303. not(newRegModified and orgRegRead)) (* and
  1304. { since newsupreg will be replaced by orgsupreg, we can't allow that newsupreg }
  1305. { gets modified if orgRegCanBeModified = false }
  1306. { this now gets checked after the loop (JM) }
  1307. (orgRegCanBeModified or not(newRegModified)) *);
  1308. tmpResult :=
  1309. not(removeLast) and
  1310. not(newRegModified and orgRegRead) and
  1311. (* (orgRegCanBeModified or not(newRegModified)) and *)
  1312. (* already checked at the top
  1313. (endp.typ = ait_instruction) and *)
  1314. NoHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1315. RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
  1316. not RegModifiedByInstruction(orgsupreg,endP);
  1317. end;
  1318. end;
  1319. canreplacereg := sequenceEnd and
  1320. (removeLast or
  1321. (orgRegCanBeModified or not(newRegModified))) and
  1322. (not(assigned(endp)) or
  1323. not(endp.typ = ait_instruction) or
  1324. (noHardCodedRegs(taicpu(endP),orgsupreg,newsupreg) and
  1325. RegSizesOk(orgsupreg,newsupreg,taicpu(endP)) and
  1326. not(newRegModified and
  1327. (orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and
  1328. not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP))))));
  1329. if canreplacereg then
  1330. begin
  1331. resnewregmodified := newregmodified;
  1332. resorgregread := orgregread;
  1333. resremovelast := removelast;
  1334. end;
  1335. { needed for replaceregdebug code }
  1336. returnendp := endp;
  1337. end;
  1338. function ReplaceReg(asml: TAsmList; orgsupreg, newsupreg: tsuperregister; p,
  1339. seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean;
  1340. var returnEndP: tai): Boolean;
  1341. { Tries to replace orgsupreg with newsupreg in all instructions coming after p }
  1342. { until orgsupreg gets loaded with a new value. Returns true if successful, }
  1343. { false otherwise. if successful, the contents of newsupreg are set to c, }
  1344. { which should hold the contents of newsupreg before the current sequence }
  1345. { started }
  1346. { if the function returns true, returnEndP holds the last instruction }
  1347. { where newsupreg was replaced by orgsupreg }
  1348. var
  1349. endP, hp: tai;
  1350. removeLast, sequenceEnd, newRegModified, orgRegRead,
  1351. stateChanged, readStateChanged: Boolean;
  1352. {$ifdef replaceregdebug}
  1353. l: longint;
  1354. {$endif replaceregdebug}
  1355. begin
  1356. replacereg := false;
  1357. if canreplacereg(orgsupreg,newsupreg,p,orgregcanbemodified,newregmodified, orgregread, removelast,endp) then
  1358. begin
  1359. {$ifdef replaceregdebug}
  1360. l := random(1000);
  1361. hp := tai_comment.Create(strpnew(
  1362. 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1363. ' from here... '+tostr(l)));
  1364. insertllitem(asml,p.previous,p,hp);
  1365. hp := tai_comment.Create(strpnew(
  1366. 'replaced '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1367. ' till here ' + tostr(l)));
  1368. insertllitem(asml,endp,endp.next,hp);
  1369. {$endif replaceregdebug}
  1370. replaceReg := true;
  1371. returnEndP := endP;
  1372. if not getNextInstruction(p,hp) then
  1373. exit;
  1374. stateChanged := false;
  1375. while hp <> endP do
  1376. begin
  1377. if {not(ptaiprop(hp.optinfo)^.canBeRemoved) and }
  1378. (hp.typ = ait_instruction) then
  1379. stateChanged :=
  1380. doReplaceReg(taicpu(hp),newsupreg,orgsupreg) or stateChanged;
  1381. if stateChanged then
  1382. updateStates(orgsupreg,newsupreg,hp,true);
  1383. getNextInstruction(hp,hp)
  1384. end;
  1385. if assigned(endp) and (endp.typ = ait_instruction) then
  1386. readStateChanged :=
  1387. doReplaceReadReg(taicpu(endP),newsupreg,orgsupreg);
  1388. if stateChanged or readStateChanged then
  1389. updateStates(orgsupreg,newsupreg,endP,stateChanged);
  1390. if stateChanged or readStateChanged then
  1391. updateState(orgsupreg,endP);
  1392. { We replaced newreg with oldreg between p and endp, so restore the contents }
  1393. { of newreg there with its contents from before the sequence. }
  1394. if removeLast or
  1395. RegLoadedWithNewValue(newsupreg,true,endP) then
  1396. GetLastInstruction(endP,hp)
  1397. else hp := endP;
  1398. RestoreRegContentsTo(asml,newsupreg,c,seqstart,hp);
  1399. { Ot is possible that the new register was modified (e.g. an add/sub), so if }
  1400. { it was replaced by oldreg in that instruction, oldreg's contents have been }
  1401. { changed. To take this into account, we simply set the contents of orgsupreg }
  1402. { to "unknown" after this sequence }
  1403. if newRegModified then
  1404. ClearRegContentsFrom(asml,orgsupreg,p,hp);
  1405. if removeLast then
  1406. ptaiprop(endp.optinfo)^.canBeRemoved := true;
  1407. allocRegBetween(asml,newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE),p,endP,ptaiprop(p.optinfo)^.usedregs);
  1408. end
  1409. {$ifdef replaceregdebug}
  1410. else
  1411. begin
  1412. l := random(1000);
  1413. hp := tai_comment.Create(strpnew(
  1414. 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1415. ' from here... '+ tostr(l)));
  1416. insertllitem(asml,p.previous,p,hp);
  1417. hp := tai_comment.Create(strpnew(
  1418. 'replacing '+std_regname(newreg(R_INTREGISTER,newsupreg,R_SUBWHOLE))+' with '+std_regname(newreg(R_INTREGISTER,orgsupreg,R_SUBWHOLE))+
  1419. ' failed here ' + tostr(l)));
  1420. insertllitem(asml,endp,endp.next,hp);
  1421. end;
  1422. {$endif replaceregdebug}
  1423. end;
  1424. function FindRegWithConst(p: tai; size: topsize; l: aint; var Res: TRegister): Boolean;
  1425. {Finds a register which contains the constant l}
  1426. var
  1427. Counter: tsuperregister;
  1428. {$ifdef testing}
  1429. hp: tai;
  1430. {$endif testing}
  1431. begin
  1432. Result:=false;
  1433. Counter := RS_EAX;
  1434. repeat
  1435. {$ifdef testing}
  1436. if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) then
  1437. begin
  1438. hp := tai_comment.Create(strpnew(
  1439. 'checking const load of '+tostr(l)+' here...'));
  1440. hp.next := ptaiprop(p.optinfo)^.Regs[Counter].StartMod;
  1441. hp.previous := ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous;
  1442. ptaiprop(p.optinfo)^.Regs[Counter].StartMod^.previous := hp;
  1443. if assigned(hp.previous) then
  1444. hp.previous.next := hp;
  1445. end;
  1446. {$endif testing}
  1447. if (ptaiprop(p.optinfo)^.regs[counter].typ in [con_const,con_noRemoveConst]) and
  1448. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).opsize = size) and
  1449. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.typ = top_const) and
  1450. (taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[0]^.val = l) then
  1451. begin
  1452. res:=taicpu(ptaiprop(p.optinfo)^.Regs[Counter].StartMod).oper[1]^.reg;
  1453. result:=true;
  1454. exit;
  1455. end;
  1456. inc(counter);
  1457. until (Counter > RS_EDI);
  1458. end;
  1459. procedure removePrevNotUsedLoad(asml: TAsmList; p: tai; supreg: tsuperregister; check: boolean);
  1460. { if check = true, it means the procedure has to check whether it isn't }
  1461. { possible that the contents are still used after p (used when removing }
  1462. { instructions because of a "call"), otherwise this is not necessary }
  1463. { (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
  1464. { value of %eax isn't used anymore later on) }
  1465. var
  1466. hp1, next, beforestartmod: tai;
  1467. begin
  1468. if getLastInstruction(p,hp1) then
  1469. with ptaiprop(hp1.optinfo)^.regs[supreg] do
  1470. if (typ in [con_ref,con_invalid,con_const]) and
  1471. (nrofMods = 1) and
  1472. (rState = ptaiprop(startmod.optinfo)^.regs[supreg].rState) and
  1473. (not(check) or
  1474. (not(regInInstruction(supreg,p)) and
  1475. (not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or
  1476. findRegDealloc(supreg,p)))) then
  1477. begin
  1478. ptaiprop(startMod.optinfo)^.canBeRemoved := true;
  1479. getnextinstruction(p,next);
  1480. { give the register that was modified by this instruction again }
  1481. { the contents it had before this instruction }
  1482. if getlastinstruction(startmod,beforestartmod) then
  1483. RestoreRegContentsTo(asml,supreg,ptaiprop(beforestartmod.optinfo)^.regs[supreg],
  1484. startmod,hp1)
  1485. else
  1486. ClearRegContentsFrom(asml,supreg,startmod,hp1);
  1487. end;
  1488. end;
  1489. {$ifdef notused}
  1490. function is_mov_for_div(p: taicpu): boolean;
  1491. begin
  1492. is_mov_for_div :=
  1493. (p.opcode = A_MOV) and
  1494. (p.oper[0]^.typ = top_const) and
  1495. (p.oper[1]^.typ = top_reg) and
  1496. (p.oper[1]^.reg = RS_EDX) and
  1497. getNextInstruction(p,p) and
  1498. (p.typ = ait_instruction) and
  1499. ((p.opcode = A_DIV) or
  1500. (p.opcode = A_IDIV));
  1501. end;
  1502. {$endif notused}
  1503. function memtoreg(t: taicpu; const ref: treference; var startp: tai): tregister;
  1504. var
  1505. hp: tai;
  1506. p: ptaiprop;
  1507. regcounter: tsuperregister;
  1508. optimizable: boolean;
  1509. begin
  1510. if not getlastinstruction(t,hp) or
  1511. not issimplememloc(ref) then
  1512. begin
  1513. memtoreg := NR_NO;
  1514. exit;
  1515. end;
  1516. p := ptaiprop(hp.optinfo);
  1517. optimizable := false;
  1518. for regcounter := RS_EAX to RS_EDI do
  1519. begin
  1520. if (assigned(p^.regs[regcounter].memwrite) and
  1521. refsequal(ref,p^.regs[regcounter].memwrite.oper[1]^.ref^)) then
  1522. begin
  1523. optimizable := true;
  1524. hp := p^.regs[regcounter].memwrite;
  1525. end
  1526. else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
  1527. (p^.regs[regcounter].nrofmods = 1) and
  1528. ((taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
  1529. (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
  1530. (taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
  1531. (taicpu(p^.regs[regcounter].startmod).oper[0]^.typ = top_ref) and
  1532. refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0]^.ref^)) then
  1533. begin
  1534. optimizable := true;
  1535. hp := p^.regs[regcounter].startmod;
  1536. end;
  1537. if optimizable then
  1538. if ((t.opsize <> S_B) or
  1539. not(regcounter in [RS_ESI,RS_EDI])) and
  1540. sizescompatible(taicpu(hp).opsize,t.opsize) then
  1541. begin
  1542. case t.opsize of
  1543. S_B:
  1544. begin
  1545. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBL)
  1546. end;
  1547. S_W,S_BW:
  1548. begin
  1549. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBW);
  1550. if (t.opsize = S_BW) then
  1551. begin
  1552. t.opcode := A_MOV;
  1553. t.opsize := S_W;
  1554. end;
  1555. end;
  1556. S_L,S_BL,S_WL:
  1557. begin
  1558. memtoreg := newreg(R_INTREGISTER,regcounter,R_SUBWHOLE);
  1559. if (t.opsize <> S_L) then
  1560. begin
  1561. t.opcode := A_MOV;
  1562. t.opsize := S_L;
  1563. end;
  1564. end;
  1565. end;
  1566. startp := hp;
  1567. exit;
  1568. end;
  1569. end;
  1570. memtoreg := NR_NO;
  1571. end;
  1572. procedure removeLocalStores(const t1: tai);
  1573. {var
  1574. p: tai;
  1575. regcount: tregister; }
  1576. begin
  1577. {
  1578. for regcount := LoGPReg to HiGPReg do
  1579. if assigned(pTaiProp(t1.optinfo)^.regs[regcount].memwrite) and
  1580. (taicpu(pTaiProp(t1.optinfo)^.regs[regcount].memwrite).oper[1]^.ref^.base
  1581. = current_procinfo.framepointer) then
  1582. begin
  1583. pTaiProp(pTaiProp(t1.optinfo)^.regs[regcount].memwrite.optinfo)^.canberemoved := true;
  1584. clearmemwrites(pTaiProp(t1.optinfo)^.regs[regcount].memwrite,regcount);
  1585. end;
  1586. }
  1587. end;
  1588. procedure loadcseregs(asml: TAsmList; const reginfo: toptreginfo; curseqend, prevseqstart, curseqstart, curprev: tai; cnt: longint);
  1589. var
  1590. regsloaded: tregset;
  1591. regloads, reguses: array[RS_EAX..RS_EDI] of tai;
  1592. regcounter, substreg: tsuperregister;
  1593. hp, hp2: tai;
  1594. insertpos, prevseq_next: tai;
  1595. i: longint;
  1596. opc: tasmop;
  1597. begin
  1598. regsloaded := [];
  1599. fillchar(regloads,sizeof(regloads),0);
  1600. fillchar(reguses,sizeof(reguses),0);
  1601. getnextinstruction(prevseqstart,prevseq_next);
  1602. for regcounter := RS_EAX To RS_EDI do
  1603. if (reginfo.new2oldreg[regcounter] <> RS_INVALID) Then
  1604. begin
  1605. include(regsloaded,regcounter);
  1606. if assigned(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod) then
  1607. AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
  1608. ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod,curseqstart,
  1609. ptaiprop(ptaiprop(prevseqstart.optinfo)^.Regs[reginfo.new2oldreg[regcounter]].StartMod.optinfo)^.usedregs)
  1610. else
  1611. AllocRegBetween(asml,newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE),
  1612. prevseqstart,curseqstart,ptaiprop(prevseqstart.optinfo)^.usedregs);
  1613. if curprev <> prevseqstart then
  1614. begin
  1615. if assigned(reginfo.lastReload[regCounter]) then
  1616. getLastInstruction(reginfo.lastReload[regCounter],hp)
  1617. else if assigned(reginfo.lastReload[reginfo.new2oldreg[regCounter]]) then
  1618. getLastInstruction(reginfo.lastReload[reginfo.new2OldReg[regCounter]],hp)
  1619. else
  1620. hp := curprev;
  1621. clearRegContentsFrom(asml,regCounter,prevSeq_next,hp);
  1622. getnextInstruction(hp,hp);
  1623. allocRegBetween(asml,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prevseqstart,hp,
  1624. ptaiprop(prevseqstart.optinfo)^.usedregs);
  1625. end;
  1626. if not(regcounter in reginfo.RegsLoadedforRef) and
  1627. {old reg new reg}
  1628. (reginfo.new2oldreg[regcounter] <> regcounter) then
  1629. begin
  1630. getLastInstruction(curseqend,hp);
  1631. opc := A_MOV;
  1632. insertpos := prevseq_next;
  1633. if assigned(reguses[regcounter]) then
  1634. if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
  1635. opc := A_XCHG
  1636. else
  1637. insertpos := tai(reguses[regcounter].next)
  1638. else
  1639. if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
  1640. insertpos := regloads[reginfo.new2oldreg[regcounter]];
  1641. hp := Tai_Marker.Create(mark_NoPropInfoStart);
  1642. InsertLLItem(asml, insertpos.previous,insertpos, hp);
  1643. hp2 := taicpu.Op_Reg_Reg(opc, S_L,
  1644. {old reg new reg}
  1645. newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
  1646. if (opc = A_XCHG) and
  1647. (taicpu(regloads[reginfo.new2oldreg[regcounter]]).opcode <> A_XCHG) then
  1648. begin
  1649. asml.remove(regloads[reginfo.new2oldreg[regcounter]]);
  1650. regloads[reginfo.new2oldreg[regcounter]].free;
  1651. regloads[reginfo.new2oldreg[regcounter]] := hp2;
  1652. reguses[regcounter] := hp2;
  1653. end;
  1654. regloads[regcounter] := hp2;
  1655. reguses[reginfo.new2oldreg[regcounter]] := hp2;
  1656. new(ptaiprop(hp2.optinfo));
  1657. ptaiprop(hp2.optinfo)^ := ptaiprop(insertpos.optinfo)^;
  1658. ptaiprop(hp2.optinfo)^.canBeRemoved := false;
  1659. InsertLLItem(asml, insertpos.previous, insertpos, hp2);
  1660. hp := Tai_Marker.Create(mark_NoPropInfoEnd);
  1661. InsertLLItem(asml, insertpos.previous, insertpos, hp);
  1662. { adjusts states in previous instruction so that it will }
  1663. { definitely be different from the previous or next state }
  1664. incstate(ptaiprop(hp2.optinfo)^.
  1665. regs[reginfo.new2oldreg[regcounter]].rstate,20);
  1666. incstate(ptaiprop(hp2.optinfo)^.
  1667. regs[regCounter].wstate,20);
  1668. updateState(reginfo.new2oldreg[regcounter],hp2);
  1669. updateState(regcounter,hp2);
  1670. end
  1671. else
  1672. { imagine the following code: }
  1673. { normal wrong optimized }
  1674. { movl 8(%ebp), %eax movl 8(%ebp), %eax }
  1675. { movl (%eax), %eax movl (%eax), %eax }
  1676. { cmpl 8(%ebp), %eax cmpl 8(%ebp), %eax }
  1677. { jne l1 jne l1 }
  1678. { movl 8(%ebp), %eax }
  1679. { movl (%eax), %edi movl %eax, %edi }
  1680. { movl %edi, -4(%ebp) movl %edi, -4(%ebp) }
  1681. { movl 8(%ebp), %eax }
  1682. { pushl 70(%eax) pushl 70(%eax) }
  1683. { }
  1684. { The error is that at the moment that the last instruction is executed, }
  1685. { %eax doesn't contain 8(%ebp) anymore. Solution: the contents of }
  1686. { registers that are completely removed from a sequence (= registers in }
  1687. { RegLoadedforRef), have to be changed to their contents from before the }
  1688. { sequence. }
  1689. { if regcounter in reginfo.RegsLoadedforRef then }
  1690. begin
  1691. hp := curseqstart;
  1692. { cnt still holds the number of instructions }
  1693. { of the sequence, so go to the end of it }
  1694. for i := 1 to pred(cnt) do
  1695. getNextInstruction(hp,hp);
  1696. { curprev = instruction prior to start of sequence }
  1697. restoreRegContentsTo(asml,regCounter,
  1698. ptaiprop(curprev.optinfo)^.Regs[regcounter],
  1699. curseqstart,hp);
  1700. end;
  1701. end;
  1702. end;
  1703. procedure replaceoperandwithreg(asml: TAsmList; p: tai; opnr: byte; reg: tregister);
  1704. var
  1705. hp: tai;
  1706. begin
  1707. { new instruction -> it's info block is not in the big one allocated at the start }
  1708. hp := Tai_Marker.Create(mark_NoPropInfoStart);
  1709. InsertLLItem(asml, p.previous,p, hp);
  1710. { duplicate the original instruction and replace it's designated operant with the register }
  1711. hp := tai(p.getcopy);
  1712. taicpu(hp).loadreg(opnr,reg);
  1713. { add optimizer state info }
  1714. new(ptaiprop(hp.optinfo));
  1715. ptaiprop(hp.optinfo)^ := ptaiprop(p.optinfo)^;
  1716. { new instruction can not be removed }
  1717. ptaiprop(hp.optinfo)^.canBeRemoved := false;
  1718. { but the old one can }
  1719. ptaiprop(p.optinfo)^.canBeRemoved := true;
  1720. { insert end marker }
  1721. InsertLLItem(asml, p.previous, p, hp);
  1722. hp := Tai_Marker.Create(mark_NoPropInfoEnd);
  1723. InsertLLItem(asml, p.previous, p, hp);
  1724. end;
  1725. procedure doCSE(asml: TAsmList; First, Last: tai; findPrevSeqs, doSubOpts: boolean);
  1726. {marks the instructions that can be removed by RemoveInstructs. They're not
  1727. removed immediately because sometimes an instruction needs to be checked in
  1728. two different sequences}
  1729. var cnt, cnt2, {cnt3,} orgNrofMods: longint;
  1730. p, hp1, hp2, prevSeq: tai;
  1731. hp3, hp4: tai;
  1732. hp5 : tai;
  1733. reginfo: toptreginfo;
  1734. memreg: tregister;
  1735. regcounter: tsuperregister;
  1736. begin
  1737. p := First;
  1738. SkipHead(p);
  1739. while (p <> Last) do
  1740. begin
  1741. case p.typ of
  1742. ait_align:
  1743. if not(tai_align(p).use_op) then
  1744. SetAlignReg(p);
  1745. ait_instruction:
  1746. begin
  1747. case taicpu(p).opcode of
  1748. {
  1749. Does not work anymore with register calling because the registers are
  1750. released before the call
  1751. A_CALL:
  1752. for regCounter := RS_EAX to RS_EBX do
  1753. removePrevNotUsedLoad(asml,p,regCounter,true);
  1754. }
  1755. A_CLD: if GetLastInstruction(p, hp1) and
  1756. (ptaiprop(hp1.optinfo)^.DirFlag = F_NotSet) then
  1757. ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
  1758. A_LEA, A_MOV, A_MOVZX, A_MOVSX:
  1759. begin
  1760. hp2 := p;
  1761. case taicpu(p).oper[0]^.typ of
  1762. top_ref, top_reg:
  1763. if (taicpu(p).oper[1]^.typ = top_reg) then
  1764. begin
  1765. With ptaiprop(p.optinfo)^.Regs[getsupreg(taicpu(p).oper[1]^.reg)] do
  1766. begin
  1767. if (startmod = p) then
  1768. orgNrofMods := nrofMods
  1769. else
  1770. orgNrofMods := 0;
  1771. if (p = StartMod) and
  1772. GetLastInstruction (p, hp1) and
  1773. not(hp1.typ in [ait_marker,ait_label]) then
  1774. {so we don't try to check a sequence when p is the first instruction of the block}
  1775. begin
  1776. {$ifdef csdebug}
  1777. hp5 := tai_comment.Create(strpnew(
  1778. 'cse checking '+std_regname(taicpu(p).oper[1]^.reg)));
  1779. insertLLItem(asml,p,p.next,hp5);
  1780. {$endif csdebug}
  1781. if CheckSequence(p,prevSeq,getsupreg(taicpu(p).oper[1]^.reg), Cnt, reginfo, findPrevSeqs) and
  1782. (Cnt > 0) then
  1783. begin
  1784. (*
  1785. hp1 := nil;
  1786. { although it's perfectly ok to remove an instruction which doesn't contain }
  1787. { the register that we've just checked (CheckSequence takes care of that), }
  1788. { the sequence containing this other register should also be completely }
  1789. { checked and removed, otherwise we may get situations like this: }
  1790. { }
  1791. { movl 12(%ebp), %edx movl 12(%ebp), %edx }
  1792. { movl 16(%ebp), %eax movl 16(%ebp), %eax }
  1793. { movl 8(%edx), %edx movl 8(%edx), %edx }
  1794. { movl (%eax), eax movl (%eax), eax }
  1795. { cmpl %eax, %edx cmpl %eax, %edx }
  1796. { jnz l123 getting converted to jnz l123 }
  1797. { movl 12(%ebp), %edx movl 4(%eax), eax }
  1798. { movl 16(%ebp), %eax }
  1799. { movl 8(%edx), %edx }
  1800. { movl 4(%eax), eax }
  1801. *)
  1802. { not anymore: if the start of a new sequence is found while checking (e.g. }
  1803. { above that of eax while checking edx, this new sequence is automatically }
  1804. { also checked }
  1805. Cnt2 := 1;
  1806. while Cnt2 <= Cnt do
  1807. begin
  1808. {$ifndef noremove}
  1809. ptaiprop(p.optinfo)^.CanBeRemoved := True
  1810. {$endif noremove}
  1811. ; inc(Cnt2);
  1812. GetNextInstruction(p, p);
  1813. end;
  1814. {hp4 is used to get the contents of the registers before the sequence}
  1815. GetLastInstruction(hp2, hp4);
  1816. {$IfDef CSDebug}
  1817. for regcounter := RS_EAX To RS_EDI do
  1818. if (regcounter in reginfo.RegsLoadedforRef) then
  1819. begin
  1820. hp5 := tai_comment.Create(strpnew('New: '+std_regname(newreg(R_INTREGISTER,regcounter,R_SUBNONE))+', Old: '+
  1821. std_regname(newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBNONE))));
  1822. InsertLLItem(asml, tai(hp2.previous), hp2, hp5);
  1823. end;
  1824. {$EndIf CSDebug}
  1825. { if some registers were different in the old and the new sequence, move }
  1826. { the contents of those old registers to the new ones }
  1827. loadcseregs(asml,reginfo,p,prevseq,hp2,hp4,cnt);
  1828. continue;
  1829. end
  1830. end;
  1831. end;
  1832. { try to replace the new reg with the old reg }
  1833. if not(ptaiprop(p.optinfo)^.canBeRemoved) then
  1834. if (taicpu(p).oper[0]^.typ = top_reg) and
  1835. (taicpu(p).oper[1]^.typ = top_reg) and
  1836. { only remove if we're not storing something in a regvar }
  1837. (getsupreg(taicpu(p).oper[1]^.reg) in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_ESI,RS_EDI]) and
  1838. { (taicpu(p).oper[1]^.reg in (rg.usableregsint+[RS_EDI])) and}
  1839. (taicpu(p).opcode = A_MOV) and
  1840. getLastInstruction(p,hp4) and
  1841. { we only have to start replacing from the instruction after the mov, }
  1842. { but replacereg only starts with getnextinstruction(p,p) }
  1843. replaceReg(asml,getsupreg(taicpu(p).oper[0]^.reg),
  1844. getsupreg(taicpu(p).oper[1]^.reg),p,p,
  1845. ptaiprop(hp4.optinfo)^.regs[getsupreg(taicpu(p).oper[1]^.reg)],false,hp1) then
  1846. begin
  1847. ptaiprop(p.optinfo)^.canBeRemoved := true;
  1848. { this is just a regular move that was here, so the source register should be }
  1849. { allocated already at this point -> only allocate from here onwards }
  1850. if not(getsupreg(taicpu(p).oper[0]^.reg) in pTaiProp(p.optinfo)^.usedregs) then
  1851. internalerror(2004101011);
  1852. allocRegBetween(asml,taicpu(p).oper[0]^.reg,
  1853. p,hp1,pTaiProp(p.optinfo)^.usedregs)
  1854. end
  1855. else
  1856. begin
  1857. if (taicpu(p).oper[1]^.typ = top_reg) and
  1858. not regInOp(getsupreg(taicpu(p).oper[1]^.reg),taicpu(p).oper[0]^) then
  1859. removePrevNotUsedLoad(asml,p,getsupreg(taicpu(p).oper[1]^.reg),false);
  1860. if doSubOpts and
  1861. (taicpu(p).opcode <> A_LEA) and
  1862. (taicpu(p).oper[0]^.typ = top_ref) then
  1863. begin
  1864. memreg :=
  1865. memtoreg(taicpu(p),
  1866. taicpu(p).oper[0]^.ref^,hp5);
  1867. if memreg <> NR_NO then
  1868. if (taicpu(p).opcode = A_MOV) and
  1869. (taicpu(p).oper[1]^.typ = top_reg) and
  1870. (taicpu(p).oper[1]^.reg = memreg) then
  1871. begin
  1872. pTaiProp(p.optinfo)^.canberemoved := true;
  1873. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1874. end
  1875. else
  1876. begin
  1877. replaceoperandwithreg(asml,p,0,memreg);
  1878. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1879. regcounter := getsupreg(memreg);
  1880. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1881. updatestate(regcounter,p);
  1882. end;
  1883. end;
  1884. end;
  1885. { at first, only try optimizations of large blocks, because doing }
  1886. { doing smaller ones may prevent bigger ones from completing in }
  1887. { in the next pass }
  1888. if not doSubOpts and (orgNrofMods <> 0) then
  1889. begin
  1890. p := hp2;
  1891. for cnt := 1 to pred(orgNrofMods) do
  1892. getNextInstruction(p,p);
  1893. end;
  1894. end;
  1895. top_Const:
  1896. begin
  1897. case taicpu(p).oper[1]^.typ of
  1898. Top_Reg:
  1899. begin
  1900. regCounter := getsupreg(taicpu(p).oper[1]^.reg);
  1901. if GetLastInstruction(p, hp1) then
  1902. With ptaiprop(hp1.optinfo)^.Regs[regCounter] do
  1903. if (typ in [con_const,con_noRemoveConst]) and
  1904. (taicpu(startMod).opsize >= taicpu(p).opsize) and
  1905. opsequal(taicpu(StartMod).oper[0]^,taicpu(p).oper[0]^) then
  1906. begin
  1907. ptaiprop(p.optinfo)^.CanBeRemoved := True;
  1908. allocRegBetween(asml,taicpu(p).oper[1]^.reg,startmod,p,
  1909. ptaiprop(startmod.optinfo)^.usedregs);
  1910. end
  1911. else
  1912. removePrevNotUsedLoad(asml,p,getsupreg(taicpu(p).oper[1]^.reg),false);
  1913. end;
  1914. Top_Ref:
  1915. if (taicpu(p).oper[0]^.typ = top_const) and
  1916. getLastInstruction(p,hp1) and
  1917. findRegWithConst(hp1,taicpu(p).opsize,taicpu(p).oper[0]^.val,memreg) then
  1918. begin
  1919. taicpu(p).loadreg(0,memreg);
  1920. { mark the used register as read }
  1921. incstate(ptaiprop(p.optinfo)^.
  1922. regs[getsupreg(memreg)].rstate,20);
  1923. updateState(getsupreg(memreg),p);
  1924. allocRegBetween(asml,memreg,
  1925. ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod,p,
  1926. ptaiprop(ptaiprop(hp1.optinfo)^.regs[getsupreg(memreg)].startMod.optinfo)^.usedregs);
  1927. end;
  1928. end;
  1929. end;
  1930. end;
  1931. end;
  1932. A_LEAVE:
  1933. begin
  1934. if getlastinstruction(p,hp1) then
  1935. removeLocalStores(hp1);
  1936. end;
  1937. A_STD: if GetLastInstruction(p, hp1) and
  1938. (ptaiprop(hp1.optinfo)^.DirFlag = F_Set) then
  1939. ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
  1940. else
  1941. begin
  1942. for cnt := 1 to maxinschanges do
  1943. begin
  1944. case InsProp[taicpu(p).opcode].Ch[cnt] of
  1945. Ch_ROp1:
  1946. if (taicpu(p).oper[0]^.typ = top_ref) and
  1947. ((taicpu(p).opcode < A_F2XM1) or
  1948. ((taicpu(p).opcode > A_IN) and
  1949. (taicpu(p).opcode < A_OUT)) or
  1950. (taicpu(p).opcode = A_PUSH) or
  1951. ((taicpu(p).opcode >= A_RCL) and
  1952. (taicpu(p).opcode <= A_XOR))) then
  1953. begin
  1954. memreg :=
  1955. memtoreg(taicpu(p),
  1956. taicpu(p).oper[0]^.ref^,hp5);
  1957. if memreg <> NR_NO then
  1958. begin
  1959. replaceoperandwithreg(asml,p,0,memreg);
  1960. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  1961. regcounter := getsupreg(memreg);
  1962. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  1963. updatestate(regcounter,p);
  1964. end;
  1965. end;
  1966. Ch_MOp1:
  1967. if not(cs_opt_size in aktoptimizerswitches) and
  1968. (taicpu(p).oper[0]^.typ = top_ref) then
  1969. begin
  1970. memreg :=
  1971. memtoreg(taicpu(p),
  1972. taicpu(p).oper[0]^.ref^,hp5);
  1973. if (memreg <> NR_NO) and
  1974. (not getNextInstruction(p,hp1) or
  1975. (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
  1976. FindRegDealloc(getsupreg(memreg),hp1))) then
  1977. begin
  1978. hp1 := Tai_Marker.Create(mark_NoPropInfoEnd);
  1979. insertllitem(asml,p,p.next,hp1);
  1980. hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
  1981. memreg,taicpu(p).oper[0]^.ref^);
  1982. new(ptaiprop(hp1.optinfo));
  1983. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  1984. insertllitem(asml,p,p.next,hp1);
  1985. regcounter := getsupreg(memreg);
  1986. incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
  1987. updatestate(regcounter,hp1);
  1988. hp1 := Tai_Marker.Create(mark_NoPropInfoStart);
  1989. insertllitem(asml,p,p.next,hp1);
  1990. replaceoperandwithreg(asml,p,0,memreg);
  1991. allocregbetween(asml,memreg,hp5,
  1992. tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
  1993. ClearRegContentsFrom(asml,regcounter,hp5,p);
  1994. end;
  1995. end;
  1996. Ch_ROp2:
  1997. if ((taicpu(p).opcode = A_CMP) or
  1998. (taicpu(p).opcode = A_TEST)) and
  1999. (taicpu(p).oper[1]^.typ = top_ref) then
  2000. begin
  2001. memreg :=
  2002. memtoreg(taicpu(p),
  2003. taicpu(p).oper[1]^.ref^,hp5);
  2004. if memreg <> NR_NO then
  2005. begin
  2006. replaceoperandwithreg(asml,p,1,memreg);
  2007. allocregbetween(asml,memreg,hp5,p,ptaiprop(hp5.optinfo)^.usedregs);
  2008. regcounter := getsupreg(memreg);
  2009. incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
  2010. updatestate(regcounter,p);
  2011. end;
  2012. end;
  2013. Ch_MOp2:
  2014. if not(cs_opt_size in aktoptimizerswitches) and
  2015. (taicpu(p).oper[1]^.typ = top_ref) and
  2016. ((taicpu(p).opcode < A_BT) or
  2017. ((taicpu(p).opcode > A_IN) and
  2018. (taicpu(p).opcode < A_OUT)) or
  2019. (taicpu(p).opcode = A_PUSH) or
  2020. ((taicpu(p).opcode >= A_RCL) and
  2021. (taicpu(p).opcode <= A_XOR))) then
  2022. begin
  2023. memreg :=
  2024. memtoreg(taicpu(p),
  2025. taicpu(p).oper[1]^.ref^,hp5);
  2026. if (memreg <> NR_NO) and
  2027. (not getNextInstruction(p,hp1) or
  2028. (RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
  2029. FindRegDealloc(getsupreg(memreg),hp1))) then
  2030. begin
  2031. hp1 := Tai_Marker.Create(mark_NoPropInfoEnd);
  2032. insertllitem(asml,p,p.next,hp1);
  2033. hp1 := taicpu.op_reg_ref(A_MOV,reg2opsize(memreg),
  2034. memreg,taicpu(p).oper[1]^.ref^);
  2035. new(ptaiprop(hp1.optinfo));
  2036. pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
  2037. insertllitem(asml,p,p.next,hp1);
  2038. regcounter := getsupreg(memreg);
  2039. incstate(pTaiProp(hp1.optinfo)^.regs[regcounter].rstate,1);
  2040. updatestate(regcounter,hp1);
  2041. hp1 := Tai_Marker.Create(mark_NoPropInfoStart);
  2042. insertllitem(asml,p,p.next,hp1);
  2043. replaceoperandwithreg(asml,p,1,memreg);
  2044. allocregbetween(asml,memreg,hp5,
  2045. tai(p.next.next),ptaiprop(hp5.optinfo)^.usedregs);
  2046. ClearRegContentsFrom(asml,regcounter,hp5,p);
  2047. end;
  2048. end;
  2049. end;
  2050. end;
  2051. end;
  2052. end
  2053. end;
  2054. end;
  2055. GetNextInstruction(p, p);
  2056. end;
  2057. end;
  2058. function removeInstructs(asml: TAsmList; first, last: tai): boolean;
  2059. { Removes the marked instructions and disposes the PTaiProps of the other }
  2060. { instructions }
  2061. var
  2062. p, hp1: tai;
  2063. nopropinfolevel: longint;
  2064. begin
  2065. removeInstructs := false;
  2066. p := First;
  2067. nopropinfolevel := 0;
  2068. while (p <> Last) do
  2069. begin
  2070. if (p.typ = ait_marker) and
  2071. (Tai_marker(p).kind = mark_NoPropInfoStart) then
  2072. begin
  2073. hp1 := tai(p.next);
  2074. asml.remove(p);
  2075. p.free;
  2076. nopropinfolevel := 1;
  2077. while (nopropinfolevel <> 0) do
  2078. begin
  2079. p := tai(hp1.next);
  2080. {$ifndef noinstremove}
  2081. { allocregbetween can insert new ait_regalloc objects }
  2082. { without optinfo }
  2083. if (hp1.typ = ait_marker) then
  2084. begin
  2085. case Tai_marker(hp1).kind of
  2086. { they can be nested! }
  2087. mark_NoPropInfoStart: inc(nopropinfolevel);
  2088. mark_NoPropInfoEnd: dec(nopropinfolevel);
  2089. else
  2090. begin
  2091. hp1 := p;
  2092. continue;
  2093. end;
  2094. end;
  2095. asml.remove(hp1);
  2096. hp1.free;
  2097. end
  2098. else if assigned(hp1.optinfo) then
  2099. if ptaiprop(hp1.optinfo)^.canBeRemoved then
  2100. begin
  2101. dispose(ptaiprop(hp1.optinfo));
  2102. hp1.optinfo := nil;
  2103. asml.remove(hp1);
  2104. hp1.free;
  2105. end
  2106. else
  2107. {$endif noinstremove}
  2108. begin
  2109. dispose(ptaiprop(hp1.optinfo));
  2110. hp1.optinfo := nil;
  2111. end;
  2112. hp1 := p;
  2113. end;
  2114. end
  2115. else
  2116. {$ifndef noinstremove}
  2117. if assigned(p.optinfo) and
  2118. ptaiprop(p.optinfo)^.canBeRemoved then
  2119. begin
  2120. hp1 := tai(p.next);
  2121. asml.Remove(p);
  2122. p.free;
  2123. p := hp1;
  2124. removeInstructs := true;
  2125. end
  2126. else
  2127. {$endif noinstremove}
  2128. begin
  2129. p.optinfo := nil;
  2130. p := tai(p.next);;
  2131. end;
  2132. end;
  2133. end;
  2134. function CSE(asml: TAsmList; First, Last: tai; pass: longint): boolean;
  2135. begin
  2136. doCSE(asml, First, Last, not(cs_opt_asmcse in aktoptimizerswitches) or (pass >= 2),
  2137. not(cs_opt_asmcse in aktoptimizerswitches) or (pass >= 1));
  2138. { register renaming }
  2139. if not(cs_opt_asmcse in aktoptimizerswitches) or (pass > 0) then
  2140. doRenaming(asml, first, last);
  2141. cse := removeInstructs(asml, first, last);
  2142. end;
  2143. end.