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