rgobj.pas 66 KB

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