rgobj.pas 72 KB

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