csopt386.pas 90 KB

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