rgobj.pas 84 KB

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