rgobj.pas 79 KB

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