rgobj.pas 79 KB

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