rgobj.pas 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the base class for the register allocator
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$i fpcdefs.inc}
  19. { Allow duplicate allocations, can be used to get the .s file written }
  20. { $define ALLOWDUPREG}
  21. {#******************************************************************************
  22. @abstract(Abstract register allocator unit)
  23. Register allocator introduction.
  24. Free Pascal uses a Chaitin style register allocator. We use a variant similair
  25. to the one described in the book "Modern compiler implementation in C" by
  26. Andrew W. Appel., published by Cambridge University Press.
  27. The register allocator that is described by Appel uses a much improved way
  28. of register coalescing, called "iterated register coalescing". Instead
  29. of doing coalescing as a prepass to the register allocation, the coalescing
  30. is done inside the register allocator. This has the advantage that the
  31. register allocator can coalesce very aggresively without introducing spills.
  32. Reading this book is recommended for a complete understanding. Here is a small
  33. introduction.
  34. The code generator thinks it has an infinite amount of registers. Our processor
  35. has a limited amount of registers. Therefore we must reduce the amount of
  36. registers until there are less enough to fit into the processors registers.
  37. Registers can interfere or not interfere. If two imaginary registers interfere
  38. they cannot be placed into the same psysical register. Reduction of registers
  39. is done by:
  40. - "coalescing" Two registers that do not interfere are combined
  41. into one register.
  42. - "spilling" A register is changed into a memory location and the generated
  43. code is modified to use the memory location instead of the register.
  44. Register allocation is a graph colouring problem. Each register is a colour, and
  45. if two registers interfere there is a connection between them in the graph.
  46. In addition to the imaginary registers in the code generator, the psysical
  47. CPU registers are also present in this graph. This allows us to make
  48. interferences between imaginary registers and cpu registers. This is very
  49. usefull for describing architectural constraints, like for example that
  50. the div instruction modifies edx, so variables that are in use at that time
  51. cannot be stored into edx. This can be modelled by making edx interfere
  52. with those variables.
  53. Graph colouring is an NP complete problem. Therefore we use an approximation
  54. that pushes registers to colour on to a stack. This is done in the "simplify"
  55. procedure.
  56. The register allocator first checks which registers are a candidate for
  57. coalescing.
  58. *******************************************************************************}
  59. unit rgobj;
  60. interface
  61. uses
  62. cutils, cpubase,
  63. aasmbase,aasmtai,aasmcpu,
  64. cclasses,globtype,cgbase,node,
  65. {$ifdef delphi}
  66. dmisc,
  67. {$endif}
  68. cpuinfo
  69. ;
  70. type
  71. {
  72. regvarother_longintarray = array[tregisterindex] of longint;
  73. regvarother_booleanarray = array[tregisterindex] of boolean;
  74. regvarint_longintarray = array[first_int_supreg..last_int_supreg] of longint;
  75. regvarint_ptreearray = array[first_int_supreg..last_int_supreg] of tnode;
  76. }
  77. {
  78. The interference bitmap contains of 2 layers:
  79. layer 1 - 256*256 blocks with pointers to layer 2 blocks
  80. layer 2 - blocks of 32*256 (32 bytes = 256 bits)
  81. }
  82. Tinterferencebitmap2 = array[byte] of set of byte;
  83. Pinterferencebitmap2 = ^Tinterferencebitmap2;
  84. Tinterferencebitmap1 = array[byte] of Pinterferencebitmap2;
  85. pinterferencebitmap1 = ^tinterferencebitmap1;
  86. Tinterferencebitmap=class
  87. private
  88. maxx1,
  89. maxy1 : byte;
  90. fbitmap : pinterferencebitmap1;
  91. function getbitmap(x,y:tsuperregister):boolean;
  92. procedure setbitmap(x,y:tsuperregister;b:boolean);
  93. public
  94. constructor create;
  95. destructor destroy;override;
  96. property bitmap[x,y:tsuperregister]:boolean read getbitmap write setbitmap;default;
  97. end;
  98. Tmovelist=record
  99. count:cardinal;
  100. data:array[0..$ffff] of Tlinkedlistitem;
  101. end;
  102. Pmovelist=^Tmovelist;
  103. {In the register allocator we keep track of move instructions.
  104. These instructions are moved between five linked lists. There
  105. is also a linked list per register to keep track about the moves
  106. it is associated with. Because we need to determine quickly in
  107. which of the five lists it is we add anu enumeradtion to each
  108. move instruction.}
  109. Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
  110. ms_worklist_moves,ms_active_moves);
  111. Tmoveins=class(Tlinkedlistitem)
  112. moveset:Tmoveset;
  113. x,y:Tsuperregister;
  114. end;
  115. Treginfoflag=(ri_coalesced,ri_selected);
  116. Treginfoflagset=set of Treginfoflag;
  117. Treginfo=record
  118. live_start,
  119. live_end : Tai;
  120. subreg : tsubregister;
  121. alias : Tsuperregister;
  122. { The register allocator assigns each register a colour }
  123. colour : Tsuperregister;
  124. movelist : Pmovelist;
  125. adjlist : Psuperregisterworklist;
  126. degree : TSuperregister;
  127. flags : Treginfoflagset;
  128. end;
  129. Preginfo=^TReginfo;
  130. {#------------------------------------------------------------------
  131. This class implements the default register allocator. It is used by the
  132. code generator to allocate and free registers which might be valid
  133. across nodes. It also contains utility routines related to registers.
  134. Some of the methods in this class should be overriden
  135. by cpu-specific implementations.
  136. --------------------------------------------------------------------}
  137. trgobj=class
  138. preserved_by_proc : tcpuregisterset;
  139. used_in_proc : tcpuregisterset;
  140. // is_reg_var : Tsuperregisterset; {old regvars}
  141. // reg_var_loaded:Tsuperregisterset; {old regvars}
  142. constructor create(Aregtype:Tregistertype;
  143. Adefaultsub:Tsubregister;
  144. const Ausable:array of tsuperregister;
  145. Afirst_imaginary:Tsuperregister;
  146. Apreserved_by_proc:Tcpuregisterset);
  147. destructor destroy;override;
  148. {# Allocate a register. An internalerror will be generated if there is
  149. no more free registers which can be allocated.}
  150. function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;
  151. {# Get the register specified.}
  152. procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;
  153. {# Get multiple registers specified.}
  154. procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
  155. {# Free multiple registers specified.}
  156. procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
  157. function uses_registers:boolean;virtual;
  158. {# Deallocate any kind of register }
  159. procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
  160. procedure add_reg_instruction(instr:Tai;r:tregister);
  161. procedure add_move_instruction(instr:Taicpu);
  162. {# Do the register allocation.}
  163. procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
  164. { Adds an interference edge.
  165. don't move this to the protected section, the arm cg requires to access this (FK) }
  166. procedure add_edge(u,v:Tsuperregister);
  167. protected
  168. regtype : Tregistertype;
  169. { default subregister used }
  170. defaultsub : tsubregister;
  171. procedure add_constraints(reg:Tregister);virtual;
  172. private
  173. {# First imaginary register.}
  174. first_imaginary : Tsuperregister;
  175. {# Highest register allocated until now.}
  176. reginfo : PReginfo;
  177. maxreginfo,
  178. maxreginfoinc,
  179. maxreg : Tsuperregister;
  180. usable_registers_cnt : word;
  181. usable_registers : array[0..maxcpuregister-1] of tsuperregister;
  182. ibitmap : Tinterferencebitmap;
  183. spillednodes,
  184. simplifyworklist,
  185. freezeworklist,
  186. spillworklist,
  187. coalescednodes,
  188. selectstack : tsuperregisterworklist;
  189. worklist_moves,
  190. active_moves,
  191. frozen_moves,
  192. coalesced_moves,
  193. constrained_moves : Tlinkedlist;
  194. live_registers:Tsuperregisterworklist;
  195. {$ifdef EXTDEBUG}
  196. procedure writegraph(loopidx:longint);
  197. {$endif EXTDEBUG}
  198. {# Prepare the register colouring.}
  199. procedure prepare_colouring;
  200. {# Clean up after register colouring.}
  201. procedure epilogue_colouring;
  202. {# Colour the registers; that is do the register allocation.}
  203. procedure colour_registers;
  204. {# Spills certain registers in the specified assembler list.}
  205. procedure insert_regalloc_info(list:Taasmoutput;headertai:tai);
  206. procedure generate_interference_graph(list:Taasmoutput;headertai:tai);
  207. procedure translate_registers(list:Taasmoutput);
  208. function spill_registers(list:Taasmoutput;headertai:tai):boolean;
  209. function getnewreg(subreg:tsubregister):tsuperregister;
  210. procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
  211. procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
  212. procedure add_edges_used(u:Tsuperregister);
  213. procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
  214. function move_related(n:Tsuperregister):boolean;
  215. procedure make_work_list;
  216. procedure sort_simplify_worklist;
  217. procedure enable_moves(n:Tsuperregister);
  218. procedure decrement_degree(m:Tsuperregister);
  219. procedure simplify;
  220. function get_alias(n:Tsuperregister):Tsuperregister;
  221. procedure add_worklist(u:Tsuperregister);
  222. function adjacent_ok(u,v:Tsuperregister):boolean;
  223. function conservative(u,v:Tsuperregister):boolean;
  224. procedure combine(u,v:Tsuperregister);
  225. procedure coalesce;
  226. procedure freeze_moves(u:Tsuperregister);
  227. procedure freeze;
  228. procedure select_spill;
  229. procedure assign_colours;
  230. procedure clear_interferences(u:Tsuperregister);
  231. end;
  232. const
  233. first_reg = 0;
  234. last_reg = high(tsuperregister)-1;
  235. maxspillingcounter = 20;
  236. implementation
  237. uses
  238. systems,
  239. globals,verbose,tgobj,procinfo;
  240. {******************************************************************************
  241. tinterferencebitmap
  242. ******************************************************************************}
  243. constructor tinterferencebitmap.create;
  244. begin
  245. inherited create;
  246. maxx1:=1;
  247. getmem(fbitmap,sizeof(tinterferencebitmap1)*2);
  248. fillchar(fbitmap^,sizeof(tinterferencebitmap1)*2,0);
  249. end;
  250. destructor tinterferencebitmap.destroy;
  251. var i,j:byte;
  252. begin
  253. for i:=0 to maxx1 do
  254. for j:=0 to maxy1 do
  255. if assigned(fbitmap[i,j]) then
  256. dispose(fbitmap[i,j]);
  257. freemem(fbitmap);
  258. end;
  259. function tinterferencebitmap.getbitmap(x,y:tsuperregister):boolean;
  260. var
  261. page : pinterferencebitmap2;
  262. begin
  263. result:=false;
  264. if (x shr 8>maxx1) then
  265. exit;
  266. page:=fbitmap[x shr 8,y shr 8];
  267. result:=assigned(page) and
  268. ((x and $ff) in page^[y and $ff]);
  269. end;
  270. procedure tinterferencebitmap.setbitmap(x,y:tsuperregister;b:boolean);
  271. var
  272. x1,y1 : byte;
  273. begin
  274. x1:=x shr 8;
  275. y1:=y shr 8;
  276. if x1>maxx1 then
  277. begin
  278. reallocmem(fbitmap,sizeof(tinterferencebitmap1)*(x1+1));
  279. fillchar(fbitmap[maxx1+1],sizeof(tinterferencebitmap1)*(x1-maxx1),0);
  280. maxx1:=x1;
  281. end;
  282. if not assigned(fbitmap[x1,y1]) then
  283. begin
  284. if y1>maxy1 then
  285. maxy1:=y1;
  286. new(fbitmap[x1,y1]);
  287. fillchar(fbitmap[x1,y1]^,sizeof(tinterferencebitmap2),0);
  288. end;
  289. if b then
  290. include(fbitmap[x1,y1]^[y and $ff],(x and $ff))
  291. else
  292. exclude(fbitmap[x1,y1]^[y and $ff],(x and $ff));
  293. end;
  294. {******************************************************************************
  295. trgobj
  296. ******************************************************************************}
  297. constructor trgobj.create(Aregtype:Tregistertype;
  298. Adefaultsub:Tsubregister;
  299. const Ausable:array of tsuperregister;
  300. Afirst_imaginary:Tsuperregister;
  301. Apreserved_by_proc:Tcpuregisterset);
  302. var
  303. i : Tsuperregister;
  304. begin
  305. { empty super register sets can cause very strange problems }
  306. if high(Ausable)=0 then
  307. internalerror(200210181);
  308. first_imaginary:=Afirst_imaginary;
  309. maxreg:=Afirst_imaginary;
  310. regtype:=Aregtype;
  311. defaultsub:=Adefaultsub;
  312. preserved_by_proc:=Apreserved_by_proc;
  313. used_in_proc:=[];
  314. live_registers.init;
  315. ibitmap:=tinterferencebitmap.create;
  316. { Get reginfo for CPU registers }
  317. reginfo:=allocmem(first_imaginary*sizeof(treginfo));
  318. maxreginfo:=first_imaginary;
  319. maxreginfoinc:=16;
  320. for i:=0 to first_imaginary-1 do
  321. reginfo[i].degree:=high(tsuperregister);
  322. worklist_moves:=Tlinkedlist.create;
  323. { Usable registers }
  324. fillchar(usable_registers,sizeof(usable_registers),0);
  325. for i:=low(Ausable) to high(Ausable) do
  326. usable_registers[i]:=Ausable[i];
  327. usable_registers_cnt:=high(Ausable)+1;
  328. { Initialize Worklists }
  329. spillednodes.init;
  330. simplifyworklist.init;
  331. freezeworklist.init;
  332. spillworklist.init;
  333. coalescednodes.init;
  334. selectstack.init;
  335. for i:=0 to maxreg-1 do
  336. reginfo[i].alias:=RS_INVALID;
  337. end;
  338. destructor trgobj.destroy;
  339. var i:Tsuperregister;
  340. begin
  341. spillednodes.done;
  342. simplifyworklist.done;
  343. freezeworklist.done;
  344. spillworklist.done;
  345. coalescednodes.done;
  346. selectstack.done;
  347. for i:=0 to maxreg-1 do
  348. begin
  349. if reginfo[i].adjlist<>nil then
  350. dispose(reginfo[i].adjlist,done);
  351. if reginfo[i].movelist<>nil then
  352. dispose(reginfo[i].movelist);
  353. end;
  354. freemem(reginfo);
  355. worklist_moves.free;
  356. ibitmap.free;
  357. end;
  358. function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
  359. var
  360. oldmaxreginfo : tsuperregister;
  361. begin
  362. result:=maxreg;
  363. inc(maxreg);
  364. if maxreg>=last_reg then
  365. internalerror(200310146);
  366. if maxreg>=maxreginfo then
  367. begin
  368. oldmaxreginfo:=maxreginfo;
  369. inc(maxreginfo,maxreginfoinc);
  370. if maxreginfoinc<256 then
  371. maxreginfoinc:=maxreginfoinc*2;
  372. reallocmem(reginfo,maxreginfo*sizeof(treginfo));
  373. { Do we really need it to clear it ? At least for 1.0.x (PFV) }
  374. fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
  375. end;
  376. reginfo[result].subreg:=subreg;
  377. end;
  378. function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
  379. begin
  380. if defaultsub=R_SUBNONE then
  381. result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
  382. else
  383. result:=newreg(regtype,getnewreg(subreg),subreg);
  384. end;
  385. function trgobj.uses_registers:boolean;
  386. begin
  387. result:=(maxreg>first_imaginary);
  388. end;
  389. procedure trgobj.ungetregister(list:Taasmoutput;r:Tregister);
  390. begin
  391. { Only explicit allocs insert regalloc info }
  392. if getsupreg(r)<first_imaginary then
  393. list.concat(Tai_regalloc.dealloc(r));
  394. end;
  395. procedure trgobj.getexplicitregister(list:Taasmoutput;r:Tregister);
  396. var
  397. supreg:Tsuperregister;
  398. begin
  399. supreg:=getsupreg(r);
  400. if supreg>=first_imaginary then
  401. internalerror(2003121503);
  402. include(used_in_proc,supreg);
  403. list.concat(Tai_regalloc.alloc(r));
  404. end;
  405. procedure trgobj.allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
  406. var i:Tsuperregister;
  407. begin
  408. for i:=0 to first_imaginary-1 do
  409. if i in r then
  410. getexplicitregister(list,newreg(regtype,i,defaultsub));
  411. end;
  412. procedure trgobj.deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
  413. var i:Tsuperregister;
  414. begin
  415. for i:=0 to first_imaginary-1 do
  416. if i in r then
  417. ungetregister(list,newreg(regtype,i,defaultsub));
  418. end;
  419. procedure trgobj.do_register_allocation(list:Taasmoutput;headertai:tai);
  420. var
  421. spillingcounter:byte;
  422. endspill:boolean;
  423. begin
  424. { Insert regalloc info for imaginary registers }
  425. insert_regalloc_info(list,headertai);
  426. generate_interference_graph(list,headertai);
  427. { Don't do the real allocation when -sr is passed }
  428. if (cs_no_regalloc in aktglobalswitches) then
  429. exit;
  430. {Do register allocation.}
  431. spillingcounter:=0;
  432. repeat
  433. prepare_colouring;
  434. colour_registers;
  435. epilogue_colouring;
  436. endspill:=true;
  437. if spillednodes.length<>0 then
  438. begin
  439. inc(spillingcounter);
  440. if spillingcounter>maxspillingcounter then
  441. internalerror(200309041);
  442. endspill:=not spill_registers(list,headertai);
  443. end;
  444. until endspill;
  445. translate_registers(list);
  446. end;
  447. procedure trgobj.add_constraints(reg:Tregister);
  448. begin
  449. end;
  450. procedure trgobj.add_edge(u,v:Tsuperregister);
  451. {This procedure will add an edge to the virtual interference graph.}
  452. procedure addadj(u,v:Tsuperregister);
  453. begin
  454. if reginfo[u].adjlist=nil then
  455. new(reginfo[u].adjlist,init);
  456. reginfo[u].adjlist^.add(v);
  457. end;
  458. begin
  459. if (u<>v) and not(ibitmap[v,u]) then
  460. begin
  461. ibitmap[v,u]:=true;
  462. ibitmap[u,v]:=true;
  463. {Precoloured nodes are not stored in the interference graph.}
  464. if (u>=first_imaginary) then
  465. addadj(u,v);
  466. if (v>=first_imaginary) then
  467. addadj(v,u);
  468. end;
  469. end;
  470. procedure trgobj.add_edges_used(u:Tsuperregister);
  471. var i:word;
  472. begin
  473. if live_registers.length>0 then
  474. for i:=0 to live_registers.length-1 do
  475. add_edge(u,live_registers.buf^[i]);
  476. end;
  477. {$ifdef EXTDEBUG}
  478. procedure trgobj.writegraph(loopidx:longint);
  479. {This procedure writes out the current interference graph in the
  480. register allocator.}
  481. var f:text;
  482. i,j:Tsuperregister;
  483. begin
  484. assign(f,'igraph'+tostr(loopidx));
  485. rewrite(f);
  486. writeln(f,'Interference graph');
  487. writeln(f);
  488. write(f,' ');
  489. for i:=0 to 15 do
  490. for j:=0 to 15 do
  491. write(f,hexstr(i,1));
  492. writeln(f);
  493. write(f,' ');
  494. for i:=0 to 15 do
  495. write(f,'0123456789ABCDEF');
  496. writeln(f);
  497. for i:=0 to maxreg-1 do
  498. begin
  499. write(f,hexstr(i,2):4);
  500. for j:=0 to maxreg-1 do
  501. if ibitmap[i,j] then
  502. write(f,'*')
  503. else
  504. write(f,'-');
  505. writeln(f);
  506. end;
  507. close(f);
  508. end;
  509. {$endif EXTDEBUG}
  510. procedure trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
  511. begin
  512. if reginfo[u].movelist=nil then
  513. begin
  514. getmem(reginfo[u].movelist,64);
  515. reginfo[u].movelist^.count:=0;
  516. end
  517. else if (reginfo[u].movelist^.count and 15)=15 then
  518. reallocmem(reginfo[u].movelist,(reginfo[u].movelist^.count+1)*4+64);
  519. reginfo[u].movelist^.data[reginfo[u].movelist^.count]:=data;
  520. inc(reginfo[u].movelist^.count);
  521. end;
  522. procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
  523. var
  524. supreg : tsuperregister;
  525. begin
  526. supreg:=getsupreg(r);
  527. if supreg>=first_imaginary then
  528. begin
  529. if not assigned(reginfo[supreg].live_start) then
  530. reginfo[supreg].live_start:=instr;
  531. reginfo[supreg].live_end:=instr;
  532. end;
  533. end;
  534. procedure trgobj.add_move_instruction(instr:Taicpu);
  535. {This procedure notifies a certain as a move instruction so the
  536. register allocator can try to eliminate it.}
  537. var i:Tmoveins;
  538. ssupreg,dsupreg:Tsuperregister;
  539. begin
  540. {$ifdef extdebug}
  541. if (instr.oper[O_MOV_SOURCE]^.typ<>top_reg) or
  542. (instr.oper[O_MOV_DEST]^.typ<>top_reg) then
  543. internalerror(200311291);
  544. {$endif}
  545. i:=Tmoveins.create;
  546. i.moveset:=ms_worklist_moves;
  547. worklist_moves.insert(i);
  548. ssupreg:=getsupreg(instr.oper[O_MOV_SOURCE]^.reg);
  549. add_to_movelist(ssupreg,i);
  550. dsupreg:=getsupreg(instr.oper[O_MOV_DEST]^.reg);
  551. if ssupreg<>dsupreg then
  552. {Avoid adding the same move instruction twice to a single register.}
  553. add_to_movelist(dsupreg,i);
  554. i.x:=ssupreg;
  555. i.y:=dsupreg;
  556. end;
  557. function trgobj.move_related(n:Tsuperregister):boolean;
  558. var i:cardinal;
  559. begin
  560. move_related:=false;
  561. if reginfo[n].movelist<>nil then
  562. for i:=0 to reginfo[n].movelist^.count-1 do
  563. if Tmoveins(reginfo[n].movelist^.data[i]).moveset in [ms_worklist_moves,ms_active_moves] then
  564. begin
  565. move_related:=true;
  566. break;
  567. end;
  568. end;
  569. procedure Trgobj.sort_simplify_worklist;
  570. {Sorts the simplifyworklist by the number of interferences the
  571. registers in it cause. This allows simplify to execute in
  572. constant time.}
  573. var p,h,i,j,leni,lenj:word;
  574. t:Tsuperregister;
  575. adji,adjj:Psuperregisterworklist;
  576. begin
  577. if simplifyworklist.length<2 then
  578. exit;
  579. p:=1;
  580. while 2*p<simplifyworklist.length do
  581. p:=2*p;
  582. while p<>0 do
  583. begin
  584. for h:=0 to simplifyworklist.length-p-1 do
  585. begin
  586. i:=h;
  587. repeat
  588. j:=i+p;
  589. adji:=reginfo[simplifyworklist.buf^[i]].adjlist;
  590. adjj:=reginfo[simplifyworklist.buf^[j]].adjlist;
  591. if adji=nil then
  592. leni:=0
  593. else
  594. leni:=adji^.length;
  595. if adjj=nil then
  596. lenj:=0
  597. else
  598. lenj:=adjj^.length;
  599. if lenj>=leni then
  600. break;
  601. t:=simplifyworklist.buf^[i];
  602. simplifyworklist.buf^[i]:=simplifyworklist.buf^[j];
  603. simplifyworklist.buf^[j]:=t;
  604. if i<p then
  605. break;
  606. dec(i,p)
  607. until false;
  608. end;
  609. p:=p shr 1;
  610. end;
  611. end;
  612. procedure trgobj.make_work_list;
  613. var n:Tsuperregister;
  614. begin
  615. {If we have 7 cpu registers, and the degree of a node is 7, we cannot
  616. assign it to any of the registers, thus it is significant.}
  617. for n:=first_imaginary to maxreg-1 do
  618. begin
  619. if reginfo[n].adjlist=nil then
  620. reginfo[n].degree:=0
  621. else
  622. reginfo[n].degree:=reginfo[n].adjlist^.length;
  623. if reginfo[n].degree>=usable_registers_cnt then
  624. spillworklist.add(n)
  625. else if move_related(n) then
  626. freezeworklist.add(n)
  627. else
  628. simplifyworklist.add(n);
  629. end;
  630. sort_simplify_worklist;
  631. end;
  632. procedure trgobj.prepare_colouring;
  633. var i:word;
  634. begin
  635. make_work_list;
  636. active_moves:=Tlinkedlist.create;
  637. frozen_moves:=Tlinkedlist.create;
  638. coalesced_moves:=Tlinkedlist.create;
  639. constrained_moves:=Tlinkedlist.create;
  640. selectstack.clear;
  641. end;
  642. procedure trgobj.enable_moves(n:Tsuperregister);
  643. var m:Tlinkedlistitem;
  644. i:cardinal;
  645. begin
  646. if reginfo[n].movelist<>nil then
  647. for i:=0 to reginfo[n].movelist^.count-1 do
  648. begin
  649. m:=reginfo[n].movelist^.data[i];
  650. if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
  651. if Tmoveins(m).moveset=ms_active_moves then
  652. begin
  653. {Move m from the set active_moves to the set worklist_moves.}
  654. active_moves.remove(m);
  655. Tmoveins(m).moveset:=ms_worklist_moves;
  656. worklist_moves.concat(m);
  657. end;
  658. end;
  659. end;
  660. procedure trgobj.decrement_degree(m:Tsuperregister);
  661. var adj : Psuperregisterworklist;
  662. d,n : tsuperregister;
  663. i : word;
  664. begin
  665. d:=reginfo[m].degree;
  666. if d=0 then
  667. internalerror(200312151);
  668. dec(reginfo[m].degree);
  669. if d=usable_registers_cnt then
  670. begin
  671. {Enable moves for m.}
  672. enable_moves(m);
  673. {Enable moves for adjacent.}
  674. adj:=reginfo[m].adjlist;
  675. if adj<>nil then
  676. for i:=1 to adj^.length do
  677. begin
  678. n:=adj^.buf^[i-1];
  679. if reginfo[n].flags*[ri_selected,ri_coalesced]<>[] then
  680. enable_moves(n);
  681. end;
  682. {Remove the node from the spillworklist.}
  683. if not spillworklist.delete(m) then
  684. internalerror(200310145);
  685. if move_related(m) then
  686. freezeworklist.add(m)
  687. else
  688. simplifyworklist.add(m);
  689. end;
  690. end;
  691. procedure trgobj.simplify;
  692. var adj : Psuperregisterworklist;
  693. m,n : Tsuperregister;
  694. i : word;
  695. begin
  696. {We take the element with the least interferences out of the
  697. simplifyworklist. Since the simplifyworklist is now sorted, we
  698. no longer need to search, but we can simply take the first element.}
  699. m:=simplifyworklist.get;
  700. {Push it on the selectstack.}
  701. selectstack.add(m);
  702. include(reginfo[m].flags,ri_selected);
  703. adj:=reginfo[m].adjlist;
  704. if adj<>nil then
  705. for i:=1 to adj^.length do
  706. begin
  707. n:=adj^.buf^[i-1];
  708. if (n>=first_imaginary) and
  709. (reginfo[n].flags*[ri_selected,ri_coalesced]=[]) then
  710. decrement_degree(n);
  711. end;
  712. end;
  713. function trgobj.get_alias(n:Tsuperregister):Tsuperregister;
  714. begin
  715. while ri_coalesced in reginfo[n].flags do
  716. n:=reginfo[n].alias;
  717. get_alias:=n;
  718. end;
  719. procedure trgobj.add_worklist(u:Tsuperregister);
  720. begin
  721. if (u>=first_imaginary) and
  722. (not move_related(u)) and
  723. (reginfo[u].degree<usable_registers_cnt) then
  724. begin
  725. if not freezeworklist.delete(u) then
  726. internalerror(200308161); {must be found}
  727. simplifyworklist.add(u);
  728. end;
  729. end;
  730. function trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
  731. {Check wether u and v should be coalesced. u is precoloured.}
  732. function ok(t,r:Tsuperregister):boolean;
  733. begin
  734. ok:=(t<first_imaginary) or
  735. (reginfo[t].degree<usable_registers_cnt) or
  736. ibitmap[r,t];
  737. end;
  738. var adj : Psuperregisterworklist;
  739. i : word;
  740. n : tsuperregister;
  741. begin
  742. adjacent_ok:=true;
  743. adj:=reginfo[v].adjlist;
  744. if adj<>nil then
  745. for i:=1 to adj^.length do
  746. begin
  747. n:=adj^.buf^[i-1];
  748. if (reginfo[v].flags*[ri_coalesced,ri_selected]=[]) and
  749. not ok(n,u) then
  750. begin
  751. adjacent_ok:=false;
  752. break;
  753. end;
  754. end;
  755. end;
  756. function trgobj.conservative(u,v:Tsuperregister):boolean;
  757. var adj : Psuperregisterworklist;
  758. done : Tsuperregisterset; {To prevent that we count nodes twice.}
  759. i,k:word;
  760. n : tsuperregister;
  761. begin
  762. k:=0;
  763. supregset_reset(done,false);
  764. adj:=reginfo[u].adjlist;
  765. if adj<>nil then
  766. for i:=1 to adj^.length do
  767. begin
  768. n:=adj^.buf^[i-1];
  769. if reginfo[u].flags*[ri_coalesced,ri_selected]=[] then
  770. begin
  771. supregset_include(done,n);
  772. if reginfo[n].degree>=usable_registers_cnt then
  773. inc(k);
  774. end;
  775. end;
  776. adj:=reginfo[v].adjlist;
  777. if adj<>nil then
  778. for i:=1 to adj^.length do
  779. begin
  780. n:=adj^.buf^[i-1];
  781. if not supregset_in(done,n) and
  782. (reginfo[n].degree>=usable_registers_cnt) and
  783. (reginfo[u].flags*[ri_coalesced,ri_selected]=[]) then
  784. inc(k);
  785. end;
  786. conservative:=(k<usable_registers_cnt);
  787. end;
  788. procedure trgobj.combine(u,v:Tsuperregister);
  789. var adj : Psuperregisterworklist;
  790. i : word;
  791. t : tsuperregister;
  792. n,o : cardinal;
  793. decrement : boolean;
  794. label l1;
  795. begin
  796. if not freezeworklist.delete(v) then
  797. spillworklist.delete(v);
  798. coalescednodes.add(v);
  799. include(reginfo[v].flags,ri_coalesced);
  800. reginfo[v].alias:=u;
  801. {Combine both movelists. Since the movelists are sets, only add
  802. elements that are not already present.}
  803. if assigned(reginfo[v].movelist) then
  804. begin
  805. for n:=0 to reginfo[v].movelist^.count-1 do
  806. begin
  807. for o:=0 to reginfo[u].movelist^.count-1 do
  808. if reginfo[u].movelist^.data[o]=reginfo[v].movelist^.data[n] then
  809. goto l1; {Continue outer loop.}
  810. add_to_movelist(u,reginfo[v].movelist^.data[n]);
  811. l1:
  812. end;
  813. enable_moves(v);
  814. end;
  815. adj:=reginfo[v].adjlist;
  816. if adj<>nil then
  817. for i:=1 to adj^.length do
  818. begin
  819. t:=adj^.buf^[i-1];
  820. if reginfo[t].flags*[ri_coalesced,ri_selected]=[] then
  821. begin
  822. {t has a connection to v. Since we are adding v to u, we
  823. need to connect t to u. However, beware if t was already
  824. connected to u...}
  825. if ibitmap[t,u] then
  826. {... because in that case, we are actually removing an edge
  827. and the degree of t decreases.}
  828. decrement_degree(t)
  829. else
  830. begin
  831. add_edge(t,u);
  832. {We have added an edge to t and u. So their degree increases.
  833. However, v is added to u. That means its neighbours will
  834. no longer point to v, but to u instead. Therefore, only the
  835. degree of u increases.}
  836. if u>=first_imaginary then
  837. inc(reginfo[u].degree);
  838. end;
  839. end;
  840. end;
  841. if (reginfo[u].degree>=usable_registers_cnt) and
  842. freezeworklist.delete(u) then
  843. spillworklist.add(u);
  844. end;
  845. procedure trgobj.coalesce;
  846. var m:Tmoveins;
  847. x,y,u,v:Tsuperregister;
  848. begin
  849. m:=Tmoveins(worklist_moves.getfirst);
  850. x:=get_alias(m.x);
  851. y:=get_alias(m.y);
  852. if (y<first_imaginary) then
  853. begin
  854. u:=y;
  855. v:=x;
  856. end
  857. else
  858. begin
  859. u:=x;
  860. v:=y;
  861. end;
  862. if (u=v) then
  863. begin
  864. m.moveset:=ms_coalesced_moves; {Already coalesced.}
  865. coalesced_moves.insert(m);
  866. add_worklist(u);
  867. end
  868. {Do u and v interfere? In that case the move is constrained. Two
  869. precoloured nodes interfere allways. If v is precoloured, by the above
  870. code u is precoloured, thus interference...}
  871. else if (v<first_imaginary) or ibitmap[u,v] then
  872. begin
  873. m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
  874. constrained_moves.insert(m);
  875. add_worklist(u);
  876. add_worklist(v);
  877. end
  878. {Next test: is it possible and a good idea to coalesce??}
  879. else if ((u<first_imaginary) and adjacent_ok(u,v)) or
  880. ((u>=first_imaginary) and conservative(u,v)) then
  881. begin
  882. m.moveset:=ms_coalesced_moves; {Move coalesced!}
  883. coalesced_moves.insert(m);
  884. combine(u,v);
  885. add_worklist(u);
  886. end
  887. else
  888. begin
  889. m.moveset:=ms_active_moves;
  890. active_moves.insert(m);
  891. end;
  892. end;
  893. procedure trgobj.freeze_moves(u:Tsuperregister);
  894. var i:cardinal;
  895. m:Tlinkedlistitem;
  896. v,x,y:Tsuperregister;
  897. begin
  898. if reginfo[u].movelist<>nil then
  899. for i:=0 to reginfo[u].movelist^.count-1 do
  900. begin
  901. m:=reginfo[u].movelist^.data[i];
  902. if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
  903. begin
  904. x:=Tmoveins(m).x;
  905. y:=Tmoveins(m).y;
  906. if get_alias(y)=get_alias(u) then
  907. v:=get_alias(x)
  908. else
  909. v:=get_alias(y);
  910. {Move m from active_moves/worklist_moves to frozen_moves.}
  911. if Tmoveins(m).moveset=ms_active_moves then
  912. active_moves.remove(m)
  913. else
  914. worklist_moves.remove(m);
  915. Tmoveins(m).moveset:=ms_frozen_moves;
  916. frozen_moves.insert(m);
  917. if (v>=first_imaginary) and not(move_related(v)) and
  918. (reginfo[v].degree<usable_registers_cnt) then
  919. begin
  920. freezeworklist.delete(v);
  921. simplifyworklist.add(v);
  922. end;
  923. end;
  924. end;
  925. end;
  926. procedure trgobj.freeze;
  927. var n:Tsuperregister;
  928. begin
  929. { We need to take a random element out of the freezeworklist. We take
  930. the last element. Dirty code! }
  931. n:=freezeworklist.get;
  932. {Add it to the simplifyworklist.}
  933. simplifyworklist.add(n);
  934. freeze_moves(n);
  935. end;
  936. procedure trgobj.select_spill;
  937. var
  938. n : tsuperregister;
  939. adj : psuperregisterworklist;
  940. max,p,i:word;
  941. begin
  942. { We must look for the element with the most interferences in the
  943. spillworklist. This is required because those registers are creating
  944. the most conflicts and keeping them in a register will not reduce the
  945. complexity and even can cause the help registers for the spilling code
  946. to get too much conflicts with the result that the spilling code
  947. will never converge (PFV) }
  948. max:=0;
  949. p:=0;
  950. {Safe: This procedure is only called if length<>0}
  951. for i:=0 to spillworklist.length-1 do
  952. begin
  953. adj:=reginfo[spillworklist.buf^[i]].adjlist;
  954. if assigned(adj) and (adj^.length>max) then
  955. begin
  956. p:=i;
  957. max:=adj^.length;
  958. end;
  959. end;
  960. n:=spillworklist.buf^[p];
  961. spillworklist.deleteidx(p);
  962. simplifyworklist.add(n);
  963. freeze_moves(n);
  964. end;
  965. procedure trgobj.assign_colours;
  966. {Assign_colours assigns the actual colours to the registers.}
  967. var adj : Psuperregisterworklist;
  968. i,j,k : word;
  969. n,a,c : Tsuperregister;
  970. adj_colours,
  971. colourednodes : Tsuperregisterset;
  972. found : boolean;
  973. begin
  974. spillednodes.clear;
  975. {Reset colours}
  976. for n:=0 to maxreg-1 do
  977. reginfo[n].colour:=n;
  978. {Colour the cpu registers...}
  979. supregset_reset(colourednodes,false);
  980. for n:=0 to first_imaginary-1 do
  981. supregset_include(colourednodes,n);
  982. {Now colour the imaginary registers on the select-stack.}
  983. for i:=selectstack.length downto 1 do
  984. begin
  985. n:=selectstack.buf^[i-1];
  986. {Create a list of colours that we cannot assign to n.}
  987. supregset_reset(adj_colours,false);
  988. adj:=reginfo[n].adjlist;
  989. if adj<>nil then
  990. for j:=0 to adj^.length-1 do
  991. begin
  992. a:=get_alias(adj^.buf^[j]);
  993. if supregset_in(colourednodes,a) then
  994. supregset_include(adj_colours,reginfo[a].colour);
  995. end;
  996. supregset_include(adj_colours,RS_STACK_POINTER_REG);
  997. {Assume a spill by default...}
  998. found:=false;
  999. {Search for a colour not in this list.}
  1000. for k:=0 to usable_registers_cnt-1 do
  1001. begin
  1002. c:=usable_registers[k];
  1003. if not(supregset_in(adj_colours,c)) then
  1004. begin
  1005. reginfo[n].colour:=c;
  1006. found:=true;
  1007. supregset_include(colourednodes,n);
  1008. include(used_in_proc,c);
  1009. break;
  1010. end;
  1011. end;
  1012. if not found then
  1013. spillednodes.add(n);
  1014. end;
  1015. {Finally colour the nodes that were coalesced.}
  1016. for i:=1 to coalescednodes.length do
  1017. begin
  1018. n:=coalescednodes.buf^[i-1];
  1019. k:=get_alias(n);
  1020. reginfo[n].colour:=reginfo[k].colour;
  1021. if reginfo[k].colour<maxcpuregister then
  1022. include(used_in_proc,reginfo[k].colour);
  1023. end;
  1024. {$ifdef ra_debug}
  1025. if aktfilepos.line=51 then
  1026. begin
  1027. writeln('colourlist');
  1028. for i:=0 to maxreg-1 do
  1029. writeln(i:4,' ',reginfo[i].colour:4)
  1030. end;
  1031. {$endif ra_debug}
  1032. end;
  1033. procedure trgobj.colour_registers;
  1034. begin
  1035. repeat
  1036. if simplifyworklist.length<>0 then
  1037. simplify
  1038. else if not(worklist_moves.empty) then
  1039. coalesce
  1040. else if freezeworklist.length<>0 then
  1041. freeze
  1042. else if spillworklist.length<>0 then
  1043. select_spill;
  1044. until (simplifyworklist.length=0) and
  1045. worklist_moves.empty and
  1046. (freezeworklist.length=0) and
  1047. (spillworklist.length=0);
  1048. assign_colours;
  1049. end;
  1050. procedure trgobj.epilogue_colouring;
  1051. var i:Tsuperregister;
  1052. begin
  1053. worklist_moves.clear;
  1054. active_moves.destroy;
  1055. active_moves:=nil;
  1056. frozen_moves.destroy;
  1057. frozen_moves:=nil;
  1058. coalesced_moves.destroy;
  1059. coalesced_moves:=nil;
  1060. constrained_moves.destroy;
  1061. constrained_moves:=nil;
  1062. for i:=0 to maxreg-1 do
  1063. if reginfo[i].movelist<>nil then
  1064. begin
  1065. dispose(reginfo[i].movelist);
  1066. reginfo[i].movelist:=nil;
  1067. end;
  1068. end;
  1069. procedure trgobj.clear_interferences(u:Tsuperregister);
  1070. {Remove node u from the interference graph and remove all collected
  1071. move instructions it is associated with.}
  1072. var i : word;
  1073. v : Tsuperregister;
  1074. adj,adj2 : Psuperregisterworklist;
  1075. begin
  1076. adj:=reginfo[u].adjlist;
  1077. if adj<>nil then
  1078. begin
  1079. for i:=1 to adj^.length do
  1080. begin
  1081. v:=adj^.buf^[i-1];
  1082. {Remove (u,v) and (v,u) from bitmap.}
  1083. ibitmap[u,v]:=false;
  1084. ibitmap[v,u]:=false;
  1085. {Remove (v,u) from adjacency list.}
  1086. adj2:=reginfo[v].adjlist;
  1087. if adj2<>nil then
  1088. begin
  1089. adj2^.delete(u);
  1090. if adj2^.length=0 then
  1091. begin
  1092. dispose(adj2,done);
  1093. reginfo[v].adjlist:=nil;
  1094. end;
  1095. end;
  1096. end;
  1097. {Remove ( u,* ) from adjacency list.}
  1098. dispose(adj,done);
  1099. reginfo[u].adjlist:=nil;
  1100. end;
  1101. end;
  1102. procedure trgobj.getregisterinline(list:Taasmoutput;
  1103. position:Tai;subreg:Tsubregister;var result:Tregister);
  1104. var p:Tsuperregister;
  1105. r:Tregister;
  1106. begin
  1107. p:=getnewreg(subreg);
  1108. live_registers.add(p);
  1109. r:=newreg(regtype,p,subreg);
  1110. if position=nil then
  1111. list.insert(Tai_regalloc.alloc(r))
  1112. else
  1113. list.insertafter(Tai_regalloc.alloc(r),position);
  1114. add_edges_used(p);
  1115. add_constraints(r);
  1116. result:=r;
  1117. end;
  1118. procedure trgobj.ungetregisterinline(list:Taasmoutput;
  1119. position:Tai;r:Tregister);
  1120. var supreg:Tsuperregister;
  1121. begin
  1122. supreg:=getsupreg(r);
  1123. live_registers.delete(supreg);
  1124. if position=nil then
  1125. list.insert(Tai_regalloc.dealloc(r))
  1126. else
  1127. list.insertafter(Tai_regalloc.dealloc(r),position);
  1128. end;
  1129. procedure trgobj.insert_regalloc_info(list:Taasmoutput;headertai:tai);
  1130. var
  1131. supreg : tsuperregister;
  1132. p : tai;
  1133. r : tregister;
  1134. begin
  1135. { Insert regallocs for all imaginary registers }
  1136. for supreg:=first_imaginary to maxreg-1 do
  1137. begin
  1138. r:=newreg(regtype,supreg,reginfo[supreg].subreg);
  1139. if assigned(reginfo[supreg].live_start) then
  1140. begin
  1141. {$ifdef EXTDEBUG}
  1142. if reginfo[supreg].live_start=reginfo[supreg].live_end then
  1143. Comment(V_Warning,'Register '+std_regname(r)+' is only used once');
  1144. {$endif EXTDEBUG}
  1145. list.insertbefore(Tai_regalloc.alloc(r),reginfo[supreg].live_start);
  1146. { Insert live end deallocation before reg allocations
  1147. to reduce conflicts }
  1148. p:=reginfo[supreg].live_end;
  1149. while assigned(p) and
  1150. assigned(p.previous) and
  1151. (tai(p.previous).typ=ait_regalloc) and
  1152. tai_regalloc(p.previous).allocation and
  1153. (tai_regalloc(p.previous).reg<>r) do
  1154. p:=tai(p.previous);
  1155. list.insertbefore(Tai_regalloc.dealloc(r),p);
  1156. end
  1157. {$ifdef EXTDEBUG}
  1158. else
  1159. Comment(V_Warning,'Register '+std_regname(r)+' not used');
  1160. {$endif EXTDEBUG}
  1161. end;
  1162. end;
  1163. procedure trgobj.generate_interference_graph(list:Taasmoutput;headertai:tai);
  1164. var
  1165. p : tai;
  1166. i : integer;
  1167. supreg : tsuperregister;
  1168. begin
  1169. { All allocations are available. Now we can generate the
  1170. interference graph. Walk through all instructions, we can
  1171. start with the headertai, because before the header tai is
  1172. only symbols. }
  1173. live_registers.clear;
  1174. p:=headertai;
  1175. while assigned(p) do
  1176. begin
  1177. case p.typ of
  1178. ait_regalloc:
  1179. begin
  1180. if (getregtype(Tai_regalloc(p).reg)=regtype) then
  1181. begin
  1182. supreg:=getsupreg(Tai_regalloc(p).reg);
  1183. if Tai_regalloc(p).allocation then
  1184. live_registers.add(supreg)
  1185. else
  1186. live_registers.delete(supreg);
  1187. add_edges_used(supreg);
  1188. add_constraints(Tai_regalloc(p).reg);
  1189. end;
  1190. end;
  1191. { ait_instruction:
  1192. begin
  1193. aktfilepos:=Taicpu_abstract(p).fileinfo;
  1194. for i:=0 to Taicpu_abstract(p).ops-1 do
  1195. with Taicpu_abstract(p).oper[i]^ do
  1196. begin
  1197. case typ of
  1198. top_reg :
  1199. begin
  1200. add_edges_used(getsupreg(reg));
  1201. add_constraints(reg);
  1202. end;
  1203. top_ref :
  1204. begin
  1205. add_edges_used(getsupreg(ref^.base));
  1206. add_constraints(ref^.base);
  1207. add_edges_used(getsupreg(ref^.index));
  1208. add_constraints(ref^.index);
  1209. end;
  1210. end;
  1211. end;
  1212. end; }
  1213. end;
  1214. p:=Tai(p.next);
  1215. end;
  1216. {$ifdef EXTDEBUG}
  1217. if live_registers.length>0 then
  1218. begin
  1219. for i:=0 to live_registers.length-1 do
  1220. begin
  1221. { Only report for imaginary registers }
  1222. if live_registers.buf^[i]>=first_imaginary then
  1223. Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
  1224. end;
  1225. end;
  1226. {$endif}
  1227. end;
  1228. function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
  1229. {Returns true if any help registers have been used.}
  1230. var i : word;
  1231. t : tsuperregister;
  1232. p,q : Tai;
  1233. regs_to_spill_set:Tsuperregisterset;
  1234. spill_temps : ^Tspill_temp_list;
  1235. supreg : tsuperregister;
  1236. templist : taasmoutput;
  1237. begin
  1238. spill_registers:=false;
  1239. live_registers.clear;
  1240. for i:=first_imaginary to maxreg-1 do
  1241. exclude(reginfo[i].flags,ri_selected);
  1242. spill_temps:=allocmem(sizeof(treference)*maxreg);
  1243. supregset_reset(regs_to_spill_set,false);
  1244. { Allocate temps and insert in front of the list }
  1245. templist:=taasmoutput.create;
  1246. {Safe: this procedure is only called if there are spilled nodes.}
  1247. for i:=0 to spillednodes.length-1 do
  1248. begin
  1249. t:=spillednodes.buf^[i];
  1250. {Alternative representation.}
  1251. supregset_include(regs_to_spill_set,t);
  1252. {Clear all interferences of the spilled register.}
  1253. clear_interferences(t);
  1254. {Get a temp for the spilled register}
  1255. tg.gettemp(templist,4,tt_noreuse,spill_temps^[t]);
  1256. end;
  1257. list.insertlistafter(headertai,templist);
  1258. templist.free;
  1259. { Walk through all instructions, we can start with the headertai,
  1260. because before the header tai is only symbols }
  1261. p:=headertai;
  1262. while assigned(p) do
  1263. begin
  1264. case p.typ of
  1265. ait_regalloc:
  1266. begin
  1267. if (getregtype(Tai_regalloc(p).reg)=regtype) then
  1268. begin
  1269. {A register allocation of a spilled register can be removed.}
  1270. supreg:=getsupreg(Tai_regalloc(p).reg);
  1271. if supregset_in(regs_to_spill_set,supreg) then
  1272. begin
  1273. q:=Tai(p.next);
  1274. list.remove(p);
  1275. p.free;
  1276. p:=q;
  1277. continue;
  1278. end
  1279. else
  1280. if Tai_regalloc(p).allocation then
  1281. live_registers.add(supreg)
  1282. else
  1283. live_registers.delete(supreg);
  1284. end;
  1285. end;
  1286. ait_instruction:
  1287. begin
  1288. aktfilepos:=Taicpu_abstract(p).fileinfo;
  1289. if Taicpu_abstract(p).spill_registers(list,
  1290. regtype,
  1291. @getregisterinline,
  1292. @ungetregisterinline,
  1293. regs_to_spill_set,
  1294. live_registers,
  1295. spill_temps^) then
  1296. spill_registers:=true;
  1297. if Taicpu_abstract(p).is_reg_move then
  1298. add_move_instruction(Taicpu(p));
  1299. end;
  1300. end;
  1301. p:=Tai(p.next);
  1302. end;
  1303. aktfilepos:=current_procinfo.exitpos;
  1304. {Safe: this procedure is only called if there are spilled nodes.}
  1305. for i:=0 to spillednodes.length-1 do
  1306. tg.ungettemp(list,spill_temps^[spillednodes.buf^[i]]);
  1307. freemem(spill_temps);
  1308. end;
  1309. procedure Trgobj.translate_registers(list:taasmoutput);
  1310. var hp,p,q:Tai;
  1311. i:shortint;
  1312. r:Preference;
  1313. {$ifdef arm}
  1314. so:pshifterop;
  1315. {$endif arm}
  1316. begin
  1317. { Leave when no imaginary registers are used }
  1318. if maxreg<=first_imaginary then
  1319. exit;
  1320. p:=Tai(list.first);
  1321. while assigned(p) do
  1322. begin
  1323. case p.typ of
  1324. ait_regalloc:
  1325. begin
  1326. if (getregtype(Tai_regalloc(p).reg)=regtype) then
  1327. setsupreg(Tai_regalloc(p).reg,reginfo[getsupreg(Tai_regalloc(p).reg)].colour);
  1328. {
  1329. Remove sequences of release and
  1330. allocation of the same register like:
  1331. # Register X released
  1332. # Register X allocated
  1333. }
  1334. if assigned(p.previous) and
  1335. (Tai(p.previous).typ=ait_regalloc) and
  1336. (Tai_regalloc(p.previous).reg=Tai_regalloc(p).reg) and
  1337. { allocation,deallocation or deallocation,allocation }
  1338. (Tai_regalloc(p.previous).allocation xor Tai_regalloc(p).allocation) then
  1339. begin
  1340. q:=Tai(p.next);
  1341. hp:=tai(p.previous);
  1342. list.remove(hp);
  1343. hp.free;
  1344. list.remove(p);
  1345. p.free;
  1346. p:=q;
  1347. continue;
  1348. end;
  1349. end;
  1350. ait_instruction:
  1351. begin
  1352. for i:=0 to Taicpu_abstract(p).ops-1 do
  1353. case Taicpu_abstract(p).oper[i]^.typ of
  1354. Top_reg:
  1355. if (getregtype(Taicpu_abstract(p).oper[i]^.reg)=regtype) then
  1356. setsupreg(Taicpu_abstract(p).oper[i]^.reg,reginfo[getsupreg(Taicpu_abstract(p).oper[i]^.reg)].colour);
  1357. Top_ref:
  1358. begin
  1359. if regtype=R_INTREGISTER then
  1360. begin
  1361. r:=Taicpu_abstract(p).oper[i]^.ref;
  1362. if r^.base<>NR_NO then
  1363. setsupreg(r^.base,reginfo[getsupreg(r^.base)].colour);
  1364. if r^.index<>NR_NO then
  1365. setsupreg(r^.index,reginfo[getsupreg(r^.index)].colour);
  1366. end;
  1367. end;
  1368. {$ifdef arm}
  1369. Top_shifterop:
  1370. begin
  1371. so:=Taicpu_abstract(p).oper[i]^.shifterop;
  1372. if so^.rs<>NR_NO then
  1373. setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
  1374. end;
  1375. {$endif arm}
  1376. end;
  1377. { Maybe the operation can be removed when
  1378. it is a move and both arguments are the same }
  1379. if Taicpu_abstract(p).is_same_reg_move then
  1380. begin
  1381. q:=Tai(p.next);
  1382. list.remove(p);
  1383. p.free;
  1384. p:=q;
  1385. continue;
  1386. end;
  1387. end;
  1388. end;
  1389. p:=Tai(p.next);
  1390. end;
  1391. end;
  1392. end.
  1393. {
  1394. $Log$
  1395. Revision 1.110 2004-01-09 22:02:29 daniel
  1396. * Degree=0 problem fixed
  1397. * Degree to high problem fixed
  1398. Revision 1.109 2003/12/26 14:02:30 peter
  1399. * sparc updates
  1400. * use registertype in spill_register
  1401. Revision 1.108 2003/12/22 23:09:34 peter
  1402. * only report unreleased imaginary registers
  1403. Revision 1.107 2003/12/22 22:13:46 peter
  1404. * made decrease_degree working, but not really fixed
  1405. Revision 1.106 2003/12/18 17:06:21 florian
  1406. * arm compiler compilation fixed
  1407. Revision 1.105 2003/12/17 21:59:05 peter
  1408. * don't insert dealloc before alloc of the same register
  1409. Revision 1.104 2003/12/16 09:41:44 daniel
  1410. * Automatic conversion from integer constants to pointer constants is no
  1411. longer done except in Delphi mode
  1412. Revision 1.103 2003/12/15 21:25:49 peter
  1413. * reg allocations for imaginary register are now inserted just
  1414. before reg allocation
  1415. * tregister changed to enum to allow compile time check
  1416. * fixed several tregister-tsuperregister errors
  1417. Revision 1.102 2003/12/15 16:37:47 daniel
  1418. * More microoptimizations
  1419. Revision 1.101 2003/12/15 15:58:58 peter
  1420. * fix statedebug compile
  1421. Revision 1.100 2003/12/14 20:24:28 daniel
  1422. * Register allocator speed optimizations
  1423. - Worklist no longer a ringbuffer
  1424. - No find operations are left
  1425. - Simplify now done in constant time
  1426. - unusedregs is now a Tsuperregisterworklist
  1427. - Microoptimizations
  1428. Revision 1.99 2003/12/12 17:16:17 peter
  1429. * rg[tregistertype] added in tcg
  1430. Revision 1.98 2003/12/04 23:27:32 peter
  1431. * remove redundant calls to add_edge_used
  1432. Revision 1.97 2003/11/29 17:36:41 peter
  1433. * check for add_move_instruction
  1434. Revision 1.96 2003/11/24 15:17:37 florian
  1435. * changed some types to prevend range check errors
  1436. Revision 1.95 2003/11/10 19:05:50 peter
  1437. * fixed alias/colouring > 255
  1438. Revision 1.94 2003/11/07 15:58:32 florian
  1439. * Florian's culmutative nr. 1; contains:
  1440. - invalid calling conventions for a certain cpu are rejected
  1441. - arm softfloat calling conventions
  1442. - -Sp for cpu dependend code generation
  1443. - several arm fixes
  1444. - remaining code for value open array paras on heap
  1445. Revision 1.93 2003/10/30 16:22:40 peter
  1446. * call firstpass before allocation and codegeneration is started
  1447. * move leftover code from pass_2.generatecode() to psub
  1448. Revision 1.92 2003/10/29 21:29:14 jonas
  1449. * some ALLOWDUPREG improvements
  1450. Revision 1.91 2003/10/21 15:15:36 peter
  1451. * taicpu_abstract.oper[] changed to pointers
  1452. Revision 1.90 2003/10/19 12:36:36 florian
  1453. * improved speed; reduced memory usage of the interference bitmap
  1454. Revision 1.89 2003/10/19 01:34:30 florian
  1455. * some ppc stuff fixed
  1456. * memory leak fixed
  1457. Revision 1.88 2003/10/18 15:41:26 peter
  1458. * made worklists dynamic in size
  1459. Revision 1.87 2003/10/17 16:16:08 peter
  1460. * fixed last commit
  1461. Revision 1.86 2003/10/17 15:25:18 florian
  1462. * fixed more ppc stuff
  1463. Revision 1.85 2003/10/17 14:38:32 peter
  1464. * 64k registers supported
  1465. * fixed some memory leaks
  1466. Revision 1.84 2003/10/11 16:06:42 florian
  1467. * fixed some MMX<->SSE
  1468. * started to fix ppc, needs an overhaul
  1469. + stabs info improve for spilling, not sure if it works correctly/completly
  1470. - MMX_SUPPORT removed from Makefile.fpc
  1471. Revision 1.83 2003/10/10 17:48:14 peter
  1472. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  1473. * tregisteralloctor renamed to trgobj
  1474. * removed rgobj from a lot of units
  1475. * moved location_* and reference_* to cgobj
  1476. * first things for mmx register allocation
  1477. Revision 1.82 2003/10/09 21:31:37 daniel
  1478. * Register allocator splitted, ans abstract now
  1479. Revision 1.81 2003/10/01 20:34:49 peter
  1480. * procinfo unit contains tprocinfo
  1481. * cginfo renamed to cgbase
  1482. * moved cgmessage to verbose
  1483. * fixed ppc and sparc compiles
  1484. Revision 1.80 2003/09/30 19:54:42 peter
  1485. * reuse registers with the least conflicts
  1486. Revision 1.79 2003/09/29 20:58:56 peter
  1487. * optimized releasing of registers
  1488. Revision 1.78 2003/09/28 13:41:12 peter
  1489. * return reg 255 when allowdupreg is defined
  1490. Revision 1.77 2003/09/25 16:19:32 peter
  1491. * fix filepositions
  1492. * insert spill temp allocations at the start of the proc
  1493. Revision 1.76 2003/09/16 16:17:01 peter
  1494. * varspez in calls to push_addr_param
  1495. Revision 1.75 2003/09/12 19:07:42 daniel
  1496. * Fixed fast spilling functionality by re-adding the code that initializes
  1497. precoloured nodes to degree 255. I would like to play hangman on the one
  1498. who removed that code.
  1499. Revision 1.74 2003/09/11 11:54:59 florian
  1500. * improved arm code generation
  1501. * move some protected and private field around
  1502. * the temp. register for register parameters/arguments are now released
  1503. before the move to the parameter register is done. This improves
  1504. the code in a lot of cases.
  1505. Revision 1.73 2003/09/09 20:59:27 daniel
  1506. * Adding register allocation order
  1507. Revision 1.72 2003/09/09 15:55:44 peter
  1508. * use register with least interferences in spillregister
  1509. Revision 1.71 2003/09/07 22:09:35 peter
  1510. * preparations for different default calling conventions
  1511. * various RA fixes
  1512. Revision 1.70 2003/09/03 21:06:45 peter
  1513. * fixes for FPU register allocation
  1514. Revision 1.69 2003/09/03 15:55:01 peter
  1515. * NEWRA branch merged
  1516. Revision 1.68 2003/09/03 11:18:37 florian
  1517. * fixed arm concatcopy
  1518. + arm support in the common compiler sources added
  1519. * moved some generic cg code around
  1520. + tfputype added
  1521. * ...
  1522. Revision 1.67.2.5 2003/08/31 20:44:07 peter
  1523. * fixed getexplicitregisterint tregister value
  1524. Revision 1.67.2.4 2003/08/31 20:40:50 daniel
  1525. * Fixed add_edges_used
  1526. Revision 1.67.2.3 2003/08/29 17:28:59 peter
  1527. * next batch of updates
  1528. Revision 1.67.2.2 2003/08/28 18:35:08 peter
  1529. * tregister changed to cardinal
  1530. Revision 1.67.2.1 2003/08/27 19:55:54 peter
  1531. * first tregister patch
  1532. Revision 1.67 2003/08/23 10:46:21 daniel
  1533. * Register allocator bugfix for h2pas
  1534. Revision 1.66 2003/08/17 16:59:20 jonas
  1535. * fixed regvars so they work with newra (at least for ppc)
  1536. * fixed some volatile register bugs
  1537. + -dnotranslation option for -dnewra, which causes the registers not to
  1538. be translated from virtual to normal registers. Requires support in
  1539. the assembler writer as well, which is only implemented in aggas/
  1540. agppcgas currently
  1541. Revision 1.65 2003/08/17 14:32:48 daniel
  1542. * Precoloured nodes now have an infinite degree approached with 255,
  1543. like they should.
  1544. Revision 1.64 2003/08/17 08:48:02 daniel
  1545. * Another register allocator bug fixed.
  1546. * usable_registers_cnt set to 6 for i386
  1547. Revision 1.63 2003/08/09 18:56:54 daniel
  1548. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  1549. allocator
  1550. * Some preventive changes to i386 spillinh code
  1551. Revision 1.62 2003/08/03 14:09:50 daniel
  1552. * Fixed a register allocator bug
  1553. * Figured out why -dnewra generates superfluous "mov reg1,reg2"
  1554. statements: changes in location_force. These moves are now no longer
  1555. constrained so they are optimized away.
  1556. Revision 1.61 2003/07/21 13:32:39 jonas
  1557. * add_edges_used() is now also called for registers allocated with
  1558. getexplicitregisterint()
  1559. * writing the intereference graph is now only done with -dradebug2 and
  1560. the created files are now called "igraph.<module_name>"
  1561. Revision 1.60 2003/07/06 15:31:21 daniel
  1562. * Fixed register allocator. *Lots* of fixes.
  1563. Revision 1.59 2003/07/06 15:00:47 jonas
  1564. * fixed my previous completely broken commit. It's not perfect though,
  1565. registers > last_int_supreg and < max_intreg may still be "translated"
  1566. Revision 1.58 2003/07/06 14:45:05 jonas
  1567. * support integer registers that are not managed by newra (ie. don't
  1568. translate register numbers that fall outside the range
  1569. first_int_supreg..last_int_supreg)
  1570. Revision 1.57 2003/07/02 22:18:04 peter
  1571. * paraloc splitted in callerparaloc,calleeparaloc
  1572. * sparc calling convention updates
  1573. Revision 1.56 2003/06/17 16:34:44 jonas
  1574. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  1575. * renamed all_intregisters to volatile_intregisters and made it
  1576. processor dependent
  1577. Revision 1.55 2003/06/14 14:53:50 jonas
  1578. * fixed newra cycle for x86
  1579. * added constants for indicating source and destination operands of the
  1580. "move reg,reg" instruction to aasmcpu (and use those in rgobj)
  1581. Revision 1.54 2003/06/13 21:19:31 peter
  1582. * current_procdef removed, use current_procinfo.procdef instead
  1583. Revision 1.53 2003/06/12 21:11:10 peter
  1584. * ungetregisterfpu gets size parameter
  1585. Revision 1.52 2003/06/12 16:43:07 peter
  1586. * newra compiles for sparc
  1587. Revision 1.51 2003/06/09 14:54:26 jonas
  1588. * (de)allocation of registers for parameters is now performed properly
  1589. (and checked on the ppc)
  1590. - removed obsolete allocation of all parameter registers at the start
  1591. of a procedure (and deallocation at the end)
  1592. Revision 1.50 2003/06/03 21:11:09 peter
  1593. * cg.a_load_* get a from and to size specifier
  1594. * makeregsize only accepts newregister
  1595. * i386 uses generic tcgnotnode,tcgunaryminus
  1596. Revision 1.49 2003/06/03 13:01:59 daniel
  1597. * Register allocator finished
  1598. Revision 1.48 2003/06/01 21:38:06 peter
  1599. * getregisterfpu size parameter added
  1600. * op_const_reg size parameter added
  1601. * sparc updates
  1602. Revision 1.47 2003/05/31 20:31:11 jonas
  1603. * set inital costs of assigning a variable to a register to 120 for
  1604. non-i386, because the used register must be store to memory at the
  1605. start and loaded again at the end
  1606. Revision 1.46 2003/05/30 18:55:21 jonas
  1607. * fixed several regvar related bugs for non-i386. make cycle with -Or now
  1608. works for ppc
  1609. Revision 1.45 2003/05/30 12:36:13 jonas
  1610. * use as little different registers on the ppc until newra is released,
  1611. since every used register must be saved
  1612. Revision 1.44 2003/05/17 13:30:08 jonas
  1613. * changed tt_persistant to tt_persistent :)
  1614. * tempcreatenode now doesn't accept a boolean anymore for persistent
  1615. temps, but a ttemptype, so you can also create ansistring temps etc
  1616. Revision 1.43 2003/05/16 14:33:31 peter
  1617. * regvar fixes
  1618. Revision 1.42 2003/04/26 20:03:49 daniel
  1619. * Bug fix in simplify
  1620. Revision 1.41 2003/04/25 20:59:35 peter
  1621. * removed funcretn,funcretsym, function result is now in varsym
  1622. and aliases for result and function name are added using absolutesym
  1623. * vs_hidden parameter for funcret passed in parameter
  1624. * vs_hidden fixes
  1625. * writenode changed to printnode and released from extdebug
  1626. * -vp option added to generate a tree.log with the nodetree
  1627. * nicer printnode for statements, callnode
  1628. Revision 1.40 2003/04/25 08:25:26 daniel
  1629. * Ifdefs around a lot of calls to cleartempgen
  1630. * Fixed registers that are allocated but not freed in several nodes
  1631. * Tweak to register allocator to cause less spills
  1632. * 8-bit registers now interfere with esi,edi and ebp
  1633. Compiler can now compile rtl successfully when using new register
  1634. allocator
  1635. Revision 1.39 2003/04/23 20:23:06 peter
  1636. * compile fix for no-newra
  1637. Revision 1.38 2003/04/23 14:42:07 daniel
  1638. * Further register allocator work. Compiler now smaller with new
  1639. allocator than without.
  1640. * Somebody forgot to adjust ppu version number
  1641. Revision 1.37 2003/04/22 23:50:23 peter
  1642. * firstpass uses expectloc
  1643. * checks if there are differences between the expectloc and
  1644. location.loc from secondpass in EXTDEBUG
  1645. Revision 1.36 2003/04/22 10:09:35 daniel
  1646. + Implemented the actual register allocator
  1647. + Scratch registers unavailable when new register allocator used
  1648. + maybe_save/maybe_restore unavailable when new register allocator used
  1649. Revision 1.35 2003/04/21 19:16:49 peter
  1650. * count address regs separate
  1651. Revision 1.34 2003/04/17 16:48:21 daniel
  1652. * Added some code to keep track of move instructions in register
  1653. allocator
  1654. Revision 1.33 2003/04/17 07:50:24 daniel
  1655. * Some work on interference graph construction
  1656. Revision 1.32 2003/03/28 19:16:57 peter
  1657. * generic constructor working for i386
  1658. * remove fixed self register
  1659. * esi added as address register for i386
  1660. Revision 1.31 2003/03/11 21:46:24 jonas
  1661. * lots of new regallocator fixes, both in generic and ppc-specific code
  1662. (ppc compiler still can't compile the linux system unit though)
  1663. Revision 1.30 2003/03/09 21:18:59 olle
  1664. + added cutils to the uses clause
  1665. Revision 1.29 2003/03/08 20:36:41 daniel
  1666. + Added newra version of Ti386shlshrnode
  1667. + Added interference graph construction code
  1668. Revision 1.28 2003/03/08 13:59:16 daniel
  1669. * Work to handle new register notation in ag386nsm
  1670. + Added newra version of Ti386moddivnode
  1671. Revision 1.27 2003/03/08 10:53:48 daniel
  1672. * Created newra version of secondmul in n386add.pas
  1673. Revision 1.26 2003/03/08 08:59:07 daniel
  1674. + $define newra will enable new register allocator
  1675. + getregisterint will return imaginary registers with $newra
  1676. + -sr switch added, will skip register allocation so you can see
  1677. the direct output of the code generator before register allocation
  1678. Revision 1.25 2003/02/26 20:50:45 daniel
  1679. * Fixed ungetreference
  1680. Revision 1.24 2003/02/19 22:39:56 daniel
  1681. * Fixed a few issues
  1682. Revision 1.23 2003/02/19 22:00:14 daniel
  1683. * Code generator converted to new register notation
  1684. - Horribily outdated todo.txt removed
  1685. Revision 1.22 2003/02/02 19:25:54 carl
  1686. * Several bugfixes for m68k target (register alloc., opcode emission)
  1687. + VIS target
  1688. + Generic add more complete (still not verified)
  1689. Revision 1.21 2003/01/08 18:43:57 daniel
  1690. * Tregister changed into a record
  1691. Revision 1.20 2002/10/05 12:43:28 carl
  1692. * fixes for Delphi 6 compilation
  1693. (warning : Some features do not work under Delphi)
  1694. Revision 1.19 2002/08/23 16:14:49 peter
  1695. * tempgen cleanup
  1696. * tt_noreuse temp type added that will be used in genentrycode
  1697. Revision 1.18 2002/08/17 22:09:47 florian
  1698. * result type handling in tcgcal.pass_2 overhauled
  1699. * better tnode.dowrite
  1700. * some ppc stuff fixed
  1701. Revision 1.17 2002/08/17 09:23:42 florian
  1702. * first part of procinfo rewrite
  1703. Revision 1.16 2002/08/06 20:55:23 florian
  1704. * first part of ppc calling conventions fix
  1705. Revision 1.15 2002/08/05 18:27:48 carl
  1706. + more more more documentation
  1707. + first version include/exclude (can't test though, not enough scratch for i386 :()...
  1708. Revision 1.14 2002/08/04 19:06:41 carl
  1709. + added generic exception support (still does not work!)
  1710. + more documentation
  1711. Revision 1.13 2002/07/07 09:52:32 florian
  1712. * powerpc target fixed, very simple units can be compiled
  1713. * some basic stuff for better callparanode handling, far from being finished
  1714. Revision 1.12 2002/07/01 18:46:26 peter
  1715. * internal linker
  1716. * reorganized aasm layer
  1717. Revision 1.11 2002/05/18 13:34:17 peter
  1718. * readded missing revisions
  1719. Revision 1.10 2002/05/16 19:46:44 carl
  1720. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1721. + try to fix temp allocation (still in ifdef)
  1722. + generic constructor calls
  1723. + start of tassembler / tmodulebase class cleanup
  1724. Revision 1.8 2002/04/21 15:23:03 carl
  1725. + makeregsize
  1726. + changeregsize is now a local routine
  1727. Revision 1.7 2002/04/20 21:32:25 carl
  1728. + generic FPC_CHECKPOINTER
  1729. + first parameter offset in stack now portable
  1730. * rename some constants
  1731. + move some cpu stuff to other units
  1732. - remove unused constents
  1733. * fix stacksize for some targets
  1734. * fix generic size problems which depend now on EXTEND_SIZE constant
  1735. Revision 1.6 2002/04/15 19:03:31 carl
  1736. + reg2str -> std_reg2str()
  1737. Revision 1.5 2002/04/06 18:13:01 jonas
  1738. * several powerpc-related additions and fixes
  1739. Revision 1.4 2002/04/04 19:06:04 peter
  1740. * removed unused units
  1741. * use tlocation.size in cg.a_*loc*() routines
  1742. Revision 1.3 2002/04/02 17:11:29 peter
  1743. * tlocation,treference update
  1744. * LOC_CONSTANT added for better constant handling
  1745. * secondadd splitted in multiple routines
  1746. * location_force_reg added for loading a location to a register
  1747. of a specified size
  1748. * secondassignment parses now first the right and then the left node
  1749. (this is compatible with Kylix). This saves a lot of push/pop especially
  1750. with string operations
  1751. * adapted some routines to use the new cg methods
  1752. Revision 1.2 2002/04/01 19:24:25 jonas
  1753. * fixed different parameter name in interface and implementation
  1754. declaration of a method (only 1.0.x detected this)
  1755. Revision 1.1 2002/03/31 20:26:36 jonas
  1756. + a_loadfpu_* and a_loadmm_* methods in tcg
  1757. * register allocation is now handled by a class and is mostly processor
  1758. independent (+rgobj.pas and i386/rgcpu.pas)
  1759. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1760. * some small improvements and fixes to the optimizer
  1761. * some register allocation fixes
  1762. * some fpuvaroffset fixes in the unary minus node
  1763. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1764. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1765. also better optimizable)
  1766. * fixed and optimized register saving/restoring for new/dispose nodes
  1767. * LOC_FPU locations now also require their "register" field to be set to
  1768. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1769. - list field removed of the tnode class because it's not used currently
  1770. and can cause hard-to-find bugs
  1771. }