rgobj.pas 65 KB

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