rgobj.pas 75 KB

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