csopt386.pas 87 KB

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