rgobj.pas 84 KB

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