rgobj.pas 101 KB

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