rgobj.pas 82 KB

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