2
Copyright (c) 1998-2002 by Florian Klaempfl
4
This unit implements the base class for the register allocator
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
****************************************************************************
24
{ Allow duplicate allocations, can be used to get the .s file written }
25
{ $define ALLOWDUPREG}
34
aasmbase,aasmtai,aasmdata,aasmcpu,
35
cclasses,globtype,cgbase,cgutils,
41
The interference bitmap contains of 2 layers:
42
layer 1 - 256*256 blocks with pointers to layer 2 blocks
43
layer 2 - blocks of 32*256 (32 bytes = 256 bits)
45
Tinterferencebitmap2 = array[byte] of set of byte;
46
Pinterferencebitmap2 = ^Tinterferencebitmap2;
47
Tinterferencebitmap1 = array[byte] of Pinterferencebitmap2;
48
pinterferencebitmap1 = ^tinterferencebitmap1;
50
Tinterferencebitmap=class
54
fbitmap : pinterferencebitmap1;
55
function getbitmap(x,y:tsuperregister):boolean;
56
procedure setbitmap(x,y:tsuperregister;b:boolean);
59
destructor destroy;override;
60
property bitmap[x,y:tsuperregister]:boolean read getbitmap write setbitmap;default;
63
Tmovelistheader=record
66
sorted_until : cardinal;
70
header : Tmovelistheader;
71
data : array[tsuperregister] of Tlinkedlistitem;
75
{In the register allocator we keep track of move instructions.
76
These instructions are moved between five linked lists. There
77
is also a linked list per register to keep track about the moves
78
it is associated with. Because we need to determine quickly in
79
which of the five lists it is we add anu enumeradtion to each
82
Tmoveset=(ms_coalesced_moves,ms_constrained_moves,ms_frozen_moves,
83
ms_worklist_moves,ms_active_moves);
84
Tmoveins=class(Tlinkedlistitem)
89
Treginfoflag=(ri_coalesced,ri_selected);
90
Treginfoflagset=set of Treginfoflag;
95
subreg : tsubregister;
96
alias : Tsuperregister;
97
{ The register allocator assigns each register a colour }
98
colour : Tsuperregister;
100
adjlist : Psuperregisterworklist;
101
degree : TSuperregister;
102
flags : Treginfoflagset;
106
tspillreginfo = record
107
spillreg : tregister;
108
orgreg : tsuperregister;
110
regread,regwritten, mustbespilled: boolean;
112
tspillregsinfo = array[0..3] of tspillreginfo;
114
Tspill_temp_list=array[tsuperregister] of Treference;
116
{#------------------------------------------------------------------
118
This class implements the default register allocator. It is used by the
119
code generator to allocate and free registers which might be valid
120
across nodes. It also contains utility routines related to registers.
122
Some of the methods in this class should be overriden
123
by cpu-specific implementations.
125
--------------------------------------------------------------------}
127
preserved_by_proc : tcpuregisterset;
128
used_in_proc : tcpuregisterset;
130
constructor create(Aregtype:Tregistertype;
131
Adefaultsub:Tsubregister;
132
const Ausable:array of tsuperregister;
133
Afirst_imaginary:Tsuperregister;
134
Apreserved_by_proc:Tcpuregisterset);
135
destructor destroy;override;
137
{# Allocate a register. An internalerror will be generated if there is
138
no more free registers which can be allocated.}
139
function getregister(list:TAsmList;subreg:Tsubregister):Tregister;virtual;
140
{# Get the register specified.}
141
procedure getcpuregister(list:TAsmList;r:Tregister);virtual;
142
procedure ungetcpuregister(list:TAsmList;r:Tregister);virtual;
143
{# Get multiple registers specified.}
144
procedure alloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
145
{# Free multiple registers specified.}
146
procedure dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
147
function uses_registers:boolean;virtual;
148
procedure add_reg_instruction(instr:Tai;r:tregister);
149
procedure add_move_instruction(instr:Taicpu);
150
{# Do the register allocation.}
151
procedure do_register_allocation(list:TAsmList;headertai:tai);virtual;
152
{ Adds an interference edge.
153
don't move this to the protected section, the arm cg requires to access this (FK) }
154
procedure add_edge(u,v:Tsuperregister);
155
{ translates a single given imaginary register to it's real register }
156
procedure translate_register(var reg : tregister);
158
regtype : Tregistertype;
159
{ default subregister used }
160
defaultsub : tsubregister;
161
live_registers:Tsuperregisterworklist;
162
{ can be overriden to add cpu specific interferences }
163
procedure add_cpu_interferences(p : tai);virtual;
164
procedure add_constraints(reg:Tregister);virtual;
165
function get_alias(n:Tsuperregister):Tsuperregister;
166
function getregisterinline(list:TAsmList;subreg:Tsubregister):Tregister;
167
procedure ungetregisterinline(list:TAsmList;r:Tregister);
168
function get_spill_subreg(r : tregister) : tsubregister;virtual;
169
function do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;virtual;
170
procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
171
procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);virtual;
173
function instr_spill_register(list:TAsmList;
175
const r:Tsuperregisterset;
176
const spilltemplist:Tspill_temp_list): boolean;virtual;
178
do_extend_live_range_backwards: boolean;
179
{# First imaginary register.}
180
first_imaginary : Tsuperregister;
181
{# Highest register allocated until now.}
185
maxreg : Tsuperregister;
186
usable_registers_cnt : word;
187
usable_registers : array[0..maxcpuregister-1] of tsuperregister;
188
ibitmap : Tinterferencebitmap;
194
selectstack : tsuperregisterworklist;
199
constrained_moves : Tlinkedlist;
201
backwards_was_first : tsuperregisterset;
204
procedure writegraph(loopidx:longint);
206
{# Disposes of the reginfo array.}
207
procedure dispose_reginfo;
208
{# Prepare the register colouring.}
209
procedure prepare_colouring;
210
{# Clean up after register colouring.}
211
procedure epilogue_colouring;
212
{# Colour the registers; that is do the register allocation.}
213
procedure colour_registers;
214
procedure insert_regalloc_info(list:TAsmList;u:tsuperregister);
215
procedure insert_regalloc_info_all(list:TAsmList);
216
procedure generate_interference_graph(list:TAsmList;headertai:tai);
217
{ translates the registers in the given assembler list }
218
procedure translate_registers(list:TAsmList);
219
function spill_registers(list:TAsmList;headertai:tai):boolean;virtual;
220
function getnewreg(subreg:tsubregister):tsuperregister;
221
procedure add_edges_used(u:Tsuperregister);
222
procedure add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
223
function move_related(n:Tsuperregister):boolean;
224
procedure make_work_list;
225
procedure sort_simplify_worklist;
226
procedure enable_moves(n:Tsuperregister);
227
procedure decrement_degree(m:Tsuperregister);
229
procedure add_worklist(u:Tsuperregister);
230
function adjacent_ok(u,v:Tsuperregister):boolean;
231
function conservative(u,v:Tsuperregister):boolean;
232
procedure combine(u,v:Tsuperregister);
234
procedure freeze_moves(u:Tsuperregister);
236
procedure select_spill;
237
procedure assign_colours;
238
procedure clear_interferences(u:Tsuperregister);
239
procedure set_live_range_backwards(b: boolean);
241
property extend_live_range_backwards: boolean read do_extend_live_range_backwards write set_live_range_backwards;
246
last_reg = high(tsuperregister)-1;
247
maxspillingcounter = 20;
254
globals,verbose,tgobj,procinfo;
257
procedure sort_movelist(ml:Pmovelist);
259
{Ok, sorting pointers is silly, but it does the job to make Trgobj.combine
268
if header.count<2 then
271
while 2*p<header.count do
275
for h:=p to header.count-1 do
280
if ptruint(data[i-p])<=ptruint(t) then
289
header.sorted_until:=header.count-1;
293
{******************************************************************************
295
******************************************************************************}
297
constructor tinterferencebitmap.create;
301
getmem(fbitmap,sizeof(tinterferencebitmap1)*2);
302
fillchar(fbitmap^,sizeof(tinterferencebitmap1)*2,0);
306
destructor tinterferencebitmap.destroy;
313
if assigned(fbitmap[i,j]) then
314
dispose(fbitmap[i,j]);
319
function tinterferencebitmap.getbitmap(x,y:tsuperregister):boolean;
321
page : pinterferencebitmap2;
324
if (x shr 8>maxx1) then
326
page:=fbitmap[x shr 8,y shr 8];
327
result:=assigned(page) and
328
((x and $ff) in page^[y and $ff]);
332
procedure tinterferencebitmap.setbitmap(x,y:tsuperregister;b:boolean);
340
reallocmem(fbitmap,sizeof(tinterferencebitmap1)*(x1+1));
341
fillchar(fbitmap[maxx1+1],sizeof(tinterferencebitmap1)*(x1-maxx1),0);
344
if not assigned(fbitmap[x1,y1]) then
349
fillchar(fbitmap[x1,y1]^,sizeof(tinterferencebitmap2),0);
352
include(fbitmap[x1,y1]^[y and $ff],(x and $ff))
354
exclude(fbitmap[x1,y1]^[y and $ff],(x and $ff));
358
{******************************************************************************
360
******************************************************************************}
362
constructor trgobj.create(Aregtype:Tregistertype;
363
Adefaultsub:Tsubregister;
364
const Ausable:array of tsuperregister;
365
Afirst_imaginary:Tsuperregister;
366
Apreserved_by_proc:Tcpuregisterset);
370
{ empty super register sets can cause very strange problems }
371
if high(Ausable)=-1 then
372
internalerror(200210181);
373
extend_live_range_backwards := false;
374
supregset_reset(extended_backwards,false,high(tsuperregister));
375
first_imaginary:=Afirst_imaginary;
376
maxreg:=Afirst_imaginary;
378
defaultsub:=Adefaultsub;
379
preserved_by_proc:=Apreserved_by_proc;
382
{ Get reginfo for CPU registers }
383
maxreginfo:=first_imaginary;
385
worklist_moves:=Tlinkedlist.create;
386
reginfo:=allocmem(first_imaginary*sizeof(treginfo));
387
for i:=0 to first_imaginary-1 do
389
reginfo[i].degree:=high(tsuperregister);
390
reginfo[i].alias:=RS_INVALID;
393
fillchar(usable_registers,sizeof(usable_registers),0);
394
for i:=low(Ausable) to high(Ausable) do
395
usable_registers[i]:=Ausable[i];
396
usable_registers_cnt:=high(Ausable)+1;
397
{ Initialize Worklists }
399
simplifyworklist.init;
406
destructor trgobj.destroy;
410
simplifyworklist.done;
420
procedure Trgobj.dispose_reginfo;
422
var i:Tsuperregister;
427
for i:=0 to maxreg-1 do
431
dispose(adjlist,done);
432
if movelist<>nil then
440
function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
442
oldmaxreginfo : tsuperregister;
446
if maxreg>=last_reg then
447
Message(parser_f_too_complex_proc);
448
if maxreg>=maxreginfo then
450
oldmaxreginfo:=maxreginfo;
452
if maxreginfoinc>last_reg-maxreginfo then
456
inc(maxreginfo,maxreginfoinc);
457
if maxreginfoinc<256 then
458
maxreginfoinc:=maxreginfoinc*2;
460
reallocmem(reginfo,maxreginfo*sizeof(treginfo));
461
{ Do we really need it to clear it ? At least for 1.0.x (PFV) }
462
fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
464
reginfo[result].subreg:=subreg;
468
function trgobj.getregister(list:TAsmList;subreg:Tsubregister):Tregister;
472
InternalError(2004020901);
474
if defaultsub=R_SUBNONE then
475
result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
477
result:=newreg(regtype,getnewreg(subreg),subreg);
481
function trgobj.uses_registers:boolean;
483
result:=(maxreg>first_imaginary);
487
procedure trgobj.ungetcpuregister(list:TAsmList;r:Tregister);
489
if (getsupreg(r)>=first_imaginary) then
490
InternalError(2004020901);
491
list.concat(Tai_regalloc.dealloc(r,nil));
495
procedure trgobj.getcpuregister(list:TAsmList;r:Tregister);
497
supreg:Tsuperregister;
499
supreg:=getsupreg(r);
500
if supreg>=first_imaginary then
501
internalerror(2003121503);
502
include(used_in_proc,supreg);
503
list.concat(Tai_regalloc.alloc(r,nil));
507
procedure trgobj.alloccpuregisters(list:TAsmList;const r:Tcpuregisterset);
509
var i:Tsuperregister;
512
for i:=0 to first_imaginary-1 do
514
getcpuregister(list,newreg(regtype,i,defaultsub));
518
procedure trgobj.dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);
520
var i:Tsuperregister;
523
for i:=0 to first_imaginary-1 do
525
ungetcpuregister(list,newreg(regtype,i,defaultsub));
529
procedure trgobj.do_register_allocation(list:TAsmList;headertai:tai);
531
spillingcounter:byte;
534
{ Insert regalloc info for imaginary registers }
535
insert_regalloc_info_all(list);
536
ibitmap:=tinterferencebitmap.create;
537
generate_interference_graph(list,headertai);
538
{ Don't do the real allocation when -sr is passed }
539
if (cs_no_regalloc in current_settings.globalswitches) then
541
{Do register allocation.}
548
if spillednodes.length<>0 then
550
inc(spillingcounter);
551
if spillingcounter>maxspillingcounter then
554
{ Only exit here so the .s file is still generated. Assembling
555
the file will still trigger an error }
558
internalerror(200309041);
561
endspill:=not spill_registers(list,headertai);
565
translate_registers(list);
566
{ we need the translation table for debugging info and verbose assembler output (FK)
572
procedure trgobj.add_constraints(reg:Tregister);
578
procedure trgobj.add_edge(u,v:Tsuperregister);
580
{This procedure will add an edge to the virtual interference graph.}
582
procedure addadj(u,v:Tsuperregister);
594
if (u<>v) and not(ibitmap[v,u]) then
598
{Precoloured nodes are not stored in the interference graph.}
599
if (u>=first_imaginary) then
601
if (v>=first_imaginary) then
607
procedure trgobj.add_edges_used(u:Tsuperregister);
612
with live_registers do
614
for i:=0 to length-1 do
615
add_edge(u,get_alias(buf^[i]));
619
procedure trgobj.writegraph(loopidx:longint);
621
{This procedure writes out the current interference graph in the
629
assign(f,'igraph'+tostr(loopidx));
631
writeln(f,'Interference graph');
636
write(f,hexstr(i,1));
640
write(f,'0123456789ABCDEF');
642
for i:=0 to maxreg-1 do
644
write(f,hexstr(i,2):4);
645
for j:=0 to maxreg-1 do
656
procedure trgobj.add_to_movelist(u:Tsuperregister;data:Tlinkedlistitem);
662
getmem(movelist,sizeof(tmovelistheader)+60*sizeof(pointer));
663
movelist^.header.maxcount:=60;
664
movelist^.header.count:=0;
665
movelist^.header.sorted_until:=0;
669
if movelist^.header.count>=movelist^.header.maxcount then
671
movelist^.header.maxcount:=movelist^.header.maxcount*2;
672
reallocmem(movelist,sizeof(tmovelistheader)+movelist^.header.maxcount*sizeof(pointer));
675
movelist^.data[movelist^.header.count]:=data;
676
inc(movelist^.header.count);
681
procedure trgobj.set_live_range_backwards(b: boolean);
685
{ new registers may be allocated }
686
supregset_reset(backwards_was_first,false,high(tsuperregister));
687
do_extend_live_range_backwards := true;
690
do_extend_live_range_backwards := false;
694
procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
696
supreg : tsuperregister;
698
supreg:=getsupreg(r);
700
if not (cs_no_regalloc in current_settings.globalswitches) and
701
(supreg>=maxreginfo) then
702
internalerror(200411061);
704
if supreg>=first_imaginary then
705
with reginfo[supreg] do
707
if not(extend_live_range_backwards) then
709
if not assigned(live_start) then
715
if not supregset_in(extended_backwards,supreg) then
717
supregset_include(extended_backwards,supreg);
719
if not assigned(live_end) then
721
supregset_include(backwards_was_first,supreg);
727
if supregset_in(backwards_was_first,supreg) then
735
procedure trgobj.add_move_instruction(instr:Taicpu);
737
{This procedure notifies a certain as a move instruction so the
738
register allocator can try to eliminate it.}
741
ssupreg,dsupreg:Tsuperregister;
745
if (instr.oper[O_MOV_SOURCE]^.typ<>top_reg) or
746
(instr.oper[O_MOV_DEST]^.typ<>top_reg) then
747
internalerror(200311291);
750
i.moveset:=ms_worklist_moves;
751
worklist_moves.insert(i);
752
ssupreg:=getsupreg(instr.oper[O_MOV_SOURCE]^.reg);
753
add_to_movelist(ssupreg,i);
754
dsupreg:=getsupreg(instr.oper[O_MOV_DEST]^.reg);
755
if ssupreg<>dsupreg then
756
{Avoid adding the same move instruction twice to a single register.}
757
add_to_movelist(dsupreg,i);
762
function trgobj.move_related(n:Tsuperregister):boolean;
769
if movelist<>nil then
771
for i:=0 to header.count-1 do
772
if Tmoveins(data[i]).moveset in [ms_worklist_moves,ms_active_moves] then
779
procedure Trgobj.sort_simplify_worklist;
781
{Sorts the simplifyworklist by the number of interferences the
782
registers in it cause. This allows simplify to execute in
785
var p,h,i,leni,lent:word;
787
adji,adjt:Psuperregisterworklist;
790
with simplifyworklist do
799
for h:=p to length-1 do
803
adjt:=reginfo[buf^[i]].adjlist;
808
adji:=reginfo[buf^[i-p]].adjlist;
824
procedure trgobj.make_work_list;
826
var n:Tsuperregister;
829
{If we have 7 cpu registers, and the degree of a node is 7, we cannot
830
assign it to any of the registers, thus it is significant.}
831
for n:=first_imaginary to maxreg-1 do
837
degree:=adjlist^.length;
838
if degree>=usable_registers_cnt then
840
else if move_related(n) then
841
freezeworklist.add(n)
843
simplifyworklist.add(n);
845
sort_simplify_worklist;
849
procedure trgobj.prepare_colouring;
852
active_moves:=Tlinkedlist.create;
853
frozen_moves:=Tlinkedlist.create;
854
coalesced_moves:=Tlinkedlist.create;
855
constrained_moves:=Tlinkedlist.create;
859
procedure trgobj.enable_moves(n:Tsuperregister);
861
var m:Tlinkedlistitem;
866
if movelist<>nil then
867
for i:=0 to movelist^.header.count-1 do
869
m:=movelist^.data[i];
870
if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
871
if Tmoveins(m).moveset=ms_active_moves then
873
{Move m from the set active_moves to the set worklist_moves.}
874
active_moves.remove(m);
875
Tmoveins(m).moveset:=ms_worklist_moves;
876
worklist_moves.concat(m);
881
procedure Trgobj.decrement_degree(m:Tsuperregister);
883
var adj : Psuperregisterworklist;
892
internalerror(200312151);
894
if d=usable_registers_cnt then
896
{Enable moves for m.}
898
{Enable moves for adjacent.}
901
for i:=1 to adj^.length do
904
if reginfo[n].flags*[ri_selected,ri_coalesced]<>[] then
907
{Remove the node from the spillworklist.}
908
if not spillworklist.delete(m) then
909
internalerror(200310145);
911
if move_related(m) then
912
freezeworklist.add(m)
914
simplifyworklist.add(m);
919
procedure trgobj.simplify;
921
var adj : Psuperregisterworklist;
922
m,n : Tsuperregister;
925
{We take the element with the least interferences out of the
926
simplifyworklist. Since the simplifyworklist is now sorted, we
927
no longer need to search, but we can simply take the first element.}
928
m:=simplifyworklist.get;
930
{Push it on the selectstack.}
934
include(flags,ri_selected);
938
for i:=1 to adj^.length do
941
if (n>=first_imaginary) and
942
(reginfo[n].flags*[ri_selected,ri_coalesced]=[]) then
947
function trgobj.get_alias(n:Tsuperregister):Tsuperregister;
950
while ri_coalesced in reginfo[n].flags do
955
procedure trgobj.add_worklist(u:Tsuperregister);
957
if (u>=first_imaginary) and
958
(not move_related(u)) and
959
(reginfo[u].degree<usable_registers_cnt) then
961
if not freezeworklist.delete(u) then
962
internalerror(200308161); {must be found}
963
simplifyworklist.add(u);
968
function trgobj.adjacent_ok(u,v:Tsuperregister):boolean;
970
{Check wether u and v should be coalesced. u is precoloured.}
972
function ok(t,r:Tsuperregister):boolean;
975
ok:=(t<first_imaginary) or
976
(reginfo[t].degree<usable_registers_cnt) or
980
var adj : Psuperregisterworklist;
990
for i:=1 to adj^.length do
993
if (flags*[ri_coalesced,ri_selected]=[]) and not ok(n,u) then
1002
function trgobj.conservative(u,v:Tsuperregister):boolean;
1004
var adj : Psuperregisterworklist;
1005
done : Tsuperregisterset; {To prevent that we count nodes twice.}
1011
supregset_reset(done,false,maxreg);
1016
for i:=1 to adj^.length do
1019
if flags*[ri_coalesced,ri_selected]=[] then
1021
supregset_include(done,n);
1022
if reginfo[n].degree>=usable_registers_cnt then
1027
adj:=reginfo[v].adjlist;
1029
for i:=1 to adj^.length do
1032
if not supregset_in(done,n) and
1033
(reginfo[n].degree>=usable_registers_cnt) and
1034
(reginfo[u].flags*[ri_coalesced,ri_selected]=[]) then
1037
conservative:=(k<usable_registers_cnt);
1041
procedure trgobj.combine(u,v:Tsuperregister);
1043
var adj : Psuperregisterworklist;
1046
searched:Tlinkedlistitem;
1051
if not freezeworklist.delete(v) then
1052
spillworklist.delete(v);
1053
coalescednodes.add(v);
1054
include(reginfo[v].flags,ri_coalesced);
1055
reginfo[v].alias:=u;
1057
{Combine both movelists. Since the movelists are sets, only add
1058
elements that are not already present. The movelists cannot be
1059
empty by definition; nodes are only coalesced if there is a move
1060
between them. To prevent quadratic time blowup (movelists of
1061
especially machine registers can get very large because of moves
1062
generated during calls) we need to go into disgusting complexity.
1064
(See webtbs/tw2242 for an example that stresses this.)
1066
We want to sort the movelist to be able to search logarithmically.
1067
Unfortunately, sorting the movelist every time before searching
1068
is counter-productive, since the movelist usually grows with a few
1069
items at a time. Therefore, we split the movelist into a sorted
1070
and an unsorted part and search through both. If the unsorted part
1071
becomes too large, we sort.}
1072
if assigned(reginfo[u].movelist) then
1074
{We have to weigh the cost of sorting the list against searching
1075
the cost of the unsorted part. I use factor of 8 here; if the
1076
number of items is less than 8 times the numer of unsorted items,
1077
we'll sort the list.}
1078
with reginfo[u].movelist^ do
1079
if header.count<8*(header.count-header.sorted_until) then
1080
sort_movelist(reginfo[u].movelist);
1082
if assigned(reginfo[v].movelist) then
1084
for n:=0 to reginfo[v].movelist^.header.count-1 do
1086
{Binary search the sorted part of the list.}
1087
searched:=reginfo[v].movelist^.data[n];
1089
q:=reginfo[u].movelist^.header.sorted_until;
1094
if ptruint(searched)>ptruint(reginfo[u].movelist^.data[i]) then
1099
with reginfo[u].movelist^ do
1100
if searched<>data[i] then
1102
{Linear search the unsorted part of the list.}
1103
for i:=header.sorted_until+1 to header.count-1 do
1104
if searched=data[i] then
1107
add_to_movelist(u,searched);
1116
adj:=reginfo[v].adjlist;
1118
for i:=1 to adj^.length do
1122
if not(ri_coalesced in flags) then
1124
{t has a connection to v. Since we are adding v to u, we
1125
need to connect t to u. However, beware if t was already
1127
if (ibitmap[t,u]) and not (ri_selected in flags) then
1128
{... because in that case, we are actually removing an edge
1129
and the degree of t decreases.}
1134
{We have added an edge to t and u. So their degree increases.
1135
However, v is added to u. That means its neighbours will
1136
no longer point to v, but to u instead. Therefore, only the
1137
degree of u increases.}
1138
if (u>=first_imaginary) and not (ri_selected in flags) then
1139
inc(reginfo[u].degree);
1143
if (reginfo[u].degree>=usable_registers_cnt) and freezeworklist.delete(u) then
1144
spillworklist.add(u);
1148
procedure trgobj.coalesce;
1151
x,y,u,v:Tsuperregister;
1154
m:=Tmoveins(worklist_moves.getfirst);
1157
if (y<first_imaginary) then
1169
m.moveset:=ms_coalesced_moves; {Already coalesced.}
1170
coalesced_moves.insert(m);
1173
{Do u and v interfere? In that case the move is constrained. Two
1174
precoloured nodes interfere allways. If v is precoloured, by the above
1175
code u is precoloured, thus interference...}
1176
else if (v<first_imaginary) or ibitmap[u,v] then
1178
m.moveset:=ms_constrained_moves; {Cannot coalesce yet...}
1179
constrained_moves.insert(m);
1183
{Next test: is it possible and a good idea to coalesce??}
1184
else if ((u<first_imaginary) and adjacent_ok(u,v)) or
1185
((u>=first_imaginary) and conservative(u,v)) then
1187
m.moveset:=ms_coalesced_moves; {Move coalesced!}
1188
coalesced_moves.insert(m);
1194
m.moveset:=ms_active_moves;
1195
active_moves.insert(m);
1199
procedure trgobj.freeze_moves(u:Tsuperregister);
1203
v,x,y:Tsuperregister;
1206
if reginfo[u].movelist<>nil then
1207
for i:=0 to reginfo[u].movelist^.header.count-1 do
1209
m:=reginfo[u].movelist^.data[i];
1210
if Tmoveins(m).moveset in [ms_worklist_moves,ms_active_moves] then
1214
if get_alias(y)=get_alias(u) then
1218
{Move m from active_moves/worklist_moves to frozen_moves.}
1219
if Tmoveins(m).moveset=ms_active_moves then
1220
active_moves.remove(m)
1222
worklist_moves.remove(m);
1223
Tmoveins(m).moveset:=ms_frozen_moves;
1224
frozen_moves.insert(m);
1226
if (v>=first_imaginary) and not(move_related(v)) and
1227
(reginfo[v].degree<usable_registers_cnt) then
1229
freezeworklist.delete(v);
1230
simplifyworklist.add(v);
1236
procedure trgobj.freeze;
1238
var n:Tsuperregister;
1241
{ We need to take a random element out of the freezeworklist. We take
1242
the last element. Dirty code! }
1243
n:=freezeworklist.get;
1244
{Add it to the simplifyworklist.}
1245
simplifyworklist.add(n);
1249
procedure trgobj.select_spill;
1253
adj : psuperregisterworklist;
1257
{ We must look for the element with the most interferences in the
1258
spillworklist. This is required because those registers are creating
1259
the most conflicts and keeping them in a register will not reduce the
1260
complexity and even can cause the help registers for the spilling code
1261
to get too much conflicts with the result that the spilling code
1262
will never converge (PFV) }
1265
with spillworklist do
1267
{Safe: This procedure is only called if length<>0}
1268
for i:=0 to length-1 do
1270
adj:=reginfo[buf^[i]].adjlist;
1271
if assigned(adj) and (adj^.length>max) then
1281
simplifyworklist.add(n);
1285
procedure trgobj.assign_colours;
1287
{Assign_colours assigns the actual colours to the registers.}
1289
var adj : Psuperregisterworklist;
1291
n,a,c : Tsuperregister;
1292
colourednodes : Tsuperregisterset;
1293
adj_colours:set of 0..255;
1299
for n:=0 to maxreg-1 do
1300
reginfo[n].colour:=n;
1301
{Colour the cpu registers...}
1302
supregset_reset(colourednodes,false,maxreg);
1303
for n:=0 to first_imaginary-1 do
1304
supregset_include(colourednodes,n);
1305
{Now colour the imaginary registers on the select-stack.}
1306
for i:=selectstack.length downto 1 do
1308
n:=selectstack.buf^[i-1];
1309
{Create a list of colours that we cannot assign to n.}
1311
adj:=reginfo[n].adjlist;
1313
for j:=0 to adj^.length-1 do
1315
a:=get_alias(adj^.buf^[j]);
1316
if supregset_in(colourednodes,a) and (reginfo[a].colour<=255) then
1317
include(adj_colours,reginfo[a].colour);
1319
if regtype=R_INTREGISTER then
1320
include(adj_colours,RS_STACK_POINTER_REG);
1321
{Assume a spill by default...}
1323
{Search for a colour not in this list.}
1324
for k:=0 to usable_registers_cnt-1 do
1326
c:=usable_registers[k];
1327
if not(c in adj_colours) then
1329
reginfo[n].colour:=c;
1331
supregset_include(colourednodes,n);
1332
include(used_in_proc,c);
1337
spillednodes.add(n);
1339
{Finally colour the nodes that were coalesced.}
1340
for i:=1 to coalescednodes.length do
1342
n:=coalescednodes.buf^[i-1];
1344
reginfo[n].colour:=reginfo[k].colour;
1345
if reginfo[k].colour<maxcpuregister then
1346
include(used_in_proc,reginfo[k].colour);
1350
procedure trgobj.colour_registers;
1354
if simplifyworklist.length<>0 then
1356
else if not(worklist_moves.empty) then
1358
else if freezeworklist.length<>0 then
1360
else if spillworklist.length<>0 then
1362
until (simplifyworklist.length=0) and
1363
worklist_moves.empty and
1364
(freezeworklist.length=0) and
1365
(spillworklist.length=0);
1369
procedure trgobj.epilogue_colouring;
1373
worklist_moves.clear;
1374
active_moves.destroy;
1376
frozen_moves.destroy;
1378
coalesced_moves.destroy;
1379
coalesced_moves:=nil;
1380
constrained_moves.destroy;
1381
constrained_moves:=nil;
1382
for i:=0 to maxreg-1 do
1384
if movelist<>nil then
1392
procedure trgobj.clear_interferences(u:Tsuperregister);
1394
{Remove node u from the interference graph and remove all collected
1395
move instructions it is associated with.}
1399
adj,adj2 : Psuperregisterworklist;
1402
adj:=reginfo[u].adjlist;
1405
for i:=1 to adj^.length do
1408
{Remove (u,v) and (v,u) from bitmap.}
1409
ibitmap[u,v]:=false;
1410
ibitmap[v,u]:=false;
1411
{Remove (v,u) from adjacency list.}
1412
adj2:=reginfo[v].adjlist;
1416
if adj2^.length=0 then
1419
reginfo[v].adjlist:=nil;
1423
{Remove ( u,* ) from adjacency list.}
1425
reginfo[u].adjlist:=nil;
1430
function trgobj.getregisterinline(list:TAsmList;subreg:Tsubregister):Tregister;
1434
p:=getnewreg(subreg);
1435
live_registers.add(p);
1436
result:=newreg(regtype,p,subreg);
1438
add_constraints(result);
1442
procedure trgobj.ungetregisterinline(list:TAsmList;r:Tregister);
1444
supreg:Tsuperregister;
1446
supreg:=getsupreg(r);
1447
live_registers.delete(supreg);
1448
insert_regalloc_info(list,supreg);
1452
procedure trgobj.insert_regalloc_info(list:TAsmList;u:tsuperregister);
1457
pdealloc : tai_regalloc;
1459
{ Insert regallocs for all imaginary registers }
1462
r:=newreg(regtype,u,subreg);
1463
if assigned(live_start) then
1465
{ Generate regalloc and bind it to an instruction, this
1466
is needed to find all live registers belonging to an
1467
instruction during the spilling }
1468
if live_start.typ=ait_instruction then
1469
palloc:=tai_regalloc.alloc(r,live_start)
1471
palloc:=tai_regalloc.alloc(r,nil);
1472
if live_end.typ=ait_instruction then
1473
pdealloc:=tai_regalloc.dealloc(r,live_end)
1475
pdealloc:=tai_regalloc.dealloc(r,nil);
1476
{ Insert live start allocation before the instruction/reg_a_sync }
1477
list.insertbefore(palloc,live_start);
1478
{ Insert live end deallocation before reg allocations
1479
to reduce conflicts }
1481
while assigned(p) and
1482
assigned(p.previous) and
1483
(tai(p.previous).typ=ait_regalloc) and
1484
(tai_regalloc(p.previous).ratype=ra_alloc) and
1485
(tai_regalloc(p.previous).reg<>r) do
1487
{ , but add release after a reg_a_sync }
1489
(p.typ=ait_regalloc) and
1490
(tai_regalloc(p).ratype=ra_sync) then
1493
list.insertbefore(pdealloc,p)
1495
list.concat(pdealloc);
1501
procedure trgobj.insert_regalloc_info_all(list:TAsmList);
1503
supreg : tsuperregister;
1505
{ Insert regallocs for all imaginary registers }
1506
for supreg:=first_imaginary to maxreg-1 do
1507
insert_regalloc_info(list,supreg);
1511
procedure trgobj.add_cpu_interferences(p : tai);
1516
procedure trgobj.generate_interference_graph(list:TAsmList;headertai:tai);
1522
supreg : tsuperregister;
1524
{ All allocations are available. Now we can generate the
1525
interference graph. Walk through all instructions, we can
1526
start with the headertai, because before the header tai is
1528
live_registers.clear;
1530
while assigned(p) do
1532
if p.typ=ait_regalloc then
1533
with Tai_regalloc(p) do
1535
if (getregtype(reg)=regtype) then
1537
supreg:=getsupreg(reg);
1541
live_registers.add(supreg);
1542
add_edges_used(supreg);
1546
live_registers.delete(supreg);
1547
add_edges_used(supreg);
1550
{ constraints needs always to be updated }
1551
add_constraints(reg);
1554
add_cpu_interferences(p);
1559
if live_registers.length>0 then
1561
for i:=0 to live_registers.length-1 do
1563
{ Only report for imaginary registers }
1564
if live_registers.buf^[i]>=first_imaginary then
1565
Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf^[i],defaultsub))+' not released');
1572
procedure trgobj.translate_register(var reg : tregister);
1574
if (getregtype(reg)=regtype) then
1575
setsupreg(reg,reginfo[getsupreg(reg)].colour)
1577
internalerror(200602021);
1581
procedure Trgobj.translate_registers(list:TAsmList);
1591
{ Leave when no imaginary registers are used }
1592
if maxreg<=first_imaginary then
1595
while assigned(p) do
1599
with Tai_regalloc(p) do
1601
if (getregtype(reg)=regtype) then
1603
{ Only alloc/dealloc is needed for the optimizer, remove
1605
if not(ratype in [ra_alloc,ra_dealloc]) then
1615
setsupreg(reg,reginfo[getsupreg(reg)].colour);
1617
Remove sequences of release and
1618
allocation of the same register like. Other combinations
1619
of release/allocate need to stay in the list.
1621
# Register X released
1622
# Register X allocated
1624
if assigned(previous) and
1625
(ratype=ra_alloc) and
1626
(Tai(previous).typ=ait_regalloc) and
1627
(Tai_regalloc(previous).reg=reg) and
1628
(Tai_regalloc(previous).ratype=ra_dealloc) then
1645
current_filepos:=fileinfo;
1646
for i:=0 to ops-1 do
1650
if (getregtype(reg)=regtype) then
1651
setsupreg(reg,reginfo[getsupreg(reg)].colour);
1654
if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
1658
setsupreg(base,reginfo[getsupreg(base)].colour);
1659
if index<>NR_NO then
1660
setsupreg(index,reginfo[getsupreg(index)].colour);
1666
if regtype=R_INTREGISTER then
1669
if so^.rs<>NR_NO then
1670
setsupreg(so^.rs,reginfo[getsupreg(so^.rs)].colour);
1676
{ Maybe the operation can be removed when
1677
it is a move and both arguments are the same }
1678
if is_same_reg_move(regtype) then
1690
current_filepos:=current_procinfo.exitpos;
1694
function trgobj.spill_registers(list:TAsmList;headertai:tai):boolean;
1695
{ Returns true if any help registers have been used }
1700
regs_to_spill_set:Tsuperregisterset;
1701
spill_temps : ^Tspill_temp_list;
1702
supreg : tsuperregister;
1703
templist : TAsmList;
1705
spill_registers:=false;
1706
live_registers.clear;
1707
for i:=first_imaginary to maxreg-1 do
1708
exclude(reginfo[i].flags,ri_selected);
1709
spill_temps:=allocmem(sizeof(treference)*maxreg);
1710
supregset_reset(regs_to_spill_set,false,$ffff);
1711
{ Allocate temps and insert in front of the list }
1712
templist:=TAsmList.create;
1713
{Safe: this procedure is only called if there are spilled nodes.}
1714
with spillednodes do
1715
for i:=0 to length-1 do
1718
{Alternative representation.}
1719
supregset_include(regs_to_spill_set,t);
1720
{Clear all interferences of the spilled register.}
1721
clear_interferences(t);
1722
{Get a temp for the spilled register, the size must at least equal a complete register,
1723
take also care of the fact that subreg can be larger than a single register like doubles
1724
that occupy 2 registers }
1725
tg.gettemp(templist,
1726
max(tcgsize2size[reg_cgsize(newreg(regtype,t,R_SUBWHOLE))],
1727
tcgsize2size[reg_cgsize(newreg(regtype,t,reginfo[t].subreg))]),
1728
tt_noreuse,spill_temps^[t]);
1730
list.insertlistafter(headertai,templist);
1732
{ Walk through all instructions, we can start with the headertai,
1733
because before the header tai is only symbols }
1735
while assigned(p) do
1739
with Tai_regalloc(p) do
1741
if (getregtype(reg)=regtype) then
1743
{A register allocation of a spilled register can be removed.}
1744
supreg:=getsupreg(reg);
1745
if supregset_in(regs_to_spill_set,supreg) then
1757
live_registers.add(supreg);
1759
live_registers.delete(supreg);
1767
current_filepos:=fileinfo;
1768
if instr_spill_register(list,taicpu(p),regs_to_spill_set,spill_temps^) then
1769
spill_registers:=true;
1774
current_filepos:=current_procinfo.exitpos;
1775
{Safe: this procedure is only called if there are spilled nodes.}
1776
with spillednodes do
1777
for i:=0 to length-1 do
1778
tg.ungettemp(list,spill_temps^[buf^[i]]);
1779
freemem(spill_temps);
1783
function trgobj.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
1789
procedure Trgobj.do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
1791
list.insertafter(spilling_create_load(spilltemp,tempreg),pos);
1795
procedure Trgobj.do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);
1797
list.insertafter(spilling_create_store(tempreg,spilltemp),pos);
1801
function trgobj.get_spill_subreg(r : tregister) : tsubregister;
1807
function trgobj.instr_spill_register(list:TAsmList;
1809
const r:Tsuperregisterset;
1810
const spilltemplist:Tspill_temp_list): boolean;
1812
counter, regindex: longint;
1813
regs: tspillregsinfo;
1816
procedure addreginfo(reg: tregister; operation: topertype);
1818
i, tmpindex: longint;
1819
supreg : tsuperregister;
1821
tmpindex := regindex;
1822
supreg:=get_alias(getsupreg(reg));
1823
{ did we already encounter this register? }
1824
for i := 0 to pred(regindex) do
1825
if (regs[i].orgreg = supreg) then
1830
if tmpindex > high(regs) then
1831
internalerror(2003120301);
1832
regs[tmpindex].orgreg := supreg;
1833
regs[tmpindex].spillreg:=reg;
1834
if supregset_in(r,supreg) then
1836
{ add/update info on this register }
1837
regs[tmpindex].mustbespilled := true;
1840
regs[tmpindex].regread := true;
1842
regs[tmpindex].regwritten := true;
1845
regs[tmpindex].regread := true;
1846
regs[tmpindex].regwritten := true;
1851
inc(regindex,ord(regindex=tmpindex));
1855
procedure tryreplacereg(var reg: tregister);
1858
supreg: tsuperregister;
1860
supreg:=get_alias(getsupreg(reg));
1861
for i:=0 to pred(regindex) do
1862
if (regs[i].mustbespilled) and
1863
(regs[i].orgreg=supreg) then
1865
{ Only replace supreg }
1866
setsupreg(reg,getsupreg(regs[i].tempreg));
1874
oldlive_registers : tsuperregisterworklist;
1877
fillchar(regs,sizeof(regs),0);
1878
for counter := low(regs) to high(regs) do
1879
regs[counter].orgreg := RS_INVALID;
1883
{ check whether and if so which and how (read/written) this instructions contains
1884
registers that must be spilled }
1885
for counter := 0 to instr.ops-1 do
1886
with instr.oper[counter]^ do
1891
if (getregtype(reg) = regtype) then
1892
addreginfo(reg,instr.spilling_get_operation_type(counter));
1896
if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
1899
if (base <> NR_NO) then
1900
addreginfo(base,instr.spilling_get_operation_type_ref(counter,base));
1901
if (index <> NR_NO) then
1902
addreginfo(index,instr.spilling_get_operation_type_ref(counter,index));
1908
if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
1909
if shifterop^.rs<>NR_NO then
1910
addreginfo(shifterop^.rs,operand_read);
1916
{ if no spilling for this instruction we can leave }
1921
{ Try replacing the register with the spilltemp. This is usefull only
1922
for the i386,x86_64 that support memory locations for several instructions }
1923
for counter := 0 to pred(regindex) do
1924
with regs[counter] do
1926
if mustbespilled then
1928
if do_spill_replace(list,instr,orgreg,spilltemplist[orgreg]) then
1929
mustbespilled:=false;
1935
There are registers that need are spilled. We generate the
1936
following code for it. The used positions where code need
1937
to be inserted are marked using #. Note that code is always inserted
1938
before the positions using pos.previous. This way the position is always
1939
the same since pos doesn't change, but pos.previous is modified everytime
1940
new code is inserted.
1943
- reg_allocs load spills
1951
- reg_deallocs for load-only spills
1952
- reg_allocs for store-only spills
1955
- original instruction
1959
- reg_deallocs store spills
1966
oldlive_registers.copyfrom(live_registers);
1968
{ Process all tai_regallocs belonging to this instruction, ignore explicit
1969
inserted regallocs. These can happend for example in i386:
1971
<regdealloc ireg26, instr=taicpu of lea>
1972
<regalloc edi, insrt=nil>
1973
lea [ireg26+ireg17],edi
1974
All released registers are also added to the live_registers because
1975
they can't be used during the spilling }
1976
loadpos:=tai(instr.previous);
1977
while assigned(loadpos) and
1978
(loadpos.typ=ait_regalloc) and
1979
((tai_regalloc(loadpos).instr=nil) or
1980
(tai_regalloc(loadpos).instr=instr)) do
1982
{ Only add deallocs belonging to the instruction. Explicit inserted deallocs
1983
belong to the previous instruction and not the current instruction }
1984
if (tai_regalloc(loadpos).instr=instr) and
1985
(tai_regalloc(loadpos).ratype=ra_dealloc) then
1986
live_registers.add(getsupreg(tai_regalloc(loadpos).reg));
1987
loadpos:=tai(loadpos.previous);
1989
loadpos:=tai(loadpos.next);
1991
{ Load the spilled registers }
1992
for counter := 0 to pred(regindex) do
1993
with regs[counter] do
1995
if mustbespilled and regread then
1997
tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
1998
do_spill_read(list,tai(loadpos.previous),spilltemplist[orgreg],tempreg);
2002
{ Release temp registers of read-only registers, and add reference of the instruction
2004
for counter := 0 to pred(regindex) do
2005
with regs[counter] do
2007
if mustbespilled and regread and (not regwritten) then
2009
{ The original instruction will be the next that uses this register }
2010
add_reg_instruction(instr,tempreg);
2011
ungetregisterinline(list,tempreg);
2015
{ Allocate temp registers of write-only registers, and add reference of the instruction
2017
for counter := 0 to pred(regindex) do
2018
with regs[counter] do
2020
if mustbespilled and regwritten then
2022
{ When the register is also loaded there is already a register assigned }
2023
if (not regread) then
2024
tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
2025
{ The original instruction will be the next that uses this register, this
2026
also needs to be done for read-write registers }
2027
add_reg_instruction(instr,tempreg);
2031
{ store the spilled registers }
2032
storepos:=tai(instr.next);
2033
for counter := 0 to pred(regindex) do
2034
with regs[counter] do
2036
if mustbespilled and regwritten then
2038
do_spill_written(list,tai(storepos.previous),spilltemplist[orgreg],tempreg);
2039
ungetregisterinline(list,tempreg);
2043
{ now all spilling code is generated we can restore the live registers. This
2044
must be done after the store because the store can need an extra register
2045
that also needs to conflict with the registers of the instruction }
2046
live_registers.done;
2047
live_registers:=oldlive_registers;
2049
{ substitute registers }
2050
for counter:=0 to instr.ops-1 do
2051
with instr.oper[counter]^ do
2056
if (getregtype(reg) = regtype) then
2061
if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
2063
tryreplacereg(ref^.base);
2064
tryreplacereg(ref^.index);
2070
if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
2071
tryreplacereg(shifterop^.rs);