csopt386.pas 90 KB

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