rgobj.pas 69 KB

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