rgobj.pas 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308
  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. {#******************************************************************************
  22. @abstract(Abstract register allocator unit)
  23. Register allocator introduction.
  24. Free Pascal uses a Chaitin style register allocator. We use a variant similair
  25. to the one described in the book "Modern compiler implementation in C" by
  26. Andrew W. Appel., published by Cambridge University Press.
  27. The register allocator that is described by Appel uses a much improved way
  28. of register coalescing, called "iterated register coalescing". Instead
  29. of doing coalescing as a prepass to the register allocation, the coalescing
  30. is done inside the register allocator. This has the advantage that the
  31. register allocator can coalesce very aggresively without introducing spills.
  32. Reading this book is recommended for a complete understanding. Here is a small
  33. introduction.
  34. The code generator thinks it has an infinite amount of registers. Our processor
  35. has a limited amount of registers. Therefore we must reduce the amount of
  36. registers until there are less enough to fit into the processors registers.
  37. Registers can interfere or not interfere. If two imaginary registers interfere
  38. they cannot be placed into the same psysical register. Reduction of registers
  39. is done by:
  40. - "coalescing" Two registers that do not interfere are combined
  41. into one register.
  42. - "spilling" A register is changed into a memory location and the generated
  43. code is modified to use the memory location instead of the register.
  44. Register allocation is a graph colouring problem. Each register is a colour, and
  45. if two registers interfere there is a connection between them in the graph.
  46. In addition to the imaginary registers in the code generator, the psysical
  47. CPU registers are also present in this graph. This allows us to make
  48. interferences between imaginary registers and cpu registers. This is very
  49. usefull for describing architectural constraints, like for example that
  50. the div instruction modifies edx, so variables that are in use at that time
  51. cannot be stored into edx. This can be modelled by making edx interfere
  52. with those variables.
  53. Graph colouring is an NP complete problem. Therefore we use an approximation
  54. that pushes registers to colour on to a stack. This is done in the "simplify"
  55. procedure.
  56. The register allocator first checks which registers are a candidate for
  57. coalescing.
  58. *******************************************************************************}
  59. unit rgobj;
  60. interface
  61. uses
  62. cutils, cpubase,
  63. aasmbase,aasmtai,aasmcpu,
  64. cclasses,globtype,cgbase,node,
  65. {$ifdef delphi}
  66. dmisc,
  67. {$endif}
  68. cpuinfo
  69. ;
  70. type
  71. {
  72. regvarother_longintarray = array[tregisterindex] of longint;
  73. regvarother_booleanarray = array[tregisterindex] of boolean;
  74. regvarint_longintarray = array[first_int_supreg..last_int_supreg] of longint;
  75. regvarint_ptreearray = array[first_int_supreg..last_int_supreg] of tnode;
  76. }
  77. {
  78. The interference bitmap contains of 2 layers:
  79. layer 1 - 256*256 blocks with pointers to layer 2 blocks
  80. layer 2 - blocks of 32*256 (32 bytes = 256 bits)
  81. }
  82. Tinterferencebitmap2 = array[byte] of set of byte;
  83. Pinterferencebitmap2 = ^Tinterferencebitmap2;
  84. Tinterferencebitmap1 = array[byte] of Pinterferencebitmap2;
  85. pinterferencebitmap1 = ^tinterferencebitmap1;
  86. Tinterferencebitmap=class
  87. private
  88. maxx1,
  89. maxy1 : byte;
  90. fbitmap : pinterferencebitmap1;
  91. function getbitmap(x,y:tsuperregister):boolean;
  92. procedure setbitmap(x,y:tsuperregister;b:boolean);
  93. public
  94. constructor create;
  95. destructor destroy;override;
  96. property bitmap[x,y:tsuperregister]:boolean read getbitmap write setbitmap;default;
  97. end;
  98. Tmovelist=record
  99. count:cardinal;
  100. data:array[0..$ffff] of Tlinkedlistitem;
  101. end;
  102. Pmovelist=^Tmovelist;
  103. {In the register allocator we keep track of move instructions.
  104. These instructions are moved between five linked lists. There
  105. is also a linked list per register to keep track about the moves
  106. it is associated with. Because we need to determine quickly in
  107. which of the five lists it is we add anu enumeradtion to each
  108. move instruction.}
  109. Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
  110. ms_worklist_moves,ms_active_moves);
  111. Tmoveins=class(Tlinkedlistitem)
  112. moveset:Tmoveset;
  113. x,y:Tsuperregister;
  114. end;
  115. Treginfoflag=(ri_coalesced,ri_selected);
  116. Treginfoflagset=set of Treginfoflag;
  117. Treginfo=record
  118. live_start,
  119. live_end : Tai;
  120. subreg : tsubregister;
  121. alias : Tsuperregister;
  122. { The register allocator assigns each register a colour }
  123. colour : Tsuperregister;
  124. movelist : Pmovelist;
  125. adjlist : Psuperregisterworklist;
  126. degree : TSuperregister;
  127. flags : Treginfoflagset;
  128. end;
  129. Preginfo=^TReginfo;
  130. {#------------------------------------------------------------------
  131. This class implements the default register allocator. It is used by the
  132. code generator to allocate and free registers which might be valid
  133. across nodes. It also contains utility routines related to registers.
  134. Some of the methods in this class should be overriden
  135. by cpu-specific implementations.
  136. --------------------------------------------------------------------}
  137. trgobj=class
  138. preserved_by_proc : tcpuregisterset;
  139. used_in_proc : tcpuregisterset;
  140. // is_reg_var : Tsuperregisterset; {old regvars}
  141. // reg_var_loaded:Tsuperregisterset; {old regvars}
  142. constructor create(Aregtype:Tregistertype;
  143. Adefaultsub:Tsubregister;
  144. const Ausable:array of tsuperregister;
  145. Afirst_imaginary:Tsuperregister;
  146. Apreserved_by_proc:Tcpuregisterset);
  147. destructor destroy;override;
  148. {# Allocate a register. An internalerror will be generated if there is
  149. no more free registers which can be allocated.}
  150. function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;
  151. {# Get the register specified.}
  152. procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;
  153. {# Get multiple registers specified.}
  154. procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
  155. {# Free multiple registers specified.}
  156. procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;
  157. function uses_registers:boolean;virtual;
  158. {# Deallocate any kind of register }
  159. procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
  160. procedure add_reg_instruction(instr:Tai;r:tregister);
  161. procedure add_move_instruction(instr:Taicpu);
  162. {# Do the register allocation.}
  163. procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
  164. { Adds an interference edge.
  165. don't move this to the protected section, the arm cg requires to access this (FK) }
  166. procedure add_edge(u,v:Tsuperregister);
  167. protected
  168. regtype : Tregistertype;
  169. { default subregister used }
  170. defaultsub : tsubregister;
  171. live_registers:Tsuperregisterworklist;
  172. function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
  173. procedure forward_allocation(pfrom,pto:Tai);
  174. procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
  175. procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
  176. procedure add_constraints(reg:Tregister);virtual;
  177. function instr_spill_register(list:Taasmoutput;
  178. instr:taicpu_abstract;
  179. const r:Tsuperregisterset;
  180. const spilltemplist:Tspill_temp_list): boolean;virtual;
  181. private
  182. {# First imaginary register.}
  183. first_imaginary : Tsuperregister;
  184. {# Highest register allocated until now.}
  185. reginfo : PReginfo;
  186. maxreginfo,
  187. maxreginfoinc,
  188. maxreg : Tsuperregister;
  189. usable_registers_cnt : word;
  190. usable_registers : array[0..maxcpuregister-1] of tsuperregister;
  191. ibitmap : Tinterferencebitmap;
  192. spillednodes,
  193. simplifyworklist,
  194. freezeworklist,
  195. spillworklist,
  196. coalescednodes,
  197. selectstack : tsuperregisterworklist;
  198. worklist_moves,
  199. active_moves,
  200. frozen_moves,
  201. coalesced_moves,
  202. constrained_moves : Tlinkedlist;
  203. {$ifdef EXTDEBUG}
  204. procedure writegraph(loopidx:longint);
  205. {$endif EXTDEBUG}
  206. {# Prepare the register colouring.}
  207. procedure prepare_colouring;
  208. {# Clean up after register colouring.}
  209. procedure epilogue_colouring;
  210. {# Colour the registers; that is do the register allocation.}
  211. procedure colour_registers;
  212. {# Spills certain registers in the specified assembler list.}
  213. procedure insert_regalloc_info(list:Taasmoutput;headertai:tai);
  214. procedure generate_interference_graph(list:Taasmoutput;headertai:tai);
  215. procedure translate_registers(list:Taasmoutput);
  216. function spill_registers(list:Taasmoutput;headertai:tai):boolean;virtual;
  217. function getnewreg(subreg:tsubregister):tsuperregister;
  218. procedure add_edges_used(u:Tsuperregister);
  219. procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
  220. function move_related(n:Tsuperregister):boolean;
  221. procedure make_work_list;
  222. procedure sort_simplify_worklist;
  223. procedure enable_moves(n:Tsuperregister);
  224. procedure decrement_degree(m:Tsuperregister);
  225. procedure simplify;
  226. function get_alias(n:Tsuperregister):Tsuperregister;
  227. procedure add_worklist(u:Tsuperregister);
  228. function adjacent_ok(u,v:Tsuperregister):boolean;
  229. function conservative(u,v:Tsuperregister):boolean;
  230. procedure combine(u,v:Tsuperregister);
  231. procedure coalesce;
  232. procedure freeze_moves(u:Tsuperregister);
  233. procedure freeze;
  234. procedure select_spill;
  235. procedure assign_colours;
  236. procedure clear_interferences(u:Tsuperregister);
  237. end;
  238. const
  239. first_reg = 0;
  240. last_reg = high(tsuperregister)-1;
  241. maxspillingcounter = 20;
  242. implementation
  243. uses
  244. systems,
  245. globals,verbose,tgobj,procinfo;
  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. ibitmap:=tinterferencebitmap.create;
  322. { Get reginfo for CPU registers }
  323. reginfo:=allocmem(first_imaginary*sizeof(treginfo));
  324. maxreginfo:=first_imaginary;
  325. maxreginfoinc:=16;
  326. for i:=0 to first_imaginary-1 do
  327. reginfo[i].degree:=high(tsuperregister);
  328. worklist_moves:=Tlinkedlist.create;
  329. { Usable registers }
  330. fillchar(usable_registers,sizeof(usable_registers),0);
  331. for i:=low(Ausable) to high(Ausable) do
  332. usable_registers[i]:=Ausable[i];
  333. usable_registers_cnt:=high(Ausable)+1;
  334. { Initialize Worklists }
  335. spillednodes.init;
  336. simplifyworklist.init;
  337. freezeworklist.init;
  338. spillworklist.init;
  339. coalescednodes.init;
  340. selectstack.init;
  341. for i:=0 to maxreg-1 do
  342. reginfo[i].alias:=RS_INVALID;
  343. end;
  344. destructor trgobj.destroy;
  345. var i:Tsuperregister;
  346. begin
  347. spillednodes.done;
  348. simplifyworklist.done;
  349. freezeworklist.done;
  350. spillworklist.done;
  351. coalescednodes.done;
  352. selectstack.done;
  353. for i:=0 to maxreg-1 do
  354. begin
  355. if reginfo[i].adjlist<>nil then
  356. dispose(reginfo[i].adjlist,done);
  357. if reginfo[i].movelist<>nil then
  358. dispose(reginfo[i].movelist);
  359. end;
  360. freemem(reginfo);
  361. worklist_moves.free;
  362. ibitmap.free;
  363. end;
  364. function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
  365. var
  366. oldmaxreginfo : tsuperregister;
  367. begin
  368. result:=maxreg;
  369. inc(maxreg);
  370. if maxreg>=last_reg then
  371. internalerror(200310146);
  372. if maxreg>=maxreginfo then
  373. begin
  374. oldmaxreginfo:=maxreginfo;
  375. inc(maxreginfo,maxreginfoinc);
  376. if maxreginfoinc<256 then
  377. maxreginfoinc:=maxreginfoinc*2;
  378. reallocmem(reginfo,maxreginfo*sizeof(treginfo));
  379. { Do we really need it to clear it ? At least for 1.0.x (PFV) }
  380. fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
  381. end;
  382. reginfo[result].subreg:=subreg;
  383. end;
  384. function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
  385. begin
  386. if defaultsub=R_SUBNONE then
  387. result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
  388. else
  389. result:=newreg(regtype,getnewreg(subreg),subreg);
  390. end;
  391. function trgobj.uses_registers:boolean;
  392. begin
  393. result:=(maxreg>first_imaginary);
  394. end;
  395. procedure trgobj.ungetregister(list:Taasmoutput;r:Tregister);
  396. begin
  397. { Only explicit allocs insert regalloc info }
  398. if getsupreg(r)<first_imaginary then
  399. list.concat(Tai_regalloc.dealloc(r));
  400. end;
  401. procedure trgobj.getexplicitregister(list:Taasmoutput;r:Tregister);
  402. var
  403. supreg:Tsuperregister;
  404. begin
  405. supreg:=getsupreg(r);
  406. if supreg>=first_imaginary then
  407. internalerror(2003121503);
  408. include(used_in_proc,supreg);
  409. list.concat(Tai_regalloc.alloc(r));
  410. end;
  411. procedure trgobj.allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
  412. var i:Tsuperregister;
  413. begin
  414. for i:=0 to first_imaginary-1 do
  415. if i in r then
  416. getexplicitregister(list,newreg(regtype,i,defaultsub));
  417. end;
  418. procedure trgobj.deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
  419. var i:Tsuperregister;
  420. begin
  421. for i:=0 to first_imaginary-1 do
  422. if i in r then
  423. ungetregister(list,newreg(regtype,i,defaultsub));
  424. end;
  425. procedure trgobj.do_register_allocation(list:Taasmoutput;headertai:tai);
  426. var
  427. spillingcounter:byte;
  428. endspill:boolean;
  429. begin
  430. { Insert regalloc info for imaginary registers }
  431. insert_regalloc_info(list,headertai);
  432. generate_interference_graph(list,headertai);
  433. { Don't do the real allocation when -sr is passed }
  434. if (cs_no_regalloc in aktglobalswitches) then
  435. exit;
  436. {Do register allocation.}
  437. spillingcounter:=0;
  438. repeat
  439. prepare_colouring;
  440. colour_registers;
  441. epilogue_colouring;
  442. endspill:=true;
  443. if spillednodes.length<>0 then
  444. begin
  445. inc(spillingcounter);
  446. if spillingcounter>maxspillingcounter then
  447. internalerror(200309041);
  448. endspill:=not spill_registers(list,headertai);
  449. end;
  450. until endspill;
  451. translate_registers(list);
  452. end;
  453. procedure trgobj.add_constraints(reg:Tregister);
  454. begin
  455. end;
  456. procedure trgobj.add_edge(u,v:Tsuperregister);
  457. {This procedure will add an edge to the virtual interference graph.}
  458. procedure addadj(u,v:Tsuperregister);
  459. begin
  460. if reginfo[u].adjlist=nil then
  461. new(reginfo[u].adjlist,init);
  462. reginfo[u].adjlist^.add(v);
  463. end;
  464. begin
  465. if (u<>v) and not(ibitmap[v,u]) then
  466. begin
  467. ibitmap[v,u]:=true;
  468. ibitmap[u,v]:=true;
  469. {Precoloured nodes are not stored in the interference graph.}
  470. if (u>=first_imaginary) then
  471. addadj(u,v);
  472. if (v>=first_imaginary) then
  473. addadj(v,u);
  474. end;
  475. end;
  476. procedure trgobj.add_edges_used(u:Tsuperregister);
  477. var i:word;
  478. begin
  479. if live_registers.length>0 then
  480. for i:=0 to live_registers.length-1 do
  481. add_edge(u,live_registers.buf^[i]);
  482. end;
  483. {$ifdef EXTDEBUG}
  484. procedure trgobj.writegraph(loopidx:longint);
  485. {This procedure writes out the current interference graph in the
  486. register allocator.}
  487. var f:text;
  488. i,j:Tsuperregister;
  489. begin
  490. assign(f,'igraph'+tostr(loopidx));
  491. rewrite(f);
  492. writeln(f,'Interference graph');
  493. writeln(f);
  494. write(f,' ');
  495. for i:=0 to 15 do
  496. for j:=0 to 15 do
  497. write(f,hexstr(i,1));
  498. writeln(f);
  499. write(f,' ');
  500. for i:=0 to 15 do
  501. write(f,'0123456789ABCDEF');
  502. writeln(f);
  503. for i:=0 to maxreg-1 do
  504. begin
  505. write(f,hexstr(i,2):4);
  506. for j:=0 to maxreg-1 do
  507. if ibitmap[i,j] then
  508. write(f,'*')
  509. else
  510. write(f,'-');
  511. writeln(f);
  512. end;
  513. close(f);
  514. end;
  515. {$endif EXTDEBUG}
  516. procedure trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
  517. begin
  518. if reginfo[u].movelist=nil then
  519. begin
  520. getmem(reginfo[u].movelist,64);
  521. reginfo[u].movelist^.count:=0;
  522. end
  523. else if (reginfo[u].movelist^.count and 15)=15 then
  524. reallocmem(reginfo[u].movelist,(reginfo[u].movelist^.count+1)*4+64);
  525. reginfo[u].movelist^.data[reginfo[u].movelist^.count]:=data;
  526. inc(reginfo[u].movelist^.count);
  527. end;
  528. procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
  529. var
  530. supreg : tsuperregister;
  531. begin
  532. supreg:=getsupreg(r);
  533. if supreg>=first_imaginary then
  534. begin
  535. if not assigned(reginfo[supreg].live_start) then
  536. reginfo[supreg].live_start:=instr;
  537. reginfo[supreg].live_end:=instr;
  538. end;
  539. end;
  540. procedure trgobj.add_move_instruction(instr:Taicpu);
  541. {This procedure notifies a certain as a move instruction so the
  542. register allocator can try to eliminate it.}
  543. var i:Tmoveins;
  544. ssupreg,dsupreg:Tsuperregister;
  545. begin
  546. {$ifdef extdebug}
  547. if (instr.oper[O_MOV_SOURCE]^.typ<>top_reg) or
  548. (instr.oper[O_MOV_DEST]^.typ<>top_reg) then
  549. internalerror(200311291);
  550. {$endif}
  551. i:=Tmoveins.create;
  552. i.moveset:=ms_worklist_moves;
  553. worklist_moves.insert(i);
  554. ssupreg:=getsupreg(instr.oper[O_MOV_SOURCE]^.reg);
  555. add_to_movelist(ssupreg,i);
  556. dsupreg:=getsupreg(instr.oper[O_MOV_DEST]^.reg);
  557. if ssupreg<>dsupreg then
  558. {Avoid adding the same move instruction twice to a single register.}
  559. add_to_movelist(dsupreg,i);
  560. i.x:=ssupreg;
  561. i.y:=dsupreg;
  562. end;
  563. function trgobj.move_related(n:Tsuperregister):boolean;
  564. var i:cardinal;
  565. begin
  566. move_related:=false;
  567. if reginfo[n].movelist<>nil then
  568. for i:=0 to reginfo[n].movelist^.count-1 do
  569. if Tmoveins(reginfo[n].movelist^.data[i]).moveset in [ms_worklist_moves,ms_active_moves] then
  570. begin
  571. move_related:=true;
  572. break;
  573. end;
  574. end;
  575. procedure Trgobj.sort_simplify_worklist;
  576. {Sorts the simplifyworklist by the number of interferences the
  577. registers in it cause. This allows simplify to execute in
  578. constant time.}
  579. var p,h,i,j,leni,lenj:word;
  580. t:Tsuperregister;
  581. adji,adjj:Psuperregisterworklist;
  582. begin
  583. if simplifyworklist.length<2 then
  584. exit;
  585. p:=1;
  586. while 2*p<simplifyworklist.length do
  587. p:=2*p;
  588. while p<>0 do
  589. begin
  590. for h:=0 to simplifyworklist.length-p-1 do
  591. begin
  592. i:=h;
  593. repeat
  594. j:=i+p;
  595. adji:=reginfo[simplifyworklist.buf^[i]].adjlist;
  596. adjj:=reginfo[simplifyworklist.buf^[j]].adjlist;
  597. if adji=nil then
  598. leni:=0
  599. else
  600. leni:=adji^.length;
  601. if adjj=nil then
  602. lenj:=0
  603. else
  604. lenj:=adjj^.length;
  605. if lenj>=leni then
  606. break;
  607. t:=simplifyworklist.buf^[i];
  608. simplifyworklist.buf^[i]:=simplifyworklist.buf^[j];
  609. simplifyworklist.buf^[j]:=t;
  610. if i<p then
  611. break;
  612. dec(i,p)
  613. until false;
  614. end;
  615. p:=p shr 1;
  616. end;
  617. end;
  618. procedure trgobj.make_work_list;
  619. var n:Tsuperregister;
  620. begin
  621. {If we have 7 cpu registers, and the degree of a node is 7, we cannot
  622. assign it to any of the registers, thus it is significant.}
  623. for n:=first_imaginary to maxreg-1 do
  624. begin
  625. if reginfo[n].adjlist=nil then
  626. reginfo[n].degree:=0
  627. else
  628. reginfo[n].degree:=reginfo[n].adjlist^.length;
  629. if reginfo[n].degree>=usable_registers_cnt then
  630. spillworklist.add(n)
  631. else if move_related(n) then
  632. freezeworklist.add(n)
  633. else
  634. simplifyworklist.add(n);
  635. end;
  636. sort_simplify_worklist;
  637. end;
  638. procedure trgobj.prepare_colouring;
  639. var i:word;
  640. begin
  641. make_work_list;
  642. active_moves:=Tlinkedlist.create;
  643. frozen_moves:=Tlinkedlist.create;
  644. coalesced_moves:=Tlinkedlist.create;
  645. constrained_moves:=Tlinkedlist.create;
  646. selectstack.clear;
  647. end;
  648. procedure trgobj.enable_moves(n:Tsuperregister);
  649. var m:Tlinkedlistitem;
  650. i:cardinal;
  651. begin
  652. if reginfo[n].movelist<>nil then
  653. for i:=0 to reginfo[n].movelist^.count-1 do
  654. begin
  655. m:=reginfo[n].movelist^.data[i];
  656. if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
  657. if Tmoveins(m).moveset=ms_active_moves then
  658. begin
  659. {Move m from the set active_moves to the set worklist_moves.}
  660. active_moves.remove(m);
  661. Tmoveins(m).moveset:=ms_worklist_moves;
  662. worklist_moves.concat(m);
  663. end;
  664. end;
  665. end;
  666. procedure trgobj.decrement_degree(m:Tsuperregister);
  667. var adj : Psuperregisterworklist;
  668. d,n : tsuperregister;
  669. i : word;
  670. begin
  671. d:=reginfo[m].degree;
  672. if d=0 then
  673. internalerror(200312151);
  674. dec(reginfo[m].degree);
  675. if d=usable_registers_cnt then
  676. begin
  677. {Enable moves for m.}
  678. enable_moves(m);
  679. {Enable moves for adjacent.}
  680. adj:=reginfo[m].adjlist;
  681. if adj<>nil then
  682. for i:=1 to adj^.length do
  683. begin
  684. n:=adj^.buf^[i-1];
  685. if reginfo[n].flags*[ri_selected,ri_coalesced]<>[] then
  686. enable_moves(n);
  687. end;
  688. {Remove the node from the spillworklist.}
  689. if not spillworklist.delete(m) then
  690. internalerror(200310145);
  691. if move_related(m) then
  692. freezeworklist.add(m)
  693. else
  694. simplifyworklist.add(m);
  695. end;
  696. end;
  697. procedure trgobj.simplify;
  698. var adj : Psuperregisterworklist;
  699. m,n : Tsuperregister;
  700. i : word;
  701. begin
  702. {We take the element with the least interferences out of the
  703. simplifyworklist. Since the simplifyworklist is now sorted, we
  704. no longer need to search, but we can simply take the first element.}
  705. m:=simplifyworklist.get;
  706. {Push it on the selectstack.}
  707. selectstack.add(m);
  708. include(reginfo[m].flags,ri_selected);
  709. adj:=reginfo[m].adjlist;
  710. if adj<>nil then
  711. for i:=1 to adj^.length do
  712. begin
  713. n:=adj^.buf^[i-1];
  714. if (n>=first_imaginary) and
  715. (reginfo[n].flags*[ri_selected,ri_coalesced]=[]) then
  716. decrement_degree(n);
  717. end;
  718. end;
  719. function trgobj.get_alias(n:Tsuperregister):Tsuperregister;
  720. begin
  721. while ri_coalesced in reginfo[n].flags do
  722. n:=reginfo[n].alias;
  723. get_alias:=n;
  724. end;
  725. procedure trgobj.add_worklist(u:Tsuperregister);
  726. begin
  727. if (u>=first_imaginary) and
  728. (not move_related(u)) and
  729. (reginfo[u].degree<usable_registers_cnt) then
  730. begin
  731. if not freezeworklist.delete(u) then
  732. internalerror(200308161); {must be found}
  733. simplifyworklist.add(u);
  734. end;
  735. end;
  736. function trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
  737. {Check wether u and v should be coalesced. u is precoloured.}
  738. function ok(t,r:Tsuperregister):boolean;
  739. begin
  740. ok:=(t<first_imaginary) or
  741. (reginfo[t].degree<usable_registers_cnt) or
  742. ibitmap[r,t];
  743. end;
  744. var adj : Psuperregisterworklist;
  745. i : word;
  746. n : tsuperregister;
  747. begin
  748. adjacent_ok:=true;
  749. adj:=reginfo[v].adjlist;
  750. if adj<>nil then
  751. for i:=1 to adj^.length do
  752. begin
  753. n:=adj^.buf^[i-1];
  754. if (reginfo[v].flags*[ri_coalesced,ri_selected]=[]) and
  755. not ok(n,u) then
  756. begin
  757. adjacent_ok:=false;
  758. break;
  759. end;
  760. end;
  761. end;
  762. function trgobj.conservative(u,v:Tsuperregister):boolean;
  763. var adj : Psuperregisterworklist;
  764. done : Tsuperregisterset; {To prevent that we count nodes twice.}
  765. i,k:word;
  766. n : tsuperregister;
  767. begin
  768. k:=0;
  769. supregset_reset(done,false);
  770. adj:=reginfo[u].adjlist;
  771. if adj<>nil then
  772. for i:=1 to adj^.length do
  773. begin
  774. n:=adj^.buf^[i-1];
  775. if reginfo[u].flags*[ri_coalesced,ri_selected]=[] then
  776. begin
  777. supregset_include(done,n);
  778. if reginfo[n].degree>=usable_registers_cnt then
  779. inc(k);
  780. end;
  781. end;
  782. adj:=reginfo[v].adjlist;
  783. if adj<>nil then
  784. for i:=1 to adj^.length do
  785. begin
  786. n:=adj^.buf^[i-1];
  787. if not supregset_in(done,n) and
  788. (reginfo[n].degree>=usable_registers_cnt) and
  789. (reginfo[u].flags*[ri_coalesced,ri_selected]=[]) then
  790. inc(k);
  791. end;
  792. conservative:=(k<usable_registers_cnt);
  793. end;
  794. procedure trgobj.combine(u,v:Tsuperregister);
  795. var adj : Psuperregisterworklist;
  796. i : word;
  797. t : tsuperregister;
  798. n,o : cardinal;
  799. decrement : boolean;
  800. label l1;
  801. begin
  802. if not freezeworklist.delete(v) then
  803. spillworklist.delete(v);
  804. coalescednodes.add(v);
  805. include(reginfo[v].flags,ri_coalesced);
  806. reginfo[v].alias:=u;
  807. {Combine both movelists. Since the movelists are sets, only add
  808. elements that are not already present.}
  809. if assigned(reginfo[v].movelist) then
  810. begin
  811. for n:=0 to reginfo[v].movelist^.count-1 do
  812. begin
  813. for o:=0 to reginfo[u].movelist^.count-1 do
  814. if reginfo[u].movelist^.data[o]=reginfo[v].movelist^.data[n] then
  815. goto l1; {Continue outer loop.}
  816. add_to_movelist(u,reginfo[v].movelist^.data[n]);
  817. l1:
  818. end;
  819. enable_moves(v);
  820. end;
  821. adj:=reginfo[v].adjlist;
  822. if adj<>nil then
  823. for i:=1 to adj^.length do
  824. begin
  825. t:=adj^.buf^[i-1];
  826. if not(ri_coalesced in reginfo[t].flags) then
  827. begin
  828. {t has a connection to v. Since we are adding v to u, we
  829. need to connect t to u. However, beware if t was already
  830. connected to u...}
  831. if (ibitmap[t,u]) and not (ri_selected in reginfo[t].flags) then
  832. {... because in that case, we are actually removing an edge
  833. and the degree of t decreases.}
  834. decrement_degree(t)
  835. else
  836. begin
  837. add_edge(t,u);
  838. {We have added an edge to t and u. So their degree increases.
  839. However, v is added to u. That means its neighbours will
  840. no longer point to v, but to u instead. Therefore, only the
  841. degree of u increases.}
  842. if (u>=first_imaginary) and not (ri_selected in reginfo[t].flags) then
  843. inc(reginfo[u].degree);
  844. end;
  845. end;
  846. end;
  847. if (reginfo[u].degree>=usable_registers_cnt) and
  848. freezeworklist.delete(u) then
  849. spillworklist.add(u);
  850. end;
  851. procedure trgobj.coalesce;
  852. var m:Tmoveins;
  853. x,y,u,v:Tsuperregister;
  854. begin
  855. m:=Tmoveins(worklist_moves.getfirst);
  856. x:=get_alias(m.x);
  857. y:=get_alias(m.y);
  858. if (y<first_imaginary) then
  859. begin
  860. u:=y;
  861. v:=x;
  862. end
  863. else
  864. begin
  865. u:=x;
  866. v:=y;
  867. end;
  868. if (u=v) then
  869. begin
  870. m.moveset:=ms_coalesced_moves; {Already coalesced.}
  871. coalesced_moves.insert(m);
  872. add_worklist(u);
  873. end
  874. {Do u and v interfere? In that case the move is constrained. Two
  875. precoloured nodes interfere allways. If v is precoloured, by the above
  876. code u is precoloured, thus interference...}
  877. else if (v<first_imaginary) or ibitmap[u,v] then
  878. begin
  879. m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
  880. constrained_moves.insert(m);
  881. add_worklist(u);
  882. add_worklist(v);
  883. end
  884. {Next test: is it possible and a good idea to coalesce??}
  885. else if ((u<first_imaginary) and adjacent_ok(u,v)) or
  886. ((u>=first_imaginary) and conservative(u,v)) then
  887. begin
  888. m.moveset:=ms_coalesced_moves; {Move coalesced!}
  889. coalesced_moves.insert(m);
  890. combine(u,v);
  891. add_worklist(u);
  892. end
  893. else
  894. begin
  895. m.moveset:=ms_active_moves;
  896. active_moves.insert(m);
  897. end;
  898. end;
  899. procedure trgobj.freeze_moves(u:Tsuperregister);
  900. var i:cardinal;
  901. m:Tlinkedlistitem;
  902. v,x,y:Tsuperregister;
  903. begin
  904. if reginfo[u].movelist<>nil then
  905. for i:=0 to reginfo[u].movelist^.count-1 do
  906. begin
  907. m:=reginfo[u].movelist^.data[i];
  908. if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
  909. begin
  910. x:=Tmoveins(m).x;
  911. y:=Tmoveins(m).y;
  912. if get_alias(y)=get_alias(u) then
  913. v:=get_alias(x)
  914. else
  915. v:=get_alias(y);
  916. {Move m from active_moves/worklist_moves to frozen_moves.}
  917. if Tmoveins(m).moveset=ms_active_moves then
  918. active_moves.remove(m)
  919. else
  920. worklist_moves.remove(m);
  921. Tmoveins(m).moveset:=ms_frozen_moves;
  922. frozen_moves.insert(m);
  923. if (v>=first_imaginary) and not(move_related(v)) and
  924. (reginfo[v].degree<usable_registers_cnt) then
  925. begin
  926. freezeworklist.delete(v);
  927. simplifyworklist.add(v);
  928. end;
  929. end;
  930. end;
  931. end;
  932. procedure trgobj.freeze;
  933. var n:Tsuperregister;
  934. begin
  935. { We need to take a random element out of the freezeworklist. We take
  936. the last element. Dirty code! }
  937. n:=freezeworklist.get;
  938. {Add it to the simplifyworklist.}
  939. simplifyworklist.add(n);
  940. freeze_moves(n);
  941. end;
  942. procedure trgobj.select_spill;
  943. var
  944. n : tsuperregister;
  945. adj : psuperregisterworklist;
  946. max,p,i:word;
  947. begin
  948. { We must look for the element with the most interferences in the
  949. spillworklist. This is required because those registers are creating
  950. the most conflicts and keeping them in a register will not reduce the
  951. complexity and even can cause the help registers for the spilling code
  952. to get too much conflicts with the result that the spilling code
  953. will never converge (PFV) }
  954. max:=0;
  955. p:=0;
  956. {Safe: This procedure is only called if length<>0}
  957. for i:=0 to spillworklist.length-1 do
  958. begin
  959. adj:=reginfo[spillworklist.buf^[i]].adjlist;
  960. if assigned(adj) and (adj^.length>max) then
  961. begin
  962. p:=i;
  963. max:=adj^.length;
  964. end;
  965. end;
  966. n:=spillworklist.buf^[p];
  967. spillworklist.deleteidx(p);
  968. simplifyworklist.add(n);
  969. freeze_moves(n);
  970. end;
  971. procedure trgobj.assign_colours;
  972. {Assign_colours assigns the actual colours to the registers.}
  973. var adj : Psuperregisterworklist;
  974. i,j,k : word;
  975. n,a,c : Tsuperregister;
  976. adj_colours,
  977. colourednodes : Tsuperregisterset;
  978. found : boolean;
  979. begin
  980. spillednodes.clear;
  981. {Reset colours}
  982. for n:=0 to maxreg-1 do
  983. reginfo[n].colour:=n;
  984. {Colour the cpu registers...}
  985. supregset_reset(colourednodes,false);
  986. for n:=0 to first_imaginary-1 do
  987. supregset_include(colourednodes,n);
  988. {Now colour the imaginary registers on the select-stack.}
  989. for i:=selectstack.length downto 1 do
  990. begin
  991. n:=selectstack.buf^[i-1];
  992. {Create a list of colours that we cannot assign to n.}
  993. supregset_reset(adj_colours,false);
  994. adj:=reginfo[n].adjlist;
  995. if adj<>nil then
  996. for j:=0 to adj^.length-1 do
  997. begin
  998. a:=get_alias(adj^.buf^[j]);
  999. if supregset_in(colourednodes,a) then
  1000. supregset_include(adj_colours,reginfo[a].colour);
  1001. end;
  1002. supregset_include(adj_colours,RS_STACK_POINTER_REG);
  1003. {Assume a spill by default...}
  1004. found:=false;
  1005. {Search for a colour not in this list.}
  1006. for k:=0 to usable_registers_cnt-1 do
  1007. begin
  1008. c:=usable_registers[k];
  1009. if not(supregset_in(adj_colours,c)) then
  1010. begin
  1011. reginfo[n].colour:=c;
  1012. found:=true;
  1013. supregset_include(colourednodes,n);
  1014. include(used_in_proc,c);
  1015. break;
  1016. end;
  1017. end;
  1018. if not found then
  1019. spillednodes.add(n);
  1020. end;
  1021. {Finally colour the nodes that were coalesced.}
  1022. for i:=1 to coalescednodes.length do
  1023. begin
  1024. n:=coalescednodes.buf^[i-1];
  1025. k:=get_alias(n);
  1026. reginfo[n].colour:=reginfo[k].colour;
  1027. if reginfo[k].colour<maxcpuregister then
  1028. include(used_in_proc,reginfo[k].colour);
  1029. end;
  1030. {$ifdef ra_debug}
  1031. if aktfilepos.line=179 then
  1032. begin
  1033. writeln('colourlist');
  1034. for i:=0 to maxreg-1 do
  1035. writeln(i:4,' ',reginfo[i].colour:4)
  1036. end;
  1037. {$endif ra_debug}
  1038. end;
  1039. procedure trgobj.colour_registers;
  1040. begin
  1041. repeat
  1042. if simplifyworklist.length<>0 then
  1043. simplify
  1044. else if not(worklist_moves.empty) then
  1045. coalesce
  1046. else if freezeworklist.length<>0 then
  1047. freeze
  1048. else if spillworklist.length<>0 then
  1049. select_spill;
  1050. until (simplifyworklist.length=0) and
  1051. worklist_moves.empty and
  1052. (freezeworklist.length=0) and
  1053. (spillworklist.length=0);
  1054. assign_colours;
  1055. end;
  1056. procedure trgobj.epilogue_colouring;
  1057. var
  1058. i : Tsuperregister;
  1059. begin
  1060. worklist_moves.clear;
  1061. active_moves.destroy;
  1062. active_moves:=nil;
  1063. frozen_moves.destroy;
  1064. frozen_moves:=nil;
  1065. coalesced_moves.destroy;
  1066. coalesced_moves:=nil;
  1067. constrained_moves.destroy;
  1068. constrained_moves:=nil;
  1069. for i:=0 to maxreg-1 do
  1070. if reginfo[i].movelist<>nil then
  1071. begin
  1072. dispose(reginfo[i].movelist);
  1073. reginfo[i].movelist:=nil;
  1074. end;
  1075. end;
  1076. procedure trgobj.clear_interferences(u:Tsuperregister);
  1077. {Remove node u from the interference graph and remove all collected
  1078. move instructions it is associated with.}
  1079. var i : word;
  1080. v : Tsuperregister;
  1081. adj,adj2 : Psuperregisterworklist;
  1082. begin
  1083. adj:=reginfo[u].adjlist;
  1084. if adj<>nil then
  1085. begin
  1086. for i:=1 to adj^.length do
  1087. begin
  1088. v:=adj^.buf^[i-1];
  1089. {Remove (u,v) and (v,u) from bitmap.}
  1090. ibitmap[u,v]:=false;
  1091. ibitmap[v,u]:=false;
  1092. {Remove (v,u) from adjacency list.}
  1093. adj2:=reginfo[v].adjlist;
  1094. if adj2<>nil then
  1095. begin
  1096. adj2^.delete(u);
  1097. if adj2^.length=0 then
  1098. begin
  1099. dispose(adj2,done);
  1100. reginfo[v].adjlist:=nil;
  1101. end;
  1102. end;
  1103. end;
  1104. {Remove ( u,* ) from adjacency list.}
  1105. dispose(adj,done);
  1106. reginfo[u].adjlist:=nil;
  1107. end;
  1108. end;
  1109. procedure trgobj.getregisterinline(list:Taasmoutput;
  1110. position:Tai;subreg:Tsubregister;var result:Tregister);
  1111. var p:Tsuperregister;
  1112. r:Tregister;
  1113. begin
  1114. p:=getnewreg(subreg);
  1115. live_registers.add(p);
  1116. r:=newreg(regtype,p,subreg);
  1117. if position=nil then
  1118. list.insert(Tai_regalloc.alloc(r))
  1119. else
  1120. list.insertafter(Tai_regalloc.alloc(r),position);
  1121. add_edges_used(p);
  1122. add_constraints(r);
  1123. result:=r;
  1124. end;
  1125. procedure trgobj.ungetregisterinline(list:Taasmoutput;
  1126. position:Tai;r:Tregister);
  1127. var supreg:Tsuperregister;
  1128. begin
  1129. supreg:=getsupreg(r);
  1130. live_registers.delete(supreg);
  1131. if position=nil then
  1132. list.insert(Tai_regalloc.dealloc(r))
  1133. else
  1134. list.insertafter(Tai_regalloc.dealloc(r),position);
  1135. end;
  1136. procedure trgobj.insert_regalloc_info(list:Taasmoutput;headertai:tai);
  1137. var
  1138. supreg : tsuperregister;
  1139. p : tai;
  1140. r : tregister;
  1141. begin
  1142. { Insert regallocs for all imaginary registers }
  1143. for supreg:=first_imaginary to maxreg-1 do
  1144. begin
  1145. r:=newreg(regtype,supreg,reginfo[supreg].subreg);
  1146. if assigned(reginfo[supreg].live_start) then
  1147. begin
  1148. {$ifdef EXTDEBUG}
  1149. if reginfo[supreg].live_start=reginfo[supreg].live_end then
  1150. Comment(V_Warning,'Register '+std_regname(r)+' is only used once');
  1151. {$endif EXTDEBUG}
  1152. list.insertbefore(Tai_regalloc.alloc(r),reginfo[supreg].live_start);
  1153. { Insert live end deallocation before reg allocations
  1154. to reduce conflicts }
  1155. p:=reginfo[supreg].live_end;
  1156. while assigned(p) and
  1157. assigned(p.previous) and
  1158. (tai(p.previous).typ=ait_regalloc) and
  1159. tai_regalloc(p.previous).allocation and
  1160. (tai_regalloc(p.previous).reg<>r) do
  1161. p:=tai(p.previous);
  1162. list.insertbefore(Tai_regalloc.dealloc(r),p);
  1163. end
  1164. {$ifdef EXTDEBUG}
  1165. else
  1166. Comment(V_Warning,'Register '+std_regname(r)+' not used');
  1167. {$endif EXTDEBUG}
  1168. end;
  1169. end;
  1170. procedure trgobj.generate_interference_graph(list:Taasmoutput;headertai:tai);
  1171. var
  1172. p : tai;
  1173. i : integer;
  1174. supreg : tsuperregister;
  1175. begin
  1176. { All allocations are available. Now we can generate the
  1177. interference graph. Walk through all instructions, we can
  1178. start with the headertai, because before the header tai is
  1179. only symbols. }
  1180. live_registers.clear;
  1181. p:=headertai;
  1182. while assigned(p) do
  1183. begin
  1184. if p.typ=ait_regalloc then
  1185. begin
  1186. if (getregtype(Tai_regalloc(p).reg)=regtype) then
  1187. begin
  1188. supreg:=getsupreg(Tai_regalloc(p).reg);
  1189. if Tai_regalloc(p).allocation then
  1190. live_registers.add(supreg)
  1191. else
  1192. live_registers.delete(supreg);
  1193. add_edges_used(supreg);
  1194. add_constraints(Tai_regalloc(p).reg);
  1195. end;
  1196. end;
  1197. p:=Tai(p.next);
  1198. end;
  1199. {$ifdef EXTDEBUG}
  1200. if live_registers.length>0 then
  1201. begin
  1202. for i:=0 to live_registers.length-1 do
  1203. begin
  1204. { Only report for imaginary registers }
  1205. if live_registers.buf^[i]>=first_imaginary then
  1206. Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
  1207. end;
  1208. end;
  1209. {$endif}
  1210. end;
  1211. procedure Trgobj.translate_registers(list:taasmoutput);
  1212. var
  1213. hp,p,q:Tai;
  1214. i:shortint;
  1215. r:Preference;
  1216. {$ifdef arm}
  1217. so:pshifterop;
  1218. {$endif arm}
  1219. begin
  1220. { Leave when no imaginary registers are used }
  1221. if maxreg<=first_imaginary then
  1222. exit;
  1223. p:=Tai(list.first);
  1224. while assigned(p) do
  1225. begin
  1226. case p.typ of
  1227. ait_regalloc:
  1228. begin
  1229. if (getregtype(Tai_regalloc(p).reg)=regtype) then
  1230. setsupreg(Tai_regalloc(p).reg,reginfo[getsupreg(Tai_regalloc(p).reg)].colour);
  1231. {
  1232. Remove sequences of release and
  1233. allocation of the same register like:
  1234. # Register X released
  1235. # Register X allocated
  1236. }
  1237. if assigned(p.previous) and
  1238. (Tai(p.previous).typ=ait_regalloc) and
  1239. (Tai_regalloc(p.previous).reg=Tai_regalloc(p).reg) and
  1240. { allocation,deallocation or deallocation,allocation }
  1241. (Tai_regalloc(p.previous).allocation xor Tai_regalloc(p).allocation) then
  1242. begin
  1243. q:=Tai(p.next);
  1244. hp:=tai(p.previous);
  1245. list.remove(hp);
  1246. hp.free;
  1247. list.remove(p);
  1248. p.free;
  1249. p:=q;
  1250. continue;
  1251. end;
  1252. end;
  1253. ait_instruction:
  1254. begin
  1255. for i:=0 to Taicpu_abstract(p).ops-1 do
  1256. case Taicpu_abstract(p).oper[i]^.typ of
  1257. Top_reg:
  1258. if (getregtype(Taicpu_abstract(p).oper[i]^.reg)=regtype) then
  1259. setsupreg(Taicpu_abstract(p).oper[i]^.reg,reginfo[getsupreg(Taicpu_abstract(p).oper[i]^.reg)].colour);
  1260. Top_ref:
  1261. begin
  1262. if regtype=R_INTREGISTER then
  1263. begin
  1264. r:=Taicpu_abstract(p).oper[i]^.ref;
  1265. if r^.base<>NR_NO then
  1266. setsupreg(r^.base,reginfo[getsupreg(r^.base)].colour);
  1267. if r^.index<>NR_NO then
  1268. setsupreg(r^.index,reginfo[getsupreg(r^.index)].colour);
  1269. end;
  1270. end;
  1271. {$ifdef arm}
  1272. Top_shifterop:
  1273. begin
  1274. so:=Taicpu_abstract(p).oper[i]^.shifterop;
  1275. if so^.rs<>NR_NO then
  1276. setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
  1277. end;
  1278. {$endif arm}
  1279. end;
  1280. { Maybe the operation can be removed when
  1281. it is a move and both arguments are the same }
  1282. if Taicpu_abstract(p).is_same_reg_move then
  1283. begin
  1284. q:=Tai(p.next);
  1285. list.remove(p);
  1286. p.free;
  1287. p:=q;
  1288. continue;
  1289. end;
  1290. end;
  1291. end;
  1292. p:=Tai(p.next);
  1293. end;
  1294. end;
  1295. function trgobj.get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
  1296. var
  1297. back : Tsuperregisterworklist;
  1298. supreg : tsuperregister;
  1299. begin
  1300. back.copyfrom(live_registers);
  1301. result:=p;
  1302. while (p<>nil) and (p.typ=ait_regalloc) do
  1303. begin
  1304. supreg:=getsupreg(Tai_regalloc(p).reg);
  1305. {Rewind the register allocation.}
  1306. if Tai_regalloc(p).allocation then
  1307. live_registers.delete(supreg)
  1308. else
  1309. begin
  1310. live_registers.add(supreg);
  1311. if supreg=huntfor1 then
  1312. begin
  1313. get_insert_pos:=Tai(p.previous);
  1314. back.done;
  1315. back.copyfrom(live_registers);
  1316. end;
  1317. if supreg=huntfor2 then
  1318. begin
  1319. get_insert_pos:=Tai(p.previous);
  1320. back.done;
  1321. back.copyfrom(live_registers);
  1322. end;
  1323. if supreg=huntfor3 then
  1324. begin
  1325. get_insert_pos:=Tai(p.previous);
  1326. back.done;
  1327. back.copyfrom(live_registers);
  1328. end;
  1329. end;
  1330. p:=Tai(p.previous);
  1331. end;
  1332. live_registers.done;
  1333. live_registers.copyfrom(back);
  1334. end;
  1335. procedure trgobj.forward_allocation(pfrom,pto:Tai);
  1336. var
  1337. p : tai;
  1338. begin
  1339. {Forward the register allocation again.}
  1340. p:=pfrom;
  1341. while (p<>pto) do
  1342. begin
  1343. if p.typ<>ait_regalloc then
  1344. internalerror(200305311);
  1345. if Tai_regalloc(p).allocation then
  1346. live_registers.add(getsupreg(Tai_regalloc(p).reg))
  1347. else
  1348. live_registers.delete(getsupreg(Tai_regalloc(p).reg));
  1349. p:=Tai(p.next);
  1350. end;
  1351. end;
  1352. function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
  1353. { Returns true if any help registers have been used }
  1354. var
  1355. i : word;
  1356. t : tsuperregister;
  1357. p,q : Tai;
  1358. regs_to_spill_set:Tsuperregisterset;
  1359. spill_temps : ^Tspill_temp_list;
  1360. supreg : tsuperregister;
  1361. templist : taasmoutput;
  1362. begin
  1363. spill_registers:=false;
  1364. live_registers.clear;
  1365. for i:=first_imaginary to maxreg-1 do
  1366. exclude(reginfo[i].flags,ri_selected);
  1367. spill_temps:=allocmem(sizeof(treference)*maxreg);
  1368. supregset_reset(regs_to_spill_set,false);
  1369. { Allocate temps and insert in front of the list }
  1370. templist:=taasmoutput.create;
  1371. {Safe: this procedure is only called if there are spilled nodes.}
  1372. for i:=0 to spillednodes.length-1 do
  1373. begin
  1374. t:=spillednodes.buf^[i];
  1375. {Alternative representation.}
  1376. supregset_include(regs_to_spill_set,t);
  1377. {Clear all interferences of the spilled register.}
  1378. clear_interferences(t);
  1379. {Get a temp for the spilled register}
  1380. tg.gettemp(templist,4,tt_noreuse,spill_temps^[t]);
  1381. end;
  1382. list.insertlistafter(headertai,templist);
  1383. templist.free;
  1384. { Walk through all instructions, we can start with the headertai,
  1385. because before the header tai is only symbols }
  1386. p:=headertai;
  1387. while assigned(p) do
  1388. begin
  1389. case p.typ of
  1390. ait_regalloc:
  1391. begin
  1392. if (getregtype(Tai_regalloc(p).reg)=regtype) then
  1393. begin
  1394. {A register allocation of a spilled register can be removed.}
  1395. supreg:=getsupreg(Tai_regalloc(p).reg);
  1396. if supregset_in(regs_to_spill_set,supreg) then
  1397. begin
  1398. q:=Tai(p.next);
  1399. list.remove(p);
  1400. p.free;
  1401. p:=q;
  1402. continue;
  1403. end
  1404. else
  1405. if Tai_regalloc(p).allocation then
  1406. live_registers.add(supreg)
  1407. else
  1408. live_registers.delete(supreg);
  1409. end;
  1410. end;
  1411. ait_instruction:
  1412. begin
  1413. aktfilepos:=Taicpu_abstract(p).fileinfo;
  1414. if instr_spill_register(list,Taicpu_abstract(p),regs_to_spill_set,spill_temps^) then
  1415. spill_registers:=true;
  1416. if Taicpu_abstract(p).is_reg_move then
  1417. add_move_instruction(Taicpu(p));
  1418. end;
  1419. end;
  1420. p:=Tai(p.next);
  1421. end;
  1422. aktfilepos:=current_procinfo.exitpos;
  1423. {Safe: this procedure is only called if there are spilled nodes.}
  1424. for i:=0 to spillednodes.length-1 do
  1425. tg.ungettemp(list,spill_temps^[spillednodes.buf^[i]]);
  1426. freemem(spill_temps);
  1427. end;
  1428. function trgobj.instr_spill_register(list:Taasmoutput;
  1429. instr:taicpu_abstract;
  1430. const r:Tsuperregisterset;
  1431. const spilltemplist:Tspill_temp_list): boolean;
  1432. type
  1433. tspillreginfo = record
  1434. orgreg : tsuperregister;
  1435. tempreg : tregister;
  1436. regread,regwritten, mustbespilled: boolean;
  1437. end;
  1438. var
  1439. counter, regindex: longint;
  1440. pos: tai;
  1441. regs: array[0..2] of tspillreginfo;
  1442. spilled: boolean;
  1443. procedure DoSpillRead(pos: tai; regidx: longint);
  1444. var
  1445. helpins: tai;
  1446. begin
  1447. helpins:=instr.spilling_create_load(spilltemplist[regs[regidx].orgreg],regs[regidx].tempreg);
  1448. if pos=nil then
  1449. list.insertafter(helpins,list.first)
  1450. else
  1451. list.insertafter(helpins,pos.next);
  1452. ungetregisterinline(list,instr,regs[regidx].tempreg);
  1453. forward_allocation(tai(helpins.next),instr);
  1454. end;
  1455. procedure DoSpillWritten(pos: tai; regidx: longint);
  1456. var
  1457. helpins: tai;
  1458. begin
  1459. helpins:=instr.spilling_create_store(regs[regidx].tempreg,spilltemplist[regs[regidx].orgreg]);
  1460. list.insertafter(helpins,instr);
  1461. ungetregisterinline(list,helpins,regs[regidx].tempreg);
  1462. end;
  1463. procedure DoSpillReadWritten(pos: tai; regidx: longint);
  1464. var
  1465. helpins1, helpins2: tai;
  1466. begin
  1467. helpins1:=instr.spilling_create_load(spilltemplist[regs[regidx].orgreg],regs[regidx].tempreg);
  1468. if pos=nil then
  1469. list.insertafter(helpins1,list.first)
  1470. else
  1471. list.insertafter(helpins1,pos.next);
  1472. helpins2:=instr.spilling_create_store(regs[regidx].tempreg,spilltemplist[regs[regidx].orgreg]);
  1473. list.insertafter(helpins2,instr);
  1474. ungetregisterinline(list,helpins2,regs[regidx].tempreg);
  1475. forward_allocation(tai(helpins1.next),instr);
  1476. end;
  1477. procedure addreginfo(reg: tsuperregister; operation: topertype);
  1478. var
  1479. i, tmpindex: longint;
  1480. begin
  1481. tmpindex := regindex;
  1482. // did we already encounter this register?
  1483. for i := 0 to pred(regindex) do
  1484. if (regs[i].orgreg = reg) then
  1485. begin
  1486. tmpindex := i;
  1487. break;
  1488. end;
  1489. if tmpindex > high(regs) then
  1490. internalerror(2003120301);
  1491. regs[tmpindex].orgreg := reg;
  1492. if supregset_in(r,reg) then
  1493. begin
  1494. // add/update info on this register
  1495. regs[tmpindex].mustbespilled := true;
  1496. case operation of
  1497. operand_read:
  1498. regs[tmpindex].regread := true;
  1499. operand_write:
  1500. regs[tmpindex].regwritten := true;
  1501. operand_readwrite:
  1502. begin
  1503. regs[tmpindex].regread := true;
  1504. regs[tmpindex].regwritten := true;
  1505. end;
  1506. end;
  1507. spilled := true;
  1508. end;
  1509. inc(regindex,ord(regindex=tmpindex));
  1510. end;
  1511. procedure tryreplacereg(var reg: tregister);
  1512. var
  1513. i: longint;
  1514. supreg: tsuperregister;
  1515. begin
  1516. if (getregtype(reg) = R_INTREGISTER) then
  1517. begin
  1518. supreg := getsupreg(reg);
  1519. for i := 0 to pred(regindex) do
  1520. if (regs[i].mustbespilled) and
  1521. (regs[i].orgreg = supreg) then
  1522. begin
  1523. reg := regs[i].tempreg;
  1524. break;
  1525. end;
  1526. end;
  1527. end;
  1528. begin
  1529. result := false;
  1530. fillchar(regs,sizeof(regs),0);
  1531. for counter := low(regs) to high(regs) do
  1532. regs[counter].orgreg := RS_INVALID;
  1533. spilled := false;
  1534. regindex := 0;
  1535. { check whether and if so which and how (read/written) this instructions contains
  1536. registers that must be spilled }
  1537. for counter := 0 to instr.ops-1 do
  1538. with instr.oper[counter]^ do
  1539. begin
  1540. case typ of
  1541. top_reg:
  1542. begin
  1543. if (getregtype(reg) = regtype) then
  1544. addreginfo(getsupreg(reg),instr.spilling_get_operation_type(counter));
  1545. end;
  1546. top_ref:
  1547. begin
  1548. if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
  1549. begin
  1550. if (ref^.base <> NR_NO) then
  1551. addreginfo(getsupreg(ref^.base),operand_read);
  1552. if (ref^.index <> NR_NO) then
  1553. addreginfo(getsupreg(ref^.index),operand_read);
  1554. end;
  1555. end;
  1556. end;
  1557. end;
  1558. { if no spilling for this instruction we can leave }
  1559. if not spilled then
  1560. exit;
  1561. { generate the spilling code }
  1562. result := true;
  1563. for counter := 0 to pred(regindex) do
  1564. begin
  1565. if regs[counter].mustbespilled then
  1566. begin
  1567. pos := get_insert_pos(Tai(instr.previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg);
  1568. getregisterinline(list,pos,defaultsub,regs[counter].tempreg);
  1569. if regs[counter].regread then
  1570. if regs[counter].regwritten then
  1571. DoSpillReadWritten(pos,counter)
  1572. else
  1573. DoSpillRead(pos,counter)
  1574. else
  1575. DoSpillWritten(pos,counter)
  1576. end;
  1577. end;
  1578. { substitute registers }
  1579. for counter := 0 to instr.ops-1 do
  1580. with instr.oper[counter]^ do
  1581. begin
  1582. case typ of
  1583. top_reg:
  1584. begin
  1585. tryreplacereg(reg);
  1586. end;
  1587. top_ref:
  1588. begin
  1589. tryreplacereg(ref^.base);
  1590. tryreplacereg(ref^.index);
  1591. end;
  1592. end;
  1593. end;
  1594. end;
  1595. end.
  1596. {
  1597. $Log$
  1598. Revision 1.112 2004-01-12 16:37:59 peter
  1599. * moved spilling code from taicpu to rg
  1600. Revision 1.109 2003/12/26 14:02:30 peter
  1601. * sparc updates
  1602. * use registertype in spill_register
  1603. Revision 1.108 2003/12/22 23:09:34 peter
  1604. * only report unreleased imaginary registers
  1605. Revision 1.107 2003/12/22 22:13:46 peter
  1606. * made decrease_degree working, but not really fixed
  1607. Revision 1.106 2003/12/18 17:06:21 florian
  1608. * arm compiler compilation fixed
  1609. Revision 1.105 2003/12/17 21:59:05 peter
  1610. * don't insert dealloc before alloc of the same register
  1611. Revision 1.104 2003/12/16 09:41:44 daniel
  1612. * Automatic conversion from integer constants to pointer constants is no
  1613. longer done except in Delphi mode
  1614. Revision 1.103 2003/12/15 21:25:49 peter
  1615. * reg allocations for imaginary register are now inserted just
  1616. before reg allocation
  1617. * tregister changed to enum to allow compile time check
  1618. * fixed several tregister-tsuperregister errors
  1619. Revision 1.102 2003/12/15 16:37:47 daniel
  1620. * More microoptimizations
  1621. Revision 1.101 2003/12/15 15:58:58 peter
  1622. * fix statedebug compile
  1623. Revision 1.100 2003/12/14 20:24:28 daniel
  1624. * Register allocator speed optimizations
  1625. - Worklist no longer a ringbuffer
  1626. - No find operations are left
  1627. - Simplify now done in constant time
  1628. - unusedregs is now a Tsuperregisterworklist
  1629. - Microoptimizations
  1630. Revision 1.99 2003/12/12 17:16:17 peter
  1631. * rg[tregistertype] added in tcg
  1632. Revision 1.98 2003/12/04 23:27:32 peter
  1633. * remove redundant calls to add_edge_used
  1634. Revision 1.97 2003/11/29 17:36:41 peter
  1635. * check for add_move_instruction
  1636. Revision 1.96 2003/11/24 15:17:37 florian
  1637. * changed some types to prevend range check errors
  1638. Revision 1.95 2003/11/10 19:05:50 peter
  1639. * fixed alias/colouring > 255
  1640. Revision 1.94 2003/11/07 15:58:32 florian
  1641. * Florian's culmutative nr. 1; contains:
  1642. - invalid calling conventions for a certain cpu are rejected
  1643. - arm softfloat calling conventions
  1644. - -Sp for cpu dependend code generation
  1645. - several arm fixes
  1646. - remaining code for value open array paras on heap
  1647. Revision 1.93 2003/10/30 16:22:40 peter
  1648. * call firstpass before allocation and codegeneration is started
  1649. * move leftover code from pass_2.generatecode() to psub
  1650. Revision 1.92 2003/10/29 21:29:14 jonas
  1651. * some ALLOWDUPREG improvements
  1652. Revision 1.91 2003/10/21 15:15:36 peter
  1653. * taicpu_abstract.oper[] changed to pointers
  1654. Revision 1.90 2003/10/19 12:36:36 florian
  1655. * improved speed; reduced memory usage of the interference bitmap
  1656. Revision 1.89 2003/10/19 01:34:30 florian
  1657. * some ppc stuff fixed
  1658. * memory leak fixed
  1659. Revision 1.88 2003/10/18 15:41:26 peter
  1660. * made worklists dynamic in size
  1661. Revision 1.87 2003/10/17 16:16:08 peter
  1662. * fixed last commit
  1663. Revision 1.86 2003/10/17 15:25:18 florian
  1664. * fixed more ppc stuff
  1665. Revision 1.85 2003/10/17 14:38:32 peter
  1666. * 64k registers supported
  1667. * fixed some memory leaks
  1668. Revision 1.84 2003/10/11 16:06:42 florian
  1669. * fixed some MMX<->SSE
  1670. * started to fix ppc, needs an overhaul
  1671. + stabs info improve for spilling, not sure if it works correctly/completly
  1672. - MMX_SUPPORT removed from Makefile.fpc
  1673. Revision 1.83 2003/10/10 17:48:14 peter
  1674. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  1675. * tregisteralloctor renamed to trgobj
  1676. * removed rgobj from a lot of units
  1677. * moved location_* and reference_* to cgobj
  1678. * first things for mmx register allocation
  1679. Revision 1.82 2003/10/09 21:31:37 daniel
  1680. * Register allocator splitted, ans abstract now
  1681. Revision 1.81 2003/10/01 20:34:49 peter
  1682. * procinfo unit contains tprocinfo
  1683. * cginfo renamed to cgbase
  1684. * moved cgmessage to verbose
  1685. * fixed ppc and sparc compiles
  1686. Revision 1.80 2003/09/30 19:54:42 peter
  1687. * reuse registers with the least conflicts
  1688. Revision 1.79 2003/09/29 20:58:56 peter
  1689. * optimized releasing of registers
  1690. Revision 1.78 2003/09/28 13:41:12 peter
  1691. * return reg 255 when allowdupreg is defined
  1692. Revision 1.77 2003/09/25 16:19:32 peter
  1693. * fix filepositions
  1694. * insert spill temp allocations at the start of the proc
  1695. Revision 1.76 2003/09/16 16:17:01 peter
  1696. * varspez in calls to push_addr_param
  1697. Revision 1.75 2003/09/12 19:07:42 daniel
  1698. * Fixed fast spilling functionality by re-adding the code that initializes
  1699. precoloured nodes to degree 255. I would like to play hangman on the one
  1700. who removed that code.
  1701. Revision 1.74 2003/09/11 11:54:59 florian
  1702. * improved arm code generation
  1703. * move some protected and private field around
  1704. * the temp. register for register parameters/arguments are now released
  1705. before the move to the parameter register is done. This improves
  1706. the code in a lot of cases.
  1707. Revision 1.73 2003/09/09 20:59:27 daniel
  1708. * Adding register allocation order
  1709. Revision 1.72 2003/09/09 15:55:44 peter
  1710. * use register with least interferences in spillregister
  1711. Revision 1.71 2003/09/07 22:09:35 peter
  1712. * preparations for different default calling conventions
  1713. * various RA fixes
  1714. Revision 1.70 2003/09/03 21:06:45 peter
  1715. * fixes for FPU register allocation
  1716. Revision 1.69 2003/09/03 15:55:01 peter
  1717. * NEWRA branch merged
  1718. Revision 1.68 2003/09/03 11:18:37 florian
  1719. * fixed arm concatcopy
  1720. + arm support in the common compiler sources added
  1721. * moved some generic cg code around
  1722. + tfputype added
  1723. * ...
  1724. Revision 1.67.2.5 2003/08/31 20:44:07 peter
  1725. * fixed getexplicitregisterint tregister value
  1726. Revision 1.67.2.4 2003/08/31 20:40:50 daniel
  1727. * Fixed add_edges_used
  1728. Revision 1.67.2.3 2003/08/29 17:28:59 peter
  1729. * next batch of updates
  1730. Revision 1.67.2.2 2003/08/28 18:35:08 peter
  1731. * tregister changed to cardinal
  1732. Revision 1.67.2.1 2003/08/27 19:55:54 peter
  1733. * first tregister patch
  1734. Revision 1.67 2003/08/23 10:46:21 daniel
  1735. * Register allocator bugfix for h2pas
  1736. Revision 1.66 2003/08/17 16:59:20 jonas
  1737. * fixed regvars so they work with newra (at least for ppc)
  1738. * fixed some volatile register bugs
  1739. + -dnotranslation option for -dnewra, which causes the registers not to
  1740. be translated from virtual to normal registers. Requires support in
  1741. the assembler writer as well, which is only implemented in aggas/
  1742. agppcgas currently
  1743. Revision 1.65 2003/08/17 14:32:48 daniel
  1744. * Precoloured nodes now have an infinite degree approached with 255,
  1745. like they should.
  1746. Revision 1.64 2003/08/17 08:48:02 daniel
  1747. * Another register allocator bug fixed.
  1748. * usable_registers_cnt set to 6 for i386
  1749. Revision 1.63 2003/08/09 18:56:54 daniel
  1750. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  1751. allocator
  1752. * Some preventive changes to i386 spillinh code
  1753. Revision 1.62 2003/08/03 14:09:50 daniel
  1754. * Fixed a register allocator bug
  1755. * Figured out why -dnewra generates superfluous "mov reg1,reg2"
  1756. statements: changes in location_force. These moves are now no longer
  1757. constrained so they are optimized away.
  1758. Revision 1.61 2003/07/21 13:32:39 jonas
  1759. * add_edges_used() is now also called for registers allocated with
  1760. getexplicitregisterint()
  1761. * writing the intereference graph is now only done with -dradebug2 and
  1762. the created files are now called "igraph.<module_name>"
  1763. Revision 1.60 2003/07/06 15:31:21 daniel
  1764. * Fixed register allocator. *Lots* of fixes.
  1765. Revision 1.59 2003/07/06 15:00:47 jonas
  1766. * fixed my previous completely broken commit. It's not perfect though,
  1767. registers > last_int_supreg and < max_intreg may still be "translated"
  1768. Revision 1.58 2003/07/06 14:45:05 jonas
  1769. * support integer registers that are not managed by newra (ie. don't
  1770. translate register numbers that fall outside the range
  1771. first_int_supreg..last_int_supreg)
  1772. Revision 1.57 2003/07/02 22:18:04 peter
  1773. * paraloc splitted in callerparaloc,calleeparaloc
  1774. * sparc calling convention updates
  1775. Revision 1.56 2003/06/17 16:34:44 jonas
  1776. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  1777. * renamed all_intregisters to volatile_intregisters and made it
  1778. processor dependent
  1779. Revision 1.55 2003/06/14 14:53:50 jonas
  1780. * fixed newra cycle for x86
  1781. * added constants for indicating source and destination operands of the
  1782. "move reg,reg" instruction to aasmcpu (and use those in rgobj)
  1783. Revision 1.54 2003/06/13 21:19:31 peter
  1784. * current_procdef removed, use current_procinfo.procdef instead
  1785. Revision 1.53 2003/06/12 21:11:10 peter
  1786. * ungetregisterfpu gets size parameter
  1787. Revision 1.52 2003/06/12 16:43:07 peter
  1788. * newra compiles for sparc
  1789. Revision 1.51 2003/06/09 14:54:26 jonas
  1790. * (de)allocation of registers for parameters is now performed properly
  1791. (and checked on the ppc)
  1792. - removed obsolete allocation of all parameter registers at the start
  1793. of a procedure (and deallocation at the end)
  1794. Revision 1.50 2003/06/03 21:11:09 peter
  1795. * cg.a_load_* get a from and to size specifier
  1796. * makeregsize only accepts newregister
  1797. * i386 uses generic tcgnotnode,tcgunaryminus
  1798. Revision 1.49 2003/06/03 13:01:59 daniel
  1799. * Register allocator finished
  1800. Revision 1.48 2003/06/01 21:38:06 peter
  1801. * getregisterfpu size parameter added
  1802. * op_const_reg size parameter added
  1803. * sparc updates
  1804. Revision 1.47 2003/05/31 20:31:11 jonas
  1805. * set inital costs of assigning a variable to a register to 120 for
  1806. non-i386, because the used register must be store to memory at the
  1807. start and loaded again at the end
  1808. Revision 1.46 2003/05/30 18:55:21 jonas
  1809. * fixed several regvar related bugs for non-i386. make cycle with -Or now
  1810. works for ppc
  1811. Revision 1.45 2003/05/30 12:36:13 jonas
  1812. * use as little different registers on the ppc until newra is released,
  1813. since every used register must be saved
  1814. Revision 1.44 2003/05/17 13:30:08 jonas
  1815. * changed tt_persistant to tt_persistent :)
  1816. * tempcreatenode now doesn't accept a boolean anymore for persistent
  1817. temps, but a ttemptype, so you can also create ansistring temps etc
  1818. Revision 1.43 2003/05/16 14:33:31 peter
  1819. * regvar fixes
  1820. Revision 1.42 2003/04/26 20:03:49 daniel
  1821. * Bug fix in simplify
  1822. Revision 1.41 2003/04/25 20:59:35 peter
  1823. * removed funcretn,funcretsym, function result is now in varsym
  1824. and aliases for result and function name are added using absolutesym
  1825. * vs_hidden parameter for funcret passed in parameter
  1826. * vs_hidden fixes
  1827. * writenode changed to printnode and released from extdebug
  1828. * -vp option added to generate a tree.log with the nodetree
  1829. * nicer printnode for statements, callnode
  1830. Revision 1.40 2003/04/25 08:25:26 daniel
  1831. * Ifdefs around a lot of calls to cleartempgen
  1832. * Fixed registers that are allocated but not freed in several nodes
  1833. * Tweak to register allocator to cause less spills
  1834. * 8-bit registers now interfere with esi,edi and ebp
  1835. Compiler can now compile rtl successfully when using new register
  1836. allocator
  1837. Revision 1.39 2003/04/23 20:23:06 peter
  1838. * compile fix for no-newra
  1839. Revision 1.38 2003/04/23 14:42:07 daniel
  1840. * Further register allocator work. Compiler now smaller with new
  1841. allocator than without.
  1842. * Somebody forgot to adjust ppu version number
  1843. Revision 1.37 2003/04/22 23:50:23 peter
  1844. * firstpass uses expectloc
  1845. * checks if there are differences between the expectloc and
  1846. location.loc from secondpass in EXTDEBUG
  1847. Revision 1.36 2003/04/22 10:09:35 daniel
  1848. + Implemented the actual register allocator
  1849. + Scratch registers unavailable when new register allocator used
  1850. + maybe_save/maybe_restore unavailable when new register allocator used
  1851. Revision 1.35 2003/04/21 19:16:49 peter
  1852. * count address regs separate
  1853. Revision 1.34 2003/04/17 16:48:21 daniel
  1854. * Added some code to keep track of move instructions in register
  1855. allocator
  1856. Revision 1.33 2003/04/17 07:50:24 daniel
  1857. * Some work on interference graph construction
  1858. Revision 1.32 2003/03/28 19:16:57 peter
  1859. * generic constructor working for i386
  1860. * remove fixed self register
  1861. * esi added as address register for i386
  1862. Revision 1.31 2003/03/11 21:46:24 jonas
  1863. * lots of new regallocator fixes, both in generic and ppc-specific code
  1864. (ppc compiler still can't compile the linux system unit though)
  1865. Revision 1.30 2003/03/09 21:18:59 olle
  1866. + added cutils to the uses clause
  1867. Revision 1.29 2003/03/08 20:36:41 daniel
  1868. + Added newra version of Ti386shlshrnode
  1869. + Added interference graph construction code
  1870. Revision 1.28 2003/03/08 13:59:16 daniel
  1871. * Work to handle new register notation in ag386nsm
  1872. + Added newra version of Ti386moddivnode
  1873. Revision 1.27 2003/03/08 10:53:48 daniel
  1874. * Created newra version of secondmul in n386add.pas
  1875. Revision 1.26 2003/03/08 08:59:07 daniel
  1876. + $define newra will enable new register allocator
  1877. + getregisterint will return imaginary registers with $newra
  1878. + -sr switch added, will skip register allocation so you can see
  1879. the direct output of the code generator before register allocation
  1880. Revision 1.25 2003/02/26 20:50:45 daniel
  1881. * Fixed ungetreference
  1882. Revision 1.24 2003/02/19 22:39:56 daniel
  1883. * Fixed a few issues
  1884. Revision 1.23 2003/02/19 22:00:14 daniel
  1885. * Code generator converted to new register notation
  1886. - Horribily outdated todo.txt removed
  1887. Revision 1.22 2003/02/02 19:25:54 carl
  1888. * Several bugfixes for m68k target (register alloc., opcode emission)
  1889. + VIS target
  1890. + Generic add more complete (still not verified)
  1891. Revision 1.21 2003/01/08 18:43:57 daniel
  1892. * Tregister changed into a record
  1893. Revision 1.20 2002/10/05 12:43:28 carl
  1894. * fixes for Delphi 6 compilation
  1895. (warning : Some features do not work under Delphi)
  1896. Revision 1.19 2002/08/23 16:14:49 peter
  1897. * tempgen cleanup
  1898. * tt_noreuse temp type added that will be used in genentrycode
  1899. Revision 1.18 2002/08/17 22:09:47 florian
  1900. * result type handling in tcgcal.pass_2 overhauled
  1901. * better tnode.dowrite
  1902. * some ppc stuff fixed
  1903. Revision 1.17 2002/08/17 09:23:42 florian
  1904. * first part of procinfo rewrite
  1905. Revision 1.16 2002/08/06 20:55:23 florian
  1906. * first part of ppc calling conventions fix
  1907. Revision 1.15 2002/08/05 18:27:48 carl
  1908. + more more more documentation
  1909. + first version include/exclude (can't test though, not enough scratch for i386 :()...
  1910. Revision 1.14 2002/08/04 19:06:41 carl
  1911. + added generic exception support (still does not work!)
  1912. + more documentation
  1913. Revision 1.13 2002/07/07 09:52:32 florian
  1914. * powerpc target fixed, very simple units can be compiled
  1915. * some basic stuff for better callparanode handling, far from being finished
  1916. Revision 1.12 2002/07/01 18:46:26 peter
  1917. * internal linker
  1918. * reorganized aasm layer
  1919. Revision 1.11 2002/05/18 13:34:17 peter
  1920. * readded missing revisions
  1921. Revision 1.10 2002/05/16 19:46:44 carl
  1922. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1923. + try to fix temp allocation (still in ifdef)
  1924. + generic constructor calls
  1925. + start of tassembler / tmodulebase class cleanup
  1926. Revision 1.8 2002/04/21 15:23:03 carl
  1927. + makeregsize
  1928. + changeregsize is now a local routine
  1929. Revision 1.7 2002/04/20 21:32:25 carl
  1930. + generic FPC_CHECKPOINTER
  1931. + first parameter offset in stack now portable
  1932. * rename some constants
  1933. + move some cpu stuff to other units
  1934. - remove unused constents
  1935. * fix stacksize for some targets
  1936. * fix generic size problems which depend now on EXTEND_SIZE constant
  1937. Revision 1.6 2002/04/15 19:03:31 carl
  1938. + reg2str -> std_reg2str()
  1939. Revision 1.5 2002/04/06 18:13:01 jonas
  1940. * several powerpc-related additions and fixes
  1941. Revision 1.4 2002/04/04 19:06:04 peter
  1942. * removed unused units
  1943. * use tlocation.size in cg.a_*loc*() routines
  1944. Revision 1.3 2002/04/02 17:11:29 peter
  1945. * tlocation,treference update
  1946. * LOC_CONSTANT added for better constant handling
  1947. * secondadd splitted in multiple routines
  1948. * location_force_reg added for loading a location to a register
  1949. of a specified size
  1950. * secondassignment parses now first the right and then the left node
  1951. (this is compatible with Kylix). This saves a lot of push/pop especially
  1952. with string operations
  1953. * adapted some routines to use the new cg methods
  1954. Revision 1.2 2002/04/01 19:24:25 jonas
  1955. * fixed different parameter name in interface and implementation
  1956. declaration of a method (only 1.0.x detected this)
  1957. Revision 1.1 2002/03/31 20:26:36 jonas
  1958. + a_loadfpu_* and a_loadmm_* methods in tcg
  1959. * register allocation is now handled by a class and is mostly processor
  1960. independent (+rgobj.pas and i386/rgcpu.pas)
  1961. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1962. * some small improvements and fixes to the optimizer
  1963. * some register allocation fixes
  1964. * some fpuvaroffset fixes in the unary minus node
  1965. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1966. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1967. also better optimizable)
  1968. * fixed and optimized register saving/restoring for new/dispose nodes
  1969. * LOC_FPU locations now also require their "register" field to be set to
  1970. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1971. - list field removed of the tnode class because it's not used currently
  1972. and can cause hard-to-find bugs
  1973. }