rgobj.pas 98 KB

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