csopt386.pas 88 KB

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