csopt386.pas 88 KB

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