rgobj.pas 84 KB

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