rgobj.pas 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the base class for the register allocator
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {$i fpcdefs.inc}
  18. { Allow duplicate allocations, can be used to get the .s file written }
  19. { $define ALLOWDUPREG}
  20. unit rgobj;
  21. interface
  22. uses
  23. cutils, cpubase,
  24. aasmbase,aasmtai,aasmdata,aasmcpu,
  25. cclasses,globtype,cgbase,cgutils,
  26. cpuinfo
  27. ;
  28. type
  29. {
  30. The interference bitmap contains of 2 layers:
  31. layer 1 - 256*256 blocks with pointers to layer 2 blocks
  32. layer 2 - blocks of 32*256 (32 bytes = 256 bits)
  33. }
  34. Tinterferencebitmap2 = array[byte] of set of byte;
  35. Pinterferencebitmap2 = ^Tinterferencebitmap2;
  36. Tinterferencebitmap1 = array[byte] of Pinterferencebitmap2;
  37. pinterferencebitmap1 = ^tinterferencebitmap1;
  38. Tinterferencebitmap=class
  39. private
  40. maxx1,
  41. maxy1 : byte;
  42. fbitmap : pinterferencebitmap1;
  43. function getbitmap(x,y:tsuperregister):boolean;
  44. procedure setbitmap(x,y:tsuperregister;b:boolean);
  45. public
  46. constructor create;
  47. destructor destroy;override;
  48. property bitmap[x,y:tsuperregister]:boolean read getbitmap write setbitmap;default;
  49. end;
  50. Tmovelistheader=record
  51. count,
  52. maxcount,
  53. sorted_until : cardinal;
  54. end;
  55. Tmovelist=record
  56. header : Tmovelistheader;
  57. data : array[tsuperregister] of Tlinkedlistitem;
  58. end;
  59. Pmovelist=^Tmovelist;
  60. {In the register allocator we keep track of move instructions.
  61. These instructions are moved between five linked lists. There
  62. is also a linked list per register to keep track about the moves
  63. it is associated with. Because we need to determine quickly in
  64. which of the five lists it is we add anu enumeradtion to each
  65. move instruction.}
  66. Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
  67. ms_worklist_moves,ms_active_moves);
  68. Tmoveins=class(Tlinkedlistitem)
  69. moveset:Tmoveset;
  70. x,y:Tsuperregister;
  71. end;
  72. Treginfoflag=(ri_coalesced,ri_selected);
  73. Treginfoflagset=set of Treginfoflag;
  74. Treginfo=record
  75. live_start,
  76. live_end : Tai;
  77. subreg : tsubregister;
  78. alias : Tsuperregister;
  79. { The register allocator assigns each register a colour }
  80. colour : Tsuperregister;
  81. movelist : Pmovelist;
  82. adjlist : Psuperregisterworklist;
  83. degree : TSuperregister;
  84. flags : Treginfoflagset;
  85. end;
  86. Preginfo=^TReginfo;
  87. tspillreginfo = record
  88. spillreg : tregister;
  89. orgreg : tsuperregister;
  90. tempreg : tregister;
  91. regread,regwritten, mustbespilled: boolean;
  92. end;
  93. tspillregsinfo = array[0..2] of tspillreginfo;
  94. Tspill_temp_list=array[tsuperregister] of Treference;
  95. {#------------------------------------------------------------------
  96. This class implements the default register allocator. It is used by the
  97. code generator to allocate and free registers which might be valid
  98. across nodes. It also contains utility routines related to registers.
  99. Some of the methods in this class should be overriden
  100. by cpu-specific implementations.
  101. --------------------------------------------------------------------}
  102. trgobj=class
  103. preserved_by_proc : tcpuregisterset;
  104. used_in_proc : tcpuregisterset;
  105. constructor create(Aregtype:Tregistertype;
  106. Adefaultsub:Tsubregister;
  107. const Ausable:array of tsuperregister;
  108. Afirst_imaginary:Tsuperregister;
  109. Apreserved_by_proc:Tcpuregisterset);
  110. destructor destroy;override;
  111. {# Allocate a register. An internalerror will be generated if there is
  112. no more free registers which can be allocated.}
  113. function getregister(list:TAsmList;subreg:Tsubregister):Tregister;virtual;
  114. {# Get the register specified.}
  115. procedure getcpuregister(list:TAsmList;r:Tregister);virtual;
  116. procedure ungetcpuregister(list:TAsmList;r:Tregister);virtual;
  117. {# Get multiple registers specified.}
  118. procedure alloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
  119. {# Free multiple registers specified.}
  120. procedure dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
  121. function uses_registers:boolean;virtual;
  122. procedure add_reg_instruction(instr:Tai;r:tregister);
  123. procedure add_move_instruction(instr:Taicpu);
  124. {# Do the register allocation.}
  125. procedure do_register_allocation(list:TAsmList;headertai:tai);virtual;
  126. { Adds an interference edge.
  127. don't move this to the protected section, the arm cg requires to access this (FK) }
  128. procedure add_edge(u,v:Tsuperregister);
  129. { translates a single given imaginary register to it's real register }
  130. procedure translate_register(var reg : tregister);
  131. protected
  132. regtype : Tregistertype;
  133. { default subregister used }
  134. defaultsub : tsubregister;
  135. live_registers:Tsuperregisterworklist;
  136. { can be overriden to add cpu specific interferences }
  137. procedure add_cpu_interferences(p : tai);virtual;
  138. procedure add_constraints(reg:Tregister);virtual;
  139. function getregisterinline(list:TAsmList;subreg:Tsubregister):Tregister;
  140. procedure ungetregisterinline(list:TAsmList;r:Tregister);
  141. function get_spill_subreg(r : tregister) : tsubregister;virtual;
  142. function do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;virtual;
  143. procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
  144. procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
  145. function instr_spill_register(list:TAsmList;
  146. instr:taicpu;
  147. const r:Tsuperregisterset;
  148. const spilltemplist:Tspill_temp_list): boolean;virtual;
  149. private
  150. do_extend_live_range_backwards: boolean;
  151. {# First imaginary register.}
  152. first_imaginary : Tsuperregister;
  153. {# Highest register allocated until now.}
  154. reginfo : PReginfo;
  155. maxreginfo,
  156. maxreginfoinc,
  157. maxreg : Tsuperregister;
  158. usable_registers_cnt : word;
  159. usable_registers : array[0..maxcpuregister-1] of tsuperregister;
  160. ibitmap : Tinterferencebitmap;
  161. spillednodes,
  162. simplifyworklist,
  163. freezeworklist,
  164. spillworklist,
  165. coalescednodes,
  166. selectstack : tsuperregisterworklist;
  167. worklist_moves,
  168. active_moves,
  169. frozen_moves,
  170. coalesced_moves,
  171. constrained_moves : Tlinkedlist;
  172. extended_backwards,
  173. backwards_was_first : tsuperregisterset;
  174. {$ifdef EXTDEBUG}
  175. procedure writegraph(loopidx:longint);
  176. {$endif EXTDEBUG}
  177. {# Disposes of the reginfo array.}
  178. procedure dispose_reginfo;
  179. {# Prepare the register colouring.}
  180. procedure prepare_colouring;
  181. {# Clean up after register colouring.}
  182. procedure epilogue_colouring;
  183. {# Colour the registers; that is do the register allocation.}
  184. procedure colour_registers;
  185. procedure insert_regalloc_info(list:TAsmList;u:tsuperregister);
  186. procedure insert_regalloc_info_all(list:TAsmList);
  187. procedure generate_interference_graph(list:TAsmList;headertai:tai);
  188. { translates the registers in the given assembler list }
  189. procedure translate_registers(list:TAsmList);
  190. function spill_registers(list:TAsmList;headertai:tai):boolean;virtual;
  191. function getnewreg(subreg:tsubregister):tsuperregister;
  192. procedure add_edges_used(u:Tsuperregister);
  193. procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
  194. function move_related(n:Tsuperregister):boolean;
  195. procedure make_work_list;
  196. procedure sort_simplify_worklist;
  197. procedure enable_moves(n:Tsuperregister);
  198. procedure decrement_degree(m:Tsuperregister);
  199. procedure simplify;
  200. function get_alias(n:Tsuperregister):Tsuperregister;
  201. procedure add_worklist(u:Tsuperregister);
  202. function adjacent_ok(u,v:Tsuperregister):boolean;
  203. function conservative(u,v:Tsuperregister):boolean;
  204. procedure combine(u,v:Tsuperregister);
  205. procedure coalesce;
  206. procedure freeze_moves(u:Tsuperregister);
  207. procedure freeze;
  208. procedure select_spill;
  209. procedure assign_colours;
  210. procedure clear_interferences(u:Tsuperregister);
  211. procedure set_live_range_backwards(b: boolean);
  212. public
  213. property extend_live_range_backwards: boolean read do_extend_live_range_backwards write set_live_range_backwards;
  214. end;
  215. const
  216. first_reg = 0;
  217. last_reg = high(tsuperregister)-1;
  218. maxspillingcounter = 20;
  219. implementation
  220. uses
  221. systems,
  222. globals,verbose,tgobj,procinfo;
  223. procedure sort_movelist(ml:Pmovelist);
  224. {Ok, sorting pointers is silly, but it does the job to make Trgobj.combine
  225. faster.}
  226. var h,i,p:word;
  227. t:Tlinkedlistitem;
  228. begin
  229. with ml^ do
  230. begin
  231. if header.count<2 then
  232. exit;
  233. p:=1;
  234. while 2*p<header.count do
  235. p:=2*p;
  236. while p<>0 do
  237. begin
  238. for h:=p to header.count-1 do
  239. begin
  240. i:=h;
  241. t:=data[i];
  242. repeat
  243. if ptrint(data[i-p])<=ptrint(t) then
  244. break;
  245. data[i]:=data[i-p];
  246. dec(i,p);
  247. until i<p;
  248. data[i]:=t;
  249. end;
  250. p:=p shr 1;
  251. end;
  252. header.sorted_until:=header.count-1;
  253. end;
  254. end;
  255. {******************************************************************************
  256. tinterferencebitmap
  257. ******************************************************************************}
  258. constructor tinterferencebitmap.create;
  259. begin
  260. inherited create;
  261. maxx1:=1;
  262. getmem(fbitmap,sizeof(tinterferencebitmap1)*2);
  263. fillchar(fbitmap^,sizeof(tinterferencebitmap1)*2,0);
  264. end;
  265. destructor tinterferencebitmap.destroy;
  266. var i,j:byte;
  267. begin
  268. for i:=0 to maxx1 do
  269. for j:=0 to maxy1 do
  270. if assigned(fbitmap[i,j]) then
  271. dispose(fbitmap[i,j]);
  272. freemem(fbitmap);
  273. end;
  274. function tinterferencebitmap.getbitmap(x,y:tsuperregister):boolean;
  275. var
  276. page : pinterferencebitmap2;
  277. begin
  278. result:=false;
  279. if (x shr 8>maxx1) then
  280. exit;
  281. page:=fbitmap[x shr 8,y shr 8];
  282. result:=assigned(page) and
  283. ((x and $ff) in page^[y and $ff]);
  284. end;
  285. procedure tinterferencebitmap.setbitmap(x,y:tsuperregister;b:boolean);
  286. var
  287. x1,y1 : byte;
  288. begin
  289. x1:=x shr 8;
  290. y1:=y shr 8;
  291. if x1>maxx1 then
  292. begin
  293. reallocmem(fbitmap,sizeof(tinterferencebitmap1)*(x1+1));
  294. fillchar(fbitmap[maxx1+1],sizeof(tinterferencebitmap1)*(x1-maxx1),0);
  295. maxx1:=x1;
  296. end;
  297. if not assigned(fbitmap[x1,y1]) then
  298. begin
  299. if y1>maxy1 then
  300. maxy1:=y1;
  301. new(fbitmap[x1,y1]);
  302. fillchar(fbitmap[x1,y1]^,sizeof(tinterferencebitmap2),0);
  303. end;
  304. if b then
  305. include(fbitmap[x1,y1]^[y and $ff],(x and $ff))
  306. else
  307. exclude(fbitmap[x1,y1]^[y and $ff],(x and $ff));
  308. end;
  309. {******************************************************************************
  310. trgobj
  311. ******************************************************************************}
  312. constructor trgobj.create(Aregtype:Tregistertype;
  313. Adefaultsub:Tsubregister;
  314. const Ausable:array of tsuperregister;
  315. Afirst_imaginary:Tsuperregister;
  316. Apreserved_by_proc:Tcpuregisterset);
  317. var
  318. i : Tsuperregister;
  319. begin
  320. { empty super register sets can cause very strange problems }
  321. if high(Ausable)=0 then
  322. internalerror(200210181);
  323. extend_live_range_backwards := false;
  324. first_imaginary:=Afirst_imaginary;
  325. maxreg:=Afirst_imaginary;
  326. regtype:=Aregtype;
  327. defaultsub:=Adefaultsub;
  328. preserved_by_proc:=Apreserved_by_proc;
  329. used_in_proc:=[];
  330. live_registers.init;
  331. { Get reginfo for CPU registers }
  332. maxreginfo:=first_imaginary;
  333. maxreginfoinc:=16;
  334. worklist_moves:=Tlinkedlist.create;
  335. reginfo:=allocmem(first_imaginary*sizeof(treginfo));
  336. for i:=0 to first_imaginary-1 do
  337. begin
  338. reginfo[i].degree:=high(tsuperregister);
  339. reginfo[i].alias:=RS_INVALID;
  340. end;
  341. { Usable registers }
  342. fillchar(usable_registers,sizeof(usable_registers),0);
  343. for i:=low(Ausable) to high(Ausable) do
  344. usable_registers[i]:=Ausable[i];
  345. usable_registers_cnt:=high(Ausable)+1;
  346. { Initialize Worklists }
  347. spillednodes.init;
  348. simplifyworklist.init;
  349. freezeworklist.init;
  350. spillworklist.init;
  351. coalescednodes.init;
  352. selectstack.init;
  353. end;
  354. destructor trgobj.destroy;
  355. begin
  356. spillednodes.done;
  357. simplifyworklist.done;
  358. freezeworklist.done;
  359. spillworklist.done;
  360. coalescednodes.done;
  361. selectstack.done;
  362. live_registers.done;
  363. worklist_moves.free;
  364. dispose_reginfo;
  365. end;
  366. procedure Trgobj.dispose_reginfo;
  367. var i:Tsuperregister;
  368. begin
  369. if reginfo<>nil then
  370. begin
  371. for i:=0 to maxreg-1 do
  372. with reginfo[i] do
  373. begin
  374. if adjlist<>nil then
  375. dispose(adjlist,done);
  376. if movelist<>nil then
  377. dispose(movelist);
  378. end;
  379. freemem(reginfo);
  380. reginfo:=nil;
  381. end;
  382. end;
  383. function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
  384. var
  385. oldmaxreginfo : tsuperregister;
  386. begin
  387. result:=maxreg;
  388. inc(maxreg);
  389. if maxreg>=last_reg then
  390. Message(parser_f_too_complex_proc);
  391. if maxreg>=maxreginfo then
  392. begin
  393. oldmaxreginfo:=maxreginfo;
  394. { Prevent overflow }
  395. if maxreginfoinc>last_reg-maxreginfo then
  396. maxreginfo:=last_reg
  397. else
  398. begin
  399. inc(maxreginfo,maxreginfoinc);
  400. if maxreginfoinc<256 then
  401. maxreginfoinc:=maxreginfoinc*2;
  402. end;
  403. reallocmem(reginfo,maxreginfo*sizeof(treginfo));
  404. { Do we really need it to clear it ? At least for 1.0.x (PFV) }
  405. fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
  406. end;
  407. reginfo[result].subreg:=subreg;
  408. end;
  409. function trgobj.getregister(list:TAsmList;subreg:Tsubregister):Tregister;
  410. begin
  411. {$ifdef EXTDEBUG}
  412. if reginfo=nil then
  413. InternalError(2004020901);
  414. {$endif EXTDEBUG}
  415. if defaultsub=R_SUBNONE then
  416. result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
  417. else
  418. result:=newreg(regtype,getnewreg(subreg),subreg);
  419. end;
  420. function trgobj.uses_registers:boolean;
  421. begin
  422. result:=(maxreg>first_imaginary);
  423. end;
  424. procedure trgobj.ungetcpuregister(list:TAsmList;r:Tregister);
  425. begin
  426. if (getsupreg(r)>=first_imaginary) then
  427. InternalError(2004020901);
  428. list.concat(Tai_regalloc.dealloc(r,nil));
  429. end;
  430. procedure trgobj.getcpuregister(list:TAsmList;r:Tregister);
  431. var
  432. supreg:Tsuperregister;
  433. begin
  434. supreg:=getsupreg(r);
  435. if supreg>=first_imaginary then
  436. internalerror(2003121503);
  437. include(used_in_proc,supreg);
  438. list.concat(Tai_regalloc.alloc(r,nil));
  439. end;
  440. procedure trgobj.alloccpuregisters(list:TAsmList;const r:Tcpuregisterset);
  441. var i:Tsuperregister;
  442. begin
  443. for i:=0 to first_imaginary-1 do
  444. if i in r then
  445. getcpuregister(list,newreg(regtype,i,defaultsub));
  446. end;
  447. procedure trgobj.dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);
  448. var i:Tsuperregister;
  449. begin
  450. for i:=0 to first_imaginary-1 do
  451. if i in r then
  452. ungetcpuregister(list,newreg(regtype,i,defaultsub));
  453. end;
  454. procedure trgobj.do_register_allocation(list:TAsmList;headertai:tai);
  455. var
  456. spillingcounter:byte;
  457. endspill:boolean;
  458. begin
  459. { Insert regalloc info for imaginary registers }
  460. insert_regalloc_info_all(list);
  461. ibitmap:=tinterferencebitmap.create;
  462. generate_interference_graph(list,headertai);
  463. { Don't do the real allocation when -sr is passed }
  464. if (cs_no_regalloc in aktglobalswitches) then
  465. exit;
  466. {Do register allocation.}
  467. spillingcounter:=0;
  468. repeat
  469. prepare_colouring;
  470. colour_registers;
  471. epilogue_colouring;
  472. endspill:=true;
  473. if spillednodes.length<>0 then
  474. begin
  475. inc(spillingcounter);
  476. if spillingcounter>maxspillingcounter then
  477. begin
  478. {$ifdef EXTDEBUG}
  479. { Only exit here so the .s file is still generated. Assembling
  480. the file will still trigger an error }
  481. exit;
  482. {$else}
  483. internalerror(200309041);
  484. {$endif}
  485. end;
  486. endspill:=not spill_registers(list,headertai);
  487. end;
  488. until endspill;
  489. ibitmap.free;
  490. translate_registers(list);
  491. { we need the translation table for debugging info and verbose assembler output (FK)
  492. dispose_reginfo;
  493. }
  494. end;
  495. procedure trgobj.add_constraints(reg:Tregister);
  496. begin
  497. end;
  498. procedure trgobj.add_edge(u,v:Tsuperregister);
  499. {This procedure will add an edge to the virtual interference graph.}
  500. procedure addadj(u,v:Tsuperregister);
  501. begin
  502. with reginfo[u] do
  503. begin
  504. if adjlist=nil then
  505. new(adjlist,init);
  506. adjlist^.add(v);
  507. end;
  508. end;
  509. begin
  510. if (u<>v) and not(ibitmap[v,u]) then
  511. begin
  512. ibitmap[v,u]:=true;
  513. ibitmap[u,v]:=true;
  514. {Precoloured nodes are not stored in the interference graph.}
  515. if (u>=first_imaginary) then
  516. addadj(u,v);
  517. if (v>=first_imaginary) then
  518. addadj(v,u);
  519. end;
  520. end;
  521. procedure trgobj.add_edges_used(u:Tsuperregister);
  522. var i:word;
  523. begin
  524. with live_registers do
  525. if length>0 then
  526. for i:=0 to length-1 do
  527. add_edge(u,get_alias(buf^[i]));
  528. end;
  529. {$ifdef EXTDEBUG}
  530. procedure trgobj.writegraph(loopidx:longint);
  531. {This procedure writes out the current interference graph in the
  532. register allocator.}
  533. var f:text;
  534. i,j:Tsuperregister;
  535. begin
  536. assign(f,'igraph'+tostr(loopidx));
  537. rewrite(f);
  538. writeln(f,'Interference graph');
  539. writeln(f);
  540. write(f,' ');
  541. for i:=0 to 15 do
  542. for j:=0 to 15 do
  543. write(f,hexstr(i,1));
  544. writeln(f);
  545. write(f,' ');
  546. for i:=0 to 15 do
  547. write(f,'0123456789ABCDEF');
  548. writeln(f);
  549. for i:=0 to maxreg-1 do
  550. begin
  551. write(f,hexstr(i,2):4);
  552. for j:=0 to maxreg-1 do
  553. if ibitmap[i,j] then
  554. write(f,'*')
  555. else
  556. write(f,'-');
  557. writeln(f);
  558. end;
  559. close(f);
  560. end;
  561. {$endif EXTDEBUG}
  562. procedure trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
  563. begin
  564. with reginfo[u] do
  565. begin
  566. if movelist=nil then
  567. begin
  568. getmem(movelist,sizeof(tmovelistheader)+60*sizeof(pointer));
  569. movelist^.header.maxcount:=60;
  570. movelist^.header.count:=0;
  571. movelist^.header.sorted_until:=0;
  572. end
  573. else
  574. begin
  575. if movelist^.header.count>=movelist^.header.maxcount then
  576. begin
  577. movelist^.header.maxcount:=movelist^.header.maxcount*2;
  578. reallocmem(movelist,sizeof(tmovelistheader)+movelist^.header.maxcount*sizeof(pointer));
  579. end;
  580. end;
  581. movelist^.data[movelist^.header.count]:=data;
  582. inc(movelist^.header.count);
  583. end;
  584. end;
  585. procedure trgobj.set_live_range_backwards(b: boolean);
  586. begin
  587. if (b) then
  588. begin
  589. { new registers may be allocated }
  590. supregset_reset(extended_backwards,false,high(tsuperregister));
  591. supregset_reset(backwards_was_first,false,high(tsuperregister));
  592. do_extend_live_range_backwards := true;
  593. end
  594. else
  595. do_extend_live_range_backwards := false;
  596. end;
  597. procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
  598. var
  599. supreg : tsuperregister;
  600. begin
  601. supreg:=getsupreg(r);
  602. {$ifdef extdebug}
  603. if supreg>=maxreginfo then
  604. internalerror(200411061);
  605. {$endif extdebug}
  606. if supreg>=first_imaginary then
  607. with reginfo[supreg] do
  608. begin
  609. if not(extend_live_range_backwards) then
  610. begin
  611. if not assigned(live_start) then
  612. live_start:=instr;
  613. live_end:=instr;
  614. end
  615. else
  616. begin
  617. if not supregset_in(extended_backwards,supreg) then
  618. begin
  619. supregset_include(extended_backwards,supreg);
  620. live_start := instr;
  621. if not assigned(live_end) then
  622. begin
  623. supregset_include(backwards_was_first,supreg);
  624. live_end := instr;
  625. end;
  626. end
  627. else
  628. begin
  629. if supregset_in(backwards_was_first,supreg) then
  630. live_end := instr;
  631. end
  632. end
  633. end;
  634. end;
  635. procedure trgobj.add_move_instruction(instr:Taicpu);
  636. {This procedure notifies a certain as a move instruction so the
  637. register allocator can try to eliminate it.}
  638. var i:Tmoveins;
  639. ssupreg,dsupreg:Tsuperregister;
  640. begin
  641. {$ifdef extdebug}
  642. if (instr.oper[O_MOV_SOURCE]^.typ<>top_reg) or
  643. (instr.oper[O_MOV_DEST]^.typ<>top_reg) then
  644. internalerror(200311291);
  645. {$endif}
  646. i:=Tmoveins.create;
  647. i.moveset:=ms_worklist_moves;
  648. worklist_moves.insert(i);
  649. ssupreg:=getsupreg(instr.oper[O_MOV_SOURCE]^.reg);
  650. add_to_movelist(ssupreg,i);
  651. dsupreg:=getsupreg(instr.oper[O_MOV_DEST]^.reg);
  652. if ssupreg<>dsupreg then
  653. {Avoid adding the same move instruction twice to a single register.}
  654. add_to_movelist(dsupreg,i);
  655. i.x:=ssupreg;
  656. i.y:=dsupreg;
  657. end;
  658. function trgobj.move_related(n:Tsuperregister):boolean;
  659. var i:cardinal;
  660. begin
  661. move_related:=false;
  662. with reginfo[n] do
  663. if movelist<>nil then
  664. with movelist^ do
  665. for i:=0 to header.count-1 do
  666. if Tmoveins(data[i]).moveset in [ms_worklist_moves,ms_active_moves] then
  667. begin
  668. move_related:=true;
  669. break;
  670. end;
  671. end;
  672. procedure Trgobj.sort_simplify_worklist;
  673. {Sorts the simplifyworklist by the number of interferences the
  674. registers in it cause. This allows simplify to execute in
  675. constant time.}
  676. var p,h,i,leni,lent:word;
  677. t:Tsuperregister;
  678. adji,adjt:Psuperregisterworklist;
  679. begin
  680. with simplifyworklist do
  681. begin
  682. if length<2 then
  683. exit;
  684. p:=1;
  685. while 2*p<length do
  686. p:=2*p;
  687. while p<>0 do
  688. begin
  689. for h:=p to length-1 do
  690. begin
  691. i:=h;
  692. t:=buf^[i];
  693. adjt:=reginfo[buf^[i]].adjlist;
  694. lent:=0;
  695. if adjt<>nil then
  696. lent:=adjt^.length;
  697. repeat
  698. adji:=reginfo[buf^[i-p]].adjlist;
  699. leni:=0;
  700. if adji<>nil then
  701. leni:=adji^.length;
  702. if leni<=lent then
  703. break;
  704. buf^[i]:=buf^[i-p];
  705. dec(i,p)
  706. until i<p;
  707. buf^[i]:=t;
  708. end;
  709. p:=p shr 1;
  710. end;
  711. end;
  712. end;
  713. procedure trgobj.make_work_list;
  714. var n:Tsuperregister;
  715. begin
  716. {If we have 7 cpu registers, and the degree of a node is 7, we cannot
  717. assign it to any of the registers, thus it is significant.}
  718. for n:=first_imaginary to maxreg-1 do
  719. with reginfo[n] do
  720. begin
  721. if adjlist=nil then
  722. degree:=0
  723. else
  724. degree:=adjlist^.length;
  725. if degree>=usable_registers_cnt then
  726. spillworklist.add(n)
  727. else if move_related(n) then
  728. freezeworklist.add(n)
  729. else
  730. simplifyworklist.add(n);
  731. end;
  732. sort_simplify_worklist;
  733. end;
  734. procedure trgobj.prepare_colouring;
  735. begin
  736. make_work_list;
  737. active_moves:=Tlinkedlist.create;
  738. frozen_moves:=Tlinkedlist.create;
  739. coalesced_moves:=Tlinkedlist.create;
  740. constrained_moves:=Tlinkedlist.create;
  741. selectstack.clear;
  742. end;
  743. procedure trgobj.enable_moves(n:Tsuperregister);
  744. var m:Tlinkedlistitem;
  745. i:cardinal;
  746. begin
  747. with reginfo[n] do
  748. if movelist<>nil then
  749. for i:=0 to movelist^.header.count-1 do
  750. begin
  751. m:=movelist^.data[i];
  752. if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
  753. if Tmoveins(m).moveset=ms_active_moves then
  754. begin
  755. {Move m from the set active_moves to the set worklist_moves.}
  756. active_moves.remove(m);
  757. Tmoveins(m).moveset:=ms_worklist_moves;
  758. worklist_moves.concat(m);
  759. end;
  760. end;
  761. end;
  762. procedure Trgobj.decrement_degree(m:Tsuperregister);
  763. var adj : Psuperregisterworklist;
  764. n : tsuperregister;
  765. d,i : word;
  766. begin
  767. with reginfo[m] do
  768. begin
  769. d:=degree;
  770. if d=0 then
  771. internalerror(200312151);
  772. dec(degree);
  773. if d=usable_registers_cnt then
  774. begin
  775. {Enable moves for m.}
  776. enable_moves(m);
  777. {Enable moves for adjacent.}
  778. adj:=adjlist;
  779. if adj<>nil then
  780. for i:=1 to adj^.length do
  781. begin
  782. n:=adj^.buf^[i-1];
  783. if reginfo[n].flags*[ri_selected,ri_coalesced]<>[] then
  784. enable_moves(n);
  785. end;
  786. {Remove the node from the spillworklist.}
  787. if not spillworklist.delete(m) then
  788. internalerror(200310145);
  789. if move_related(m) then
  790. freezeworklist.add(m)
  791. else
  792. simplifyworklist.add(m);
  793. end;
  794. end;
  795. end;
  796. procedure trgobj.simplify;
  797. var adj : Psuperregisterworklist;
  798. m,n : Tsuperregister;
  799. i : word;
  800. begin
  801. {We take the element with the least interferences out of the
  802. simplifyworklist. Since the simplifyworklist is now sorted, we
  803. no longer need to search, but we can simply take the first element.}
  804. m:=simplifyworklist.get;
  805. {Push it on the selectstack.}
  806. selectstack.add(m);
  807. with reginfo[m] do
  808. begin
  809. include(flags,ri_selected);
  810. adj:=adjlist;
  811. end;
  812. if adj<>nil then
  813. for i:=1 to adj^.length do
  814. begin
  815. n:=adj^.buf^[i-1];
  816. if (n>=first_imaginary) and
  817. (reginfo[n].flags*[ri_selected,ri_coalesced]=[]) then
  818. decrement_degree(n);
  819. end;
  820. end;
  821. function trgobj.get_alias(n:Tsuperregister):Tsuperregister;
  822. begin
  823. while ri_coalesced in reginfo[n].flags do
  824. n:=reginfo[n].alias;
  825. get_alias:=n;
  826. end;
  827. procedure trgobj.add_worklist(u:Tsuperregister);
  828. begin
  829. if (u>=first_imaginary) and
  830. (not move_related(u)) and
  831. (reginfo[u].degree<usable_registers_cnt) then
  832. begin
  833. if not freezeworklist.delete(u) then
  834. internalerror(200308161); {must be found}
  835. simplifyworklist.add(u);
  836. end;
  837. end;
  838. function trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
  839. {Check wether u and v should be coalesced. u is precoloured.}
  840. function ok(t,r:Tsuperregister):boolean;
  841. begin
  842. ok:=(t<first_imaginary) or
  843. (reginfo[t].degree<usable_registers_cnt) or
  844. ibitmap[r,t];
  845. end;
  846. var adj : Psuperregisterworklist;
  847. i : word;
  848. n : tsuperregister;
  849. begin
  850. with reginfo[v] do
  851. begin
  852. adjacent_ok:=true;
  853. adj:=adjlist;
  854. if adj<>nil then
  855. for i:=1 to adj^.length do
  856. begin
  857. n:=adj^.buf^[i-1];
  858. if (flags*[ri_coalesced,ri_selected]=[]) and not ok(n,u) then
  859. begin
  860. adjacent_ok:=false;
  861. break;
  862. end;
  863. end;
  864. end;
  865. end;
  866. function trgobj.conservative(u,v:Tsuperregister):boolean;
  867. var adj : Psuperregisterworklist;
  868. done : Tsuperregisterset; {To prevent that we count nodes twice.}
  869. i,k:word;
  870. n : tsuperregister;
  871. begin
  872. k:=0;
  873. supregset_reset(done,false,maxreg);
  874. with reginfo[u] do
  875. begin
  876. adj:=adjlist;
  877. if adj<>nil then
  878. for i:=1 to adj^.length do
  879. begin
  880. n:=adj^.buf^[i-1];
  881. if flags*[ri_coalesced,ri_selected]=[] then
  882. begin
  883. supregset_include(done,n);
  884. if reginfo[n].degree>=usable_registers_cnt then
  885. inc(k);
  886. end;
  887. end;
  888. end;
  889. adj:=reginfo[v].adjlist;
  890. if adj<>nil then
  891. for i:=1 to adj^.length do
  892. begin
  893. n:=adj^.buf^[i-1];
  894. if not supregset_in(done,n) and
  895. (reginfo[n].degree>=usable_registers_cnt) and
  896. (reginfo[u].flags*[ri_coalesced,ri_selected]=[]) then
  897. inc(k);
  898. end;
  899. conservative:=(k<usable_registers_cnt);
  900. end;
  901. procedure trgobj.combine(u,v:Tsuperregister);
  902. var adj : Psuperregisterworklist;
  903. i,n,p,q:cardinal;
  904. t : tsuperregister;
  905. searched:Tlinkedlistitem;
  906. label l1;
  907. begin
  908. if not freezeworklist.delete(v) then
  909. spillworklist.delete(v);
  910. coalescednodes.add(v);
  911. include(reginfo[v].flags,ri_coalesced);
  912. reginfo[v].alias:=u;
  913. {Combine both movelists. Since the movelists are sets, only add
  914. elements that are not already present. The movelists cannot be
  915. empty by definition; nodes are only coalesced if there is a move
  916. between them. To prevent quadratic time blowup (movelists of
  917. especially machine registers can get very large because of moves
  918. generated during calls) we need to go into disgusting complexity.
  919. (See webtbs/tw2242 for an example that stresses this.)
  920. We want to sort the movelist to be able to search logarithmically.
  921. Unfortunately, sorting the movelist every time before searching
  922. is counter-productive, since the movelist usually grows with a few
  923. items at a time. Therefore, we split the movelist into a sorted
  924. and an unsorted part and search through both. If the unsorted part
  925. becomes too large, we sort.}
  926. if assigned(reginfo[u].movelist) then
  927. begin
  928. {We have to weigh the cost of sorting the list against searching
  929. the cost of the unsorted part. I use factor of 8 here; if the
  930. number of items is less than 8 times the numer of unsorted items,
  931. we'll sort the list.}
  932. with reginfo[u].movelist^ do
  933. if header.count<8*(header.count-header.sorted_until) then
  934. sort_movelist(reginfo[u].movelist);
  935. if assigned(reginfo[v].movelist) then
  936. begin
  937. for n:=0 to reginfo[v].movelist^.header.count-1 do
  938. begin
  939. {Binary search the sorted part of the list.}
  940. searched:=reginfo[v].movelist^.data[n];
  941. p:=0;
  942. q:=reginfo[u].movelist^.header.sorted_until;
  943. i:=0;
  944. if q<>0 then
  945. repeat
  946. i:=(p+q) shr 1;
  947. if ptrint(searched)>ptrint(reginfo[u].movelist^.data[i]) then
  948. p:=i+1
  949. else
  950. q:=i;
  951. until p=q;
  952. with reginfo[u].movelist^ do
  953. if searched<>data[i] then
  954. begin
  955. {Linear search the unsorted part of the list.}
  956. for i:=header.sorted_until+1 to header.count-1 do
  957. if searched=data[i] then
  958. goto l1;
  959. {Not found -> add}
  960. add_to_movelist(u,searched);
  961. l1:
  962. end;
  963. end;
  964. end;
  965. end;
  966. enable_moves(v);
  967. adj:=reginfo[v].adjlist;
  968. if adj<>nil then
  969. for i:=1 to adj^.length do
  970. begin
  971. t:=adj^.buf^[i-1];
  972. with reginfo[t] do
  973. if not(ri_coalesced in flags) then
  974. begin
  975. {t has a connection to v. Since we are adding v to u, we
  976. need to connect t to u. However, beware if t was already
  977. connected to u...}
  978. if (ibitmap[t,u]) and not (ri_selected in flags) then
  979. {... because in that case, we are actually removing an edge
  980. and the degree of t decreases.}
  981. decrement_degree(t)
  982. else
  983. begin
  984. add_edge(t,u);
  985. {We have added an edge to t and u. So their degree increases.
  986. However, v is added to u. That means its neighbours will
  987. no longer point to v, but to u instead. Therefore, only the
  988. degree of u increases.}
  989. if (u>=first_imaginary) and not (ri_selected in flags) then
  990. inc(reginfo[u].degree);
  991. end;
  992. end;
  993. end;
  994. if (reginfo[u].degree>=usable_registers_cnt) and freezeworklist.delete(u) then
  995. spillworklist.add(u);
  996. end;
  997. procedure trgobj.coalesce;
  998. var m:Tmoveins;
  999. x,y,u,v:Tsuperregister;
  1000. begin
  1001. m:=Tmoveins(worklist_moves.getfirst);
  1002. x:=get_alias(m.x);
  1003. y:=get_alias(m.y);
  1004. if (y<first_imaginary) then
  1005. begin
  1006. u:=y;
  1007. v:=x;
  1008. end
  1009. else
  1010. begin
  1011. u:=x;
  1012. v:=y;
  1013. end;
  1014. if (u=v) then
  1015. begin
  1016. m.moveset:=ms_coalesced_moves; {Already coalesced.}
  1017. coalesced_moves.insert(m);
  1018. add_worklist(u);
  1019. end
  1020. {Do u and v interfere? In that case the move is constrained. Two
  1021. precoloured nodes interfere allways. If v is precoloured, by the above
  1022. code u is precoloured, thus interference...}
  1023. else if (v<first_imaginary) or ibitmap[u,v] then
  1024. begin
  1025. m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
  1026. constrained_moves.insert(m);
  1027. add_worklist(u);
  1028. add_worklist(v);
  1029. end
  1030. {Next test: is it possible and a good idea to coalesce??}
  1031. else if ((u<first_imaginary) and adjacent_ok(u,v)) or
  1032. ((u>=first_imaginary) and conservative(u,v)) then
  1033. begin
  1034. m.moveset:=ms_coalesced_moves; {Move coalesced!}
  1035. coalesced_moves.insert(m);
  1036. combine(u,v);
  1037. add_worklist(u);
  1038. end
  1039. else
  1040. begin
  1041. m.moveset:=ms_active_moves;
  1042. active_moves.insert(m);
  1043. end;
  1044. end;
  1045. procedure trgobj.freeze_moves(u:Tsuperregister);
  1046. var i:cardinal;
  1047. m:Tlinkedlistitem;
  1048. v,x,y:Tsuperregister;
  1049. begin
  1050. if reginfo[u].movelist<>nil then
  1051. for i:=0 to reginfo[u].movelist^.header.count-1 do
  1052. begin
  1053. m:=reginfo[u].movelist^.data[i];
  1054. if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
  1055. begin
  1056. x:=Tmoveins(m).x;
  1057. y:=Tmoveins(m).y;
  1058. if get_alias(y)=get_alias(u) then
  1059. v:=get_alias(x)
  1060. else
  1061. v:=get_alias(y);
  1062. {Move m from active_moves/worklist_moves to frozen_moves.}
  1063. if Tmoveins(m).moveset=ms_active_moves then
  1064. active_moves.remove(m)
  1065. else
  1066. worklist_moves.remove(m);
  1067. Tmoveins(m).moveset:=ms_frozen_moves;
  1068. frozen_moves.insert(m);
  1069. if (v>=first_imaginary) and not(move_related(v)) and
  1070. (reginfo[v].degree<usable_registers_cnt) then
  1071. begin
  1072. freezeworklist.delete(v);
  1073. simplifyworklist.add(v);
  1074. end;
  1075. end;
  1076. end;
  1077. end;
  1078. procedure trgobj.freeze;
  1079. var n:Tsuperregister;
  1080. begin
  1081. { We need to take a random element out of the freezeworklist. We take
  1082. the last element. Dirty code! }
  1083. n:=freezeworklist.get;
  1084. {Add it to the simplifyworklist.}
  1085. simplifyworklist.add(n);
  1086. freeze_moves(n);
  1087. end;
  1088. procedure trgobj.select_spill;
  1089. var
  1090. n : tsuperregister;
  1091. adj : psuperregisterworklist;
  1092. max,p,i:word;
  1093. begin
  1094. { We must look for the element with the most interferences in the
  1095. spillworklist. This is required because those registers are creating
  1096. the most conflicts and keeping them in a register will not reduce the
  1097. complexity and even can cause the help registers for the spilling code
  1098. to get too much conflicts with the result that the spilling code
  1099. will never converge (PFV) }
  1100. max:=0;
  1101. p:=0;
  1102. with spillworklist do
  1103. begin
  1104. {Safe: This procedure is only called if length<>0}
  1105. for i:=0 to length-1 do
  1106. begin
  1107. adj:=reginfo[buf^[i]].adjlist;
  1108. if assigned(adj) and (adj^.length>max) then
  1109. begin
  1110. p:=i;
  1111. max:=adj^.length;
  1112. end;
  1113. end;
  1114. n:=buf^[p];
  1115. deleteidx(p);
  1116. end;
  1117. simplifyworklist.add(n);
  1118. freeze_moves(n);
  1119. end;
  1120. procedure trgobj.assign_colours;
  1121. {Assign_colours assigns the actual colours to the registers.}
  1122. var adj : Psuperregisterworklist;
  1123. i,j,k : word;
  1124. n,a,c : Tsuperregister;
  1125. colourednodes : Tsuperregisterset;
  1126. adj_colours:set of 0..255;
  1127. found : boolean;
  1128. begin
  1129. spillednodes.clear;
  1130. {Reset colours}
  1131. for n:=0 to maxreg-1 do
  1132. reginfo[n].colour:=n;
  1133. {Colour the cpu registers...}
  1134. supregset_reset(colourednodes,false,maxreg);
  1135. for n:=0 to first_imaginary-1 do
  1136. supregset_include(colourednodes,n);
  1137. {Now colour the imaginary registers on the select-stack.}
  1138. for i:=selectstack.length downto 1 do
  1139. begin
  1140. n:=selectstack.buf^[i-1];
  1141. {Create a list of colours that we cannot assign to n.}
  1142. adj_colours:=[];
  1143. adj:=reginfo[n].adjlist;
  1144. if adj<>nil then
  1145. for j:=0 to adj^.length-1 do
  1146. begin
  1147. a:=get_alias(adj^.buf^[j]);
  1148. if supregset_in(colourednodes,a) and (reginfo[a].colour<=255) then
  1149. include(adj_colours,reginfo[a].colour);
  1150. end;
  1151. if regtype=R_INTREGISTER then
  1152. include(adj_colours,RS_STACK_POINTER_REG);
  1153. {Assume a spill by default...}
  1154. found:=false;
  1155. {Search for a colour not in this list.}
  1156. for k:=0 to usable_registers_cnt-1 do
  1157. begin
  1158. c:=usable_registers[k];
  1159. if not(c in adj_colours) then
  1160. begin
  1161. reginfo[n].colour:=c;
  1162. found:=true;
  1163. supregset_include(colourednodes,n);
  1164. include(used_in_proc,c);
  1165. break;
  1166. end;
  1167. end;
  1168. if not found then
  1169. spillednodes.add(n);
  1170. end;
  1171. {Finally colour the nodes that were coalesced.}
  1172. for i:=1 to coalescednodes.length do
  1173. begin
  1174. n:=coalescednodes.buf^[i-1];
  1175. k:=get_alias(n);
  1176. reginfo[n].colour:=reginfo[k].colour;
  1177. if reginfo[k].colour<maxcpuregister then
  1178. include(used_in_proc,reginfo[k].colour);
  1179. end;
  1180. end;
  1181. procedure trgobj.colour_registers;
  1182. begin
  1183. repeat
  1184. if simplifyworklist.length<>0 then
  1185. simplify
  1186. else if not(worklist_moves.empty) then
  1187. coalesce
  1188. else if freezeworklist.length<>0 then
  1189. freeze
  1190. else if spillworklist.length<>0 then
  1191. select_spill;
  1192. until (simplifyworklist.length=0) and
  1193. worklist_moves.empty and
  1194. (freezeworklist.length=0) and
  1195. (spillworklist.length=0);
  1196. assign_colours;
  1197. end;
  1198. procedure trgobj.epilogue_colouring;
  1199. var
  1200. i : Tsuperregister;
  1201. begin
  1202. worklist_moves.clear;
  1203. active_moves.destroy;
  1204. active_moves:=nil;
  1205. frozen_moves.destroy;
  1206. frozen_moves:=nil;
  1207. coalesced_moves.destroy;
  1208. coalesced_moves:=nil;
  1209. constrained_moves.destroy;
  1210. constrained_moves:=nil;
  1211. for i:=0 to maxreg-1 do
  1212. with reginfo[i] do
  1213. if movelist<>nil then
  1214. begin
  1215. dispose(movelist);
  1216. movelist:=nil;
  1217. end;
  1218. end;
  1219. procedure trgobj.clear_interferences(u:Tsuperregister);
  1220. {Remove node u from the interference graph and remove all collected
  1221. move instructions it is associated with.}
  1222. var i : word;
  1223. v : Tsuperregister;
  1224. adj,adj2 : Psuperregisterworklist;
  1225. begin
  1226. adj:=reginfo[u].adjlist;
  1227. if adj<>nil then
  1228. begin
  1229. for i:=1 to adj^.length do
  1230. begin
  1231. v:=adj^.buf^[i-1];
  1232. {Remove (u,v) and (v,u) from bitmap.}
  1233. ibitmap[u,v]:=false;
  1234. ibitmap[v,u]:=false;
  1235. {Remove (v,u) from adjacency list.}
  1236. adj2:=reginfo[v].adjlist;
  1237. if adj2<>nil then
  1238. begin
  1239. adj2^.delete(u);
  1240. if adj2^.length=0 then
  1241. begin
  1242. dispose(adj2,done);
  1243. reginfo[v].adjlist:=nil;
  1244. end;
  1245. end;
  1246. end;
  1247. {Remove ( u,* ) from adjacency list.}
  1248. dispose(adj,done);
  1249. reginfo[u].adjlist:=nil;
  1250. end;
  1251. end;
  1252. function trgobj.getregisterinline(list:TAsmList;subreg:Tsubregister):Tregister;
  1253. var
  1254. p : Tsuperregister;
  1255. begin
  1256. p:=getnewreg(subreg);
  1257. live_registers.add(p);
  1258. result:=newreg(regtype,p,subreg);
  1259. add_edges_used(p);
  1260. add_constraints(result);
  1261. end;
  1262. procedure trgobj.ungetregisterinline(list:TAsmList;r:Tregister);
  1263. var
  1264. supreg:Tsuperregister;
  1265. begin
  1266. supreg:=getsupreg(r);
  1267. live_registers.delete(supreg);
  1268. insert_regalloc_info(list,supreg);
  1269. end;
  1270. procedure trgobj.insert_regalloc_info(list:TAsmList;u:tsuperregister);
  1271. var
  1272. p : tai;
  1273. r : tregister;
  1274. palloc,
  1275. pdealloc : tai_regalloc;
  1276. begin
  1277. { Insert regallocs for all imaginary registers }
  1278. with reginfo[u] do
  1279. begin
  1280. r:=newreg(regtype,u,subreg);
  1281. if assigned(live_start) then
  1282. begin
  1283. { Generate regalloc and bind it to an instruction, this
  1284. is needed to find all live registers belonging to an
  1285. instruction during the spilling }
  1286. if live_start.typ=ait_instruction then
  1287. palloc:=tai_regalloc.alloc(r,live_start)
  1288. else
  1289. palloc:=tai_regalloc.alloc(r,nil);
  1290. if live_end.typ=ait_instruction then
  1291. pdealloc:=tai_regalloc.dealloc(r,live_end)
  1292. else
  1293. pdealloc:=tai_regalloc.dealloc(r,nil);
  1294. { Insert live start allocation before the instruction/reg_a_sync }
  1295. list.insertbefore(palloc,live_start);
  1296. { Insert live end deallocation before reg allocations
  1297. to reduce conflicts }
  1298. p:=live_end;
  1299. while assigned(p) and
  1300. assigned(p.previous) and
  1301. (tai(p.previous).typ=ait_regalloc) and
  1302. (tai_regalloc(p.previous).ratype=ra_alloc) and
  1303. (tai_regalloc(p.previous).reg<>r) do
  1304. p:=tai(p.previous);
  1305. { , but add release after a reg_a_sync }
  1306. if assigned(p) and
  1307. (p.typ=ait_regalloc) and
  1308. (tai_regalloc(p).ratype=ra_sync) then
  1309. p:=tai(p.next);
  1310. if assigned(p) then
  1311. list.insertbefore(pdealloc,p)
  1312. else
  1313. list.concat(pdealloc);
  1314. end
  1315. {$ifdef EXTDEBUG}
  1316. else
  1317. Comment(V_Warning,'Register '+std_regname(r)+' not used');
  1318. {$endif EXTDEBUG}
  1319. end;
  1320. end;
  1321. procedure trgobj.insert_regalloc_info_all(list:TAsmList);
  1322. var
  1323. supreg : tsuperregister;
  1324. begin
  1325. { Insert regallocs for all imaginary registers }
  1326. for supreg:=first_imaginary to maxreg-1 do
  1327. insert_regalloc_info(list,supreg);
  1328. end;
  1329. procedure trgobj.add_cpu_interferences(p : tai);
  1330. begin
  1331. end;
  1332. procedure trgobj.generate_interference_graph(list:TAsmList;headertai:tai);
  1333. var
  1334. p : tai;
  1335. {$ifdef EXTDEBUG}
  1336. i : integer;
  1337. {$endif EXTDEBUG}
  1338. supreg : tsuperregister;
  1339. begin
  1340. { All allocations are available. Now we can generate the
  1341. interference graph. Walk through all instructions, we can
  1342. start with the headertai, because before the header tai is
  1343. only symbols. }
  1344. live_registers.clear;
  1345. p:=headertai;
  1346. while assigned(p) do
  1347. begin
  1348. if p.typ=ait_regalloc then
  1349. with Tai_regalloc(p) do
  1350. begin
  1351. if (getregtype(reg)=regtype) then
  1352. begin
  1353. supreg:=getsupreg(reg);
  1354. case ratype of
  1355. ra_alloc :
  1356. begin
  1357. live_registers.add(supreg);
  1358. add_edges_used(supreg);
  1359. end;
  1360. ra_dealloc :
  1361. begin
  1362. live_registers.delete(supreg);
  1363. add_edges_used(supreg);
  1364. end;
  1365. end;
  1366. { constraints needs always to be updated }
  1367. add_constraints(reg);
  1368. end;
  1369. end;
  1370. add_cpu_interferences(p);
  1371. p:=Tai(p.next);
  1372. end;
  1373. {$ifdef EXTDEBUG}
  1374. if live_registers.length>0 then
  1375. begin
  1376. for i:=0 to live_registers.length-1 do
  1377. begin
  1378. { Only report for imaginary registers }
  1379. if live_registers.buf^[i]>=first_imaginary then
  1380. Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
  1381. end;
  1382. end;
  1383. {$endif}
  1384. end;
  1385. procedure trgobj.translate_register(var reg : tregister);
  1386. begin
  1387. if (getregtype(reg)=regtype) then
  1388. setsupreg(reg,reginfo[getsupreg(reg)].colour)
  1389. else
  1390. internalerror(200602021);
  1391. end;
  1392. procedure Trgobj.translate_registers(list:TAsmList);
  1393. var
  1394. hp,p,q:Tai;
  1395. i:shortint;
  1396. {$ifdef arm}
  1397. so:pshifterop;
  1398. {$endif arm}
  1399. begin
  1400. { Leave when no imaginary registers are used }
  1401. if maxreg<=first_imaginary then
  1402. exit;
  1403. p:=Tai(list.first);
  1404. while assigned(p) do
  1405. begin
  1406. case p.typ of
  1407. ait_regalloc:
  1408. with Tai_regalloc(p) do
  1409. begin
  1410. if (getregtype(reg)=regtype) then
  1411. begin
  1412. { Only alloc/dealloc is needed for the optimizer, remove
  1413. other regalloc }
  1414. if not(ratype in [ra_alloc,ra_dealloc]) then
  1415. begin
  1416. q:=Tai(next);
  1417. list.remove(p);
  1418. p.free;
  1419. p:=q;
  1420. continue;
  1421. end
  1422. else
  1423. begin
  1424. setsupreg(reg,reginfo[getsupreg(reg)].colour);
  1425. {
  1426. Remove sequences of release and
  1427. allocation of the same register like. Other combinations
  1428. of release/allocate need to stay in the list.
  1429. # Register X released
  1430. # Register X allocated
  1431. }
  1432. if assigned(previous) and
  1433. (ratype=ra_alloc) and
  1434. (Tai(previous).typ=ait_regalloc) and
  1435. (Tai_regalloc(previous).reg=reg) and
  1436. (Tai_regalloc(previous).ratype=ra_dealloc) then
  1437. begin
  1438. q:=Tai(next);
  1439. hp:=tai(previous);
  1440. list.remove(hp);
  1441. hp.free;
  1442. list.remove(p);
  1443. p.free;
  1444. p:=q;
  1445. continue;
  1446. end;
  1447. end;
  1448. end;
  1449. end;
  1450. ait_instruction:
  1451. with Taicpu(p) do
  1452. begin
  1453. aktfilepos:=fileinfo;
  1454. for i:=0 to ops-1 do
  1455. with oper[i]^ do
  1456. case typ of
  1457. Top_reg:
  1458. if (getregtype(reg)=regtype) then
  1459. setsupreg(reg,reginfo[getsupreg(reg)].colour);
  1460. Top_ref:
  1461. begin
  1462. if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
  1463. with ref^ do
  1464. begin
  1465. if base<>NR_NO then
  1466. setsupreg(base,reginfo[getsupreg(base)].colour);
  1467. if index<>NR_NO then
  1468. setsupreg(index,reginfo[getsupreg(index)].colour);
  1469. end;
  1470. end;
  1471. {$ifdef arm}
  1472. Top_shifterop:
  1473. begin
  1474. if regtype=R_INTREGISTER then
  1475. begin
  1476. so:=shifterop;
  1477. if so^.rs<>NR_NO then
  1478. setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
  1479. end;
  1480. end;
  1481. {$endif arm}
  1482. end;
  1483. { Maybe the operation can be removed when
  1484. it is a move and both arguments are the same }
  1485. if is_same_reg_move(regtype) then
  1486. begin
  1487. q:=Tai(p.next);
  1488. list.remove(p);
  1489. p.free;
  1490. p:=q;
  1491. continue;
  1492. end;
  1493. end;
  1494. end;
  1495. p:=Tai(p.next);
  1496. end;
  1497. aktfilepos:=current_procinfo.exitpos;
  1498. end;
  1499. function trgobj.spill_registers(list:TAsmList;headertai:tai):boolean;
  1500. { Returns true if any help registers have been used }
  1501. var
  1502. i : word;
  1503. t : tsuperregister;
  1504. p,q : Tai;
  1505. regs_to_spill_set:Tsuperregisterset;
  1506. spill_temps : ^Tspill_temp_list;
  1507. supreg : tsuperregister;
  1508. templist : TAsmList;
  1509. begin
  1510. spill_registers:=false;
  1511. live_registers.clear;
  1512. for i:=first_imaginary to maxreg-1 do
  1513. exclude(reginfo[i].flags,ri_selected);
  1514. spill_temps:=allocmem(sizeof(treference)*maxreg);
  1515. supregset_reset(regs_to_spill_set,false,$ffff);
  1516. { Allocate temps and insert in front of the list }
  1517. templist:=TAsmList.create;
  1518. {Safe: this procedure is only called if there are spilled nodes.}
  1519. with spillednodes do
  1520. for i:=0 to length-1 do
  1521. begin
  1522. t:=buf^[i];
  1523. {Alternative representation.}
  1524. supregset_include(regs_to_spill_set,t);
  1525. {Clear all interferences of the spilled register.}
  1526. clear_interferences(t);
  1527. {Get a temp for the spilled register, the size must at least equal a complete register,
  1528. take also care of the fact that subreg can be larger than a single register like doubles
  1529. that occupy 2 registers }
  1530. tg.gettemp(templist,
  1531. max(tcgsize2size[reg_cgsize(newreg(regtype,t,R_SUBWHOLE))],
  1532. tcgsize2size[reg_cgsize(newreg(regtype,t,reginfo[t].subreg))]),
  1533. tt_noreuse,spill_temps^[t]);
  1534. end;
  1535. list.insertlistafter(headertai,templist);
  1536. templist.free;
  1537. { Walk through all instructions, we can start with the headertai,
  1538. because before the header tai is only symbols }
  1539. p:=headertai;
  1540. while assigned(p) do
  1541. begin
  1542. case p.typ of
  1543. ait_regalloc:
  1544. with Tai_regalloc(p) do
  1545. begin
  1546. if (getregtype(reg)=regtype) then
  1547. begin
  1548. {A register allocation of a spilled register can be removed.}
  1549. supreg:=getsupreg(reg);
  1550. if supregset_in(regs_to_spill_set,supreg) then
  1551. begin
  1552. q:=Tai(p.next);
  1553. list.remove(p);
  1554. p.free;
  1555. p:=q;
  1556. continue;
  1557. end
  1558. else
  1559. begin
  1560. case ratype of
  1561. ra_alloc :
  1562. live_registers.add(supreg);
  1563. ra_dealloc :
  1564. live_registers.delete(supreg);
  1565. end;
  1566. end;
  1567. end;
  1568. end;
  1569. ait_instruction:
  1570. with Taicpu(p) do
  1571. begin
  1572. aktfilepos:=fileinfo;
  1573. if instr_spill_register(list,taicpu(p),regs_to_spill_set,spill_temps^) then
  1574. spill_registers:=true;
  1575. end;
  1576. end;
  1577. p:=Tai(p.next);
  1578. end;
  1579. aktfilepos:=current_procinfo.exitpos;
  1580. {Safe: this procedure is only called if there are spilled nodes.}
  1581. with spillednodes do
  1582. for i:=0 to length-1 do
  1583. tg.ungettemp(list,spill_temps^[buf^[i]]);
  1584. freemem(spill_temps);
  1585. end;
  1586. function trgobj.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
  1587. begin
  1588. result:=false;
  1589. end;
  1590. procedure Trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
  1591. begin
  1592. list.insertafter(spilling_create_load(spilltemp,tempreg),pos);
  1593. end;
  1594. procedure Trgobj.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
  1595. begin
  1596. list.insertafter(spilling_create_store(tempreg,spilltemp),pos);
  1597. end;
  1598. function trgobj.get_spill_subreg(r : tregister) : tsubregister;
  1599. begin
  1600. result:=defaultsub;
  1601. end;
  1602. function trgobj.instr_spill_register(list:TAsmList;
  1603. instr:taicpu;
  1604. const r:Tsuperregisterset;
  1605. const spilltemplist:Tspill_temp_list): boolean;
  1606. var
  1607. counter, regindex: longint;
  1608. regs: tspillregsinfo;
  1609. spilled: boolean;
  1610. procedure addreginfo(reg: tregister; operation: topertype);
  1611. var
  1612. i, tmpindex: longint;
  1613. supreg : tsuperregister;
  1614. begin
  1615. tmpindex := regindex;
  1616. supreg:=getsupreg(reg);
  1617. { did we already encounter this register? }
  1618. for i := 0 to pred(regindex) do
  1619. if (regs[i].orgreg = supreg) then
  1620. begin
  1621. tmpindex := i;
  1622. break;
  1623. end;
  1624. if tmpindex > high(regs) then
  1625. internalerror(2003120301);
  1626. regs[tmpindex].orgreg := supreg;
  1627. regs[tmpindex].spillreg:=reg;
  1628. if supregset_in(r,supreg) then
  1629. begin
  1630. { add/update info on this register }
  1631. regs[tmpindex].mustbespilled := true;
  1632. case operation of
  1633. operand_read:
  1634. regs[tmpindex].regread := true;
  1635. operand_write:
  1636. regs[tmpindex].regwritten := true;
  1637. operand_readwrite:
  1638. begin
  1639. regs[tmpindex].regread := true;
  1640. regs[tmpindex].regwritten := true;
  1641. end;
  1642. end;
  1643. spilled := true;
  1644. end;
  1645. inc(regindex,ord(regindex=tmpindex));
  1646. end;
  1647. procedure tryreplacereg(var reg: tregister);
  1648. var
  1649. i: longint;
  1650. supreg: tsuperregister;
  1651. begin
  1652. supreg:=getsupreg(reg);
  1653. for i:=0 to pred(regindex) do
  1654. if (regs[i].mustbespilled) and
  1655. (regs[i].orgreg=supreg) then
  1656. begin
  1657. { Only replace supreg }
  1658. setsupreg(reg,getsupreg(regs[i].tempreg));
  1659. break;
  1660. end;
  1661. end;
  1662. var
  1663. loadpos,
  1664. storepos : tai;
  1665. oldlive_registers : tsuperregisterworklist;
  1666. begin
  1667. result := false;
  1668. fillchar(regs,sizeof(regs),0);
  1669. for counter := low(regs) to high(regs) do
  1670. regs[counter].orgreg := RS_INVALID;
  1671. spilled := false;
  1672. regindex := 0;
  1673. { check whether and if so which and how (read/written) this instructions contains
  1674. registers that must be spilled }
  1675. for counter := 0 to instr.ops-1 do
  1676. with instr.oper[counter]^ do
  1677. begin
  1678. case typ of
  1679. top_reg:
  1680. begin
  1681. if (getregtype(reg) = regtype) then
  1682. addreginfo(reg,instr.spilling_get_operation_type(counter));
  1683. end;
  1684. top_ref:
  1685. begin
  1686. if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
  1687. with ref^ do
  1688. begin
  1689. if (base <> NR_NO) then
  1690. addreginfo(base,instr.spilling_get_operation_type_ref(counter,base));
  1691. if (index <> NR_NO) then
  1692. addreginfo(index,instr.spilling_get_operation_type_ref(counter,index));
  1693. end;
  1694. end;
  1695. {$ifdef ARM}
  1696. top_shifterop:
  1697. begin
  1698. if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
  1699. if shifterop^.rs<>NR_NO then
  1700. addreginfo(shifterop^.rs,operand_read);
  1701. end;
  1702. {$endif ARM}
  1703. end;
  1704. end;
  1705. { if no spilling for this instruction we can leave }
  1706. if not spilled then
  1707. exit;
  1708. {$ifdef x86}
  1709. { Try replacing the register with the spilltemp. This is usefull only
  1710. for the i386,x86_64 that support memory locations for several instructions }
  1711. for counter := 0 to pred(regindex) do
  1712. with regs[counter] do
  1713. begin
  1714. if mustbespilled then
  1715. begin
  1716. if do_spill_replace(list,instr,orgreg,spilltemplist[orgreg]) then
  1717. mustbespilled:=false;
  1718. end;
  1719. end;
  1720. {$endif x86}
  1721. {
  1722. There are registers that need are spilled. We generate the
  1723. following code for it. The used positions where code need
  1724. to be inserted are marked using #. Note that code is always inserted
  1725. before the positions using pos.previous. This way the position is always
  1726. the same since pos doesn't change, but pos.previous is modified everytime
  1727. new code is inserted.
  1728. [
  1729. - reg_allocs load spills
  1730. - load spills
  1731. ]
  1732. [#loadpos
  1733. - reg_deallocs
  1734. - reg_allocs
  1735. ]
  1736. [
  1737. - reg_deallocs for load-only spills
  1738. - reg_allocs for store-only spills
  1739. ]
  1740. [#instr
  1741. - original instruction
  1742. ]
  1743. [
  1744. - store spills
  1745. - reg_deallocs store spills
  1746. ]
  1747. [#storepos
  1748. ]
  1749. }
  1750. result := true;
  1751. oldlive_registers.copyfrom(live_registers);
  1752. { Process all tai_regallocs belonging to this instruction, ignore explicit
  1753. inserted regallocs. These can happend for example in i386:
  1754. mov ref,ireg26
  1755. <regdealloc ireg26, instr=taicpu of lea>
  1756. <regalloc edi, insrt=nil>
  1757. lea [ireg26+ireg17],edi
  1758. All released registers are also added to the live_registers because
  1759. they can't be used during the spilling }
  1760. loadpos:=tai(instr.previous);
  1761. while assigned(loadpos) and
  1762. (loadpos.typ=ait_regalloc) and
  1763. ((tai_regalloc(loadpos).instr=nil) or
  1764. (tai_regalloc(loadpos).instr=instr)) do
  1765. begin
  1766. { Only add deallocs belonging to the instruction. Explicit inserted deallocs
  1767. belong to the previous instruction and not the current instruction }
  1768. if (tai_regalloc(loadpos).instr=instr) and
  1769. (tai_regalloc(loadpos).ratype=ra_dealloc) then
  1770. live_registers.add(getsupreg(tai_regalloc(loadpos).reg));
  1771. loadpos:=tai(loadpos.previous);
  1772. end;
  1773. loadpos:=tai(loadpos.next);
  1774. { Load the spilled registers }
  1775. for counter := 0 to pred(regindex) do
  1776. with regs[counter] do
  1777. begin
  1778. if mustbespilled and regread then
  1779. begin
  1780. tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
  1781. do_spill_read(list,tai(loadpos.previous),spilltemplist[orgreg],tempreg);
  1782. end;
  1783. end;
  1784. { Release temp registers of read-only registers, and add reference of the instruction
  1785. to the reginfo }
  1786. for counter := 0 to pred(regindex) do
  1787. with regs[counter] do
  1788. begin
  1789. if mustbespilled and regread and (not regwritten) then
  1790. begin
  1791. { The original instruction will be the next that uses this register }
  1792. add_reg_instruction(instr,tempreg);
  1793. ungetregisterinline(list,tempreg);
  1794. end;
  1795. end;
  1796. { Allocate temp registers of write-only registers, and add reference of the instruction
  1797. to the reginfo }
  1798. for counter := 0 to pred(regindex) do
  1799. with regs[counter] do
  1800. begin
  1801. if mustbespilled and regwritten then
  1802. begin
  1803. { When the register is also loaded there is already a register assigned }
  1804. if (not regread) then
  1805. tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
  1806. { The original instruction will be the next that uses this register, this
  1807. also needs to be done for read-write registers }
  1808. add_reg_instruction(instr,tempreg);
  1809. end;
  1810. end;
  1811. { store the spilled registers }
  1812. storepos:=tai(instr.next);
  1813. for counter := 0 to pred(regindex) do
  1814. with regs[counter] do
  1815. begin
  1816. if mustbespilled and regwritten then
  1817. begin
  1818. do_spill_written(list,tai(storepos.previous),spilltemplist[orgreg],tempreg);
  1819. ungetregisterinline(list,tempreg);
  1820. end;
  1821. end;
  1822. { now all spilling code is generated we can restore the live registers. This
  1823. must be done after the store because the store can need an extra register
  1824. that also needs to conflict with the registers of the instruction }
  1825. live_registers.done;
  1826. live_registers:=oldlive_registers;
  1827. { substitute registers }
  1828. for counter:=0 to instr.ops-1 do
  1829. with instr.oper[counter]^ do
  1830. begin
  1831. case typ of
  1832. top_reg:
  1833. begin
  1834. if (getregtype(reg) = regtype) then
  1835. tryreplacereg(reg);
  1836. end;
  1837. top_ref:
  1838. begin
  1839. if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
  1840. begin
  1841. tryreplacereg(ref^.base);
  1842. tryreplacereg(ref^.index);
  1843. end;
  1844. end;
  1845. {$ifdef ARM}
  1846. top_shifterop:
  1847. begin
  1848. if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
  1849. tryreplacereg(shifterop^.rs);
  1850. end;
  1851. {$endif ARM}
  1852. end;
  1853. end;
  1854. end;
  1855. end.