rgobj.pas 67 KB

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