2
0

csopt386.pas 90 KB

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