rgobj.pas 90 KB

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