csopt386.pas 88 KB

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