rgobj.pas 66 KB

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