csopt386.pas 89 KB

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