rgobj.pas 73 KB

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