rgobj.pas 84 KB

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