rgobj.pas 70 KB

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