rgobj.pas 82 KB

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