rgobj.pas 78 KB

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