rgobj.pas 71 KB

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