rgobj.pas 69 KB

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