rgobj.pas 70 KB

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