rgobj.pas 80 KB

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