rgobj.pas 68 KB

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