rgobj.pas 84 KB

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