csopt386.pas 88 KB

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