rgobj.pas 89 KB

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