rgobj.pas 96 KB

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