* reg allocations for imaginary register are now inserted just

before reg allocation
  * tregister changed to enum to allow compile time check
  * fixed several tregister-tsuperregister errors
This commit is contained in:
peter 2003-12-15 21:25:48 +00:00
parent e60da116b0
commit 1367e342db
16 changed files with 517 additions and 316 deletions

View File

@ -447,6 +447,7 @@ interface
Taasmoutput=class;
tadd_reg_instruction_proc=procedure(instr:Tai;r:tregister) of object;
Trggetproc=procedure(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister) of object;
Trgungetproc=procedure(list:Taasmoutput;position:Tai;r:Tregister) of object;
@ -491,7 +492,7 @@ interface
procedure loadoper(opidx:longint;o:toper);
procedure clearop(opidx:longint);
function is_nop:boolean;virtual;abstract;
function is_move:boolean;virtual;abstract;
function is_reg_move:boolean;virtual;abstract;
{ register allocator }
function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister;var live_registers_int:Tsuperregisterworklist):Tai;
procedure forward_allocation(p:Tai;var {unusedregsint:tsuperregisterset}live_registers_int:Tsuperregisterworklist);
@ -542,6 +543,9 @@ interface
{ label when the result is true or false }
truelabel,falselabel : tasmlabel;
{ hook to notify uses of registers }
add_reg_instruction_hook : tadd_reg_instruction_proc;
{ default lists }
datasegment,codesegment,bsssegment,
debuglist,withdebuglist,consts,
@ -1677,6 +1681,8 @@ implementation
segprefix:=ref^.segment;
{$endif}
typ:=top_ref;
add_reg_instruction_hook(self,ref^.base);
add_reg_instruction_hook(self,ref^.index);
{ mark symbol as used }
if assigned(ref^.symbol) then
ref^.symbol.increfs;
@ -1694,6 +1700,7 @@ implementation
reg:=r;
typ:=top_reg;
end;
add_reg_instruction_hook(self,r);
{$ifdef ARM}
{ R15 is the PC on the ARM thus moves to R15 are jumps.
Due to speed considerations we don't use a virtual overridden method here.
@ -1714,10 +1721,14 @@ implementation
with oper[opidx]^ do
begin
case typ of
top_reg:
add_reg_instruction_hook(self,reg);
top_ref:
begin
new(ref);
ref^:=o.ref^;
add_reg_instruction_hook(self,ref^.base);
add_reg_instruction_hook(self,ref^.index);
end;
{$ifdef ARM}
top_shifterop:
@ -2202,7 +2213,13 @@ implementation
end.
{
$Log$
Revision 1.60 2003-12-14 20:24:28 daniel
Revision 1.61 2003-12-15 21:25:48 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.60 2003/12/14 20:24:28 daniel
* Register allocator speed optimizations
- Worklist no longer a ringbuffer
- No find operations are left

View File

@ -133,12 +133,17 @@ interface
{
The new register coding:
SuperRegister (bits 0..7)
Unused (bits 8..15)
SuperRegister (bits 0..15)
Subregister (bits 16..23)
Register type (bits 24..31)
TRegister is defined as an enum to make it incompatible
with TSuperRegister to avoid mixing them
}
TRegister = type cardinal;
TRegister = (
TRegisterLowEnum := $80000000,
TRegisterHighEnum := $7fffffff
);
TRegisterRec=packed record
{$ifdef FPC_BIG_ENDIAN}
regtype : Tregistertype;
@ -316,7 +321,7 @@ implementation
end;
destructor tsuperregisterworklist.done;
begin
if assigned(buf) then
freemem(buf);
@ -324,7 +329,7 @@ implementation
procedure tsuperregisterworklist.add(s:tsuperregister);
begin
inc(length);
{ Need to increase buffer length? }
@ -341,14 +346,14 @@ implementation
procedure tsuperregisterworklist.clear;
begin
length:=0;
end;
procedure tsuperregisterworklist.deleteidx(i:word);
begin
if length=0 then
internalerror(200310144);
@ -358,7 +363,7 @@ implementation
function tsuperregisterworklist.get:tsuperregister;
begin
if length=0 then
internalerror(200310142);
@ -369,9 +374,9 @@ implementation
function tsuperregisterworklist.delete(s:tsuperregister):boolean;
var i:word;
begin
delete:=false;
for i:=1 to length do
@ -569,7 +574,13 @@ finalization
end.
{
$Log$
Revision 1.78 2003-12-14 20:24:28 daniel
Revision 1.79 2003-12-15 21:25:48 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.78 2003/12/14 20:24:28 daniel
* Register allocator speed optimizations
- Worklist no longer a ringbuffer
- No find operations are left

View File

@ -84,6 +84,7 @@ unit cgobj;
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
procedure ungetreference(list:Taasmoutput;const r:Treference);virtual;
procedure add_reg_instruction(instr:Tai;r:tregister);virtual;
procedure add_move_instruction(instr:Taicpu);virtual;
function uses_registers(rt:Tregistertype):boolean;virtual;
@ -553,6 +554,7 @@ implementation
constructor tcg.create;
begin
add_reg_instruction_hook:={$ifdef FPCPROCVAR}@{$endif}add_reg_instruction;
end;
@ -627,6 +629,8 @@ implementation
begin
if r.base<>NR_NO then
ungetregister(list,r.base);
if r.index<>NR_NO then
ungetregister(list,r.index);
end;
@ -657,6 +661,19 @@ implementation
end;
procedure tcg.add_reg_instruction(instr:Tai;r:tregister);
var
rt : tregistertype;
begin
rt:=getregtype(r);
{ Only add it when a register allocator is configured.
No IE can be generated, because the VMT is written
without a valid rg[] }
if assigned(rg[rt]) then
rg[rt].add_reg_instruction(instr,r);
end;
procedure tcg.add_move_instruction(instr:Taicpu);
var
rt : tregistertype;
@ -676,11 +693,7 @@ implementation
for rt:=low(tregistertype) to high(tregistertype) do
begin
if assigned(rg[rt]) then
begin
rg[rt].check_unreleasedregs;
rg[rt].do_register_allocation(list,headertai);
rg[rt].translate_registers(list);
end;
rg[rt].do_register_allocation(list,headertai);
end;
end;
@ -1941,7 +1954,13 @@ finalization
end.
{
$Log$
Revision 1.138 2003-12-12 17:16:17 peter
Revision 1.139 2003-12-15 21:25:48 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.138 2003/12/12 17:16:17 peter
* rg[tregistertype] added in tcg
Revision 1.137 2003/12/06 22:11:47 jonas

View File

@ -178,7 +178,7 @@ begin
tmpRef.base := NR_EDI;
tmpRef.index := NR_EDI;
for regCounter := RS_EAX to RS_EDI do
if writeToMemDestroysContents(NR_NO,tmpRef,regCounter,c[regCounter],dummy) then
if writeToMemDestroysContents(RS_INVALID,tmpRef,regCounter,c[regCounter],dummy) then
begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(supreg in regsStillValid);
@ -1954,7 +1954,7 @@ begin
if (memreg <> NR_NO) and
(not getNextInstruction(p,hp1) or
(RegLoadedWithNewValue(getsupreg(memreg),false,hp1) or
FindRegDealloc(getsupreg(regcounter),hp1))) then
FindRegDealloc(regcounter,hp1))) then
begin
hp1 := Tai_Marker.Create(NoPropInfoEnd);
insertllitem(asml,p,p.next,hp1);
@ -2074,7 +2074,13 @@ end.
{
$Log$
Revision 1.57 2003-12-15 16:08:15 jonas
Revision 1.58 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.57 2003/12/15 16:08:15 jonas
- disable removal of dead loads before a call, because register
parameters are released before a call
* fix storeback of registers in case of different sizes (e.g., first

View File

@ -1785,7 +1785,7 @@ begin
(typ in [con_ref,con_noRemoveRef]) and
(not(cs_UncertainOpts in aktglobalswitches) or
{ for movsl }
((ref.base = RS_EDI) and (ref.index = RS_EDI)) or
((ref.base = NR_EDI) and (ref.index = NR_EDI)) or
{ don't destroy if reg contains a parameter, local or global variable }
containsPointerLoad(c)
);
@ -1963,7 +1963,7 @@ var
p, prev: tai;
hp1, hp2: tai;
{$ifdef i386}
regcounter: tregister;
regcounter,
supreg : tsuperregister;
{$endif i386}
usedregs, nodeallocregs: tregset;
@ -2052,7 +2052,7 @@ begin
usedRegs := usedRegs - noDeallocRegs;
for regCounter := RS_EAX to RS_EDI do
if regCounter in usedRegs then
addRegDeallocFor(list,regCounter,prev);
addRegDeallocFor(list,newreg(R_INTREGISTER,regCounter,R_SUBWHOLE),prev);
{$endif i386}
end;
@ -2714,7 +2714,13 @@ end.
{
$Log$
Revision 1.60 2003-12-15 15:58:58 peter
Revision 1.61 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.60 2003/12/15 15:58:58 peter
* fix statedebug compile
Revision 1.59 2003/12/14 22:42:14 peter

View File

@ -1808,7 +1808,7 @@ begin
TmpUsedRegs := UsedRegs;
UpdateUsedRegs(TmpUsedRegs,tai(hp1.next));
if (RefsEqual(taicpu(hp2).oper[1]^.ref^, taicpu(p).oper[0]^.ref^) and
not(RegUsedAfterInstruction(getsupreg(taicpu(p).oper[1]^.reg),
not(RegUsedAfterInstruction(taicpu(p).oper[1]^.reg,
hp2, TmpUsedRegs))) then
{ change mov (ref), reg }
{ add/sub/or/... reg2/$const, reg }
@ -1996,7 +1996,13 @@ end.
{
$Log$
Revision 1.52 2003-12-14 22:42:14 peter
Revision 1.53 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.52 2003/12/14 22:42:14 peter
* fixed csdebug
Revision 1.51 2003/12/13 15:48:47 jonas

View File

@ -1,72 +1,72 @@
{ don't edit, this file is generated from x86reg.dat }
NR_NO = $00000000;
NR_AL = $01010000;
NR_AH = $01020000;
NR_AX = $01030000;
NR_EAX = $01040000;
NR_CL = $01010001;
NR_CH = $01020001;
NR_CX = $01030001;
NR_ECX = $01040001;
NR_DL = $01010002;
NR_DH = $01020002;
NR_DX = $01030002;
NR_EDX = $01040002;
NR_BL = $01010003;
NR_BH = $01020003;
NR_BX = $01030003;
NR_EBX = $01040003;
NR_SI = $01030004;
NR_ESI = $01040004;
NR_DI = $01030005;
NR_EDI = $01040005;
NR_BP = $01030006;
NR_EBP = $01040006;
NR_SP = $01030007;
NR_ESP = $01040007;
NR_CS = $05000001;
NR_DS = $05000002;
NR_ES = $05000003;
NR_SS = $05000004;
NR_FS = $05000005;
NR_GS = $05000006;
NR_DR0 = $05000007;
NR_DR1 = $05000008;
NR_DR2 = $05000009;
NR_DR3 = $0500000a;
NR_DR6 = $0500000b;
NR_DR7 = $0500000c;
NR_CR0 = $0500000d;
NR_CR2 = $0500000e;
NR_CR3 = $0500000f;
NR_CR4 = $05000010;
NR_TR3 = $05000011;
NR_TR4 = $05000012;
NR_TR5 = $05000013;
NR_TR6 = $05000014;
NR_TR7 = $05000015;
NR_ST0 = $02000000;
NR_ST1 = $02000001;
NR_ST2 = $02000002;
NR_ST3 = $02000003;
NR_ST4 = $02000004;
NR_ST5 = $02000005;
NR_ST6 = $02000006;
NR_ST7 = $02000007;
NR_ST = $02000008;
NR_MM0 = $03000000;
NR_MM1 = $03000001;
NR_MM2 = $03000002;
NR_MM3 = $03000003;
NR_MM4 = $03000004;
NR_MM5 = $03000005;
NR_MM6 = $03000006;
NR_MM7 = $03000007;
NR_XMM0 = $04000000;
NR_XMM1 = $04000001;
NR_XMM2 = $04000002;
NR_XMM3 = $04000003;
NR_XMM4 = $04000004;
NR_XMM5 = $04000005;
NR_XMM6 = $04000006;
NR_XMM7 = $04000007;
NR_NO = tregister($00000000);
NR_AL = tregister($01010000);
NR_AH = tregister($01020000);
NR_AX = tregister($01030000);
NR_EAX = tregister($01040000);
NR_CL = tregister($01010001);
NR_CH = tregister($01020001);
NR_CX = tregister($01030001);
NR_ECX = tregister($01040001);
NR_DL = tregister($01010002);
NR_DH = tregister($01020002);
NR_DX = tregister($01030002);
NR_EDX = tregister($01040002);
NR_BL = tregister($01010003);
NR_BH = tregister($01020003);
NR_BX = tregister($01030003);
NR_EBX = tregister($01040003);
NR_SI = tregister($01030004);
NR_ESI = tregister($01040004);
NR_DI = tregister($01030005);
NR_EDI = tregister($01040005);
NR_BP = tregister($01030006);
NR_EBP = tregister($01040006);
NR_SP = tregister($01030007);
NR_ESP = tregister($01040007);
NR_CS = tregister($05000001);
NR_DS = tregister($05000002);
NR_ES = tregister($05000003);
NR_SS = tregister($05000004);
NR_FS = tregister($05000005);
NR_GS = tregister($05000006);
NR_DR0 = tregister($05000007);
NR_DR1 = tregister($05000008);
NR_DR2 = tregister($05000009);
NR_DR3 = tregister($0500000a);
NR_DR6 = tregister($0500000b);
NR_DR7 = tregister($0500000c);
NR_CR0 = tregister($0500000d);
NR_CR2 = tregister($0500000e);
NR_CR3 = tregister($0500000f);
NR_CR4 = tregister($05000010);
NR_TR3 = tregister($05000011);
NR_TR4 = tregister($05000012);
NR_TR5 = tregister($05000013);
NR_TR6 = tregister($05000014);
NR_TR7 = tregister($05000015);
NR_ST0 = tregister($02000000);
NR_ST1 = tregister($02000001);
NR_ST2 = tregister($02000002);
NR_ST3 = tregister($02000003);
NR_ST4 = tregister($02000004);
NR_ST5 = tregister($02000005);
NR_ST6 = tregister($02000006);
NR_ST7 = tregister($02000007);
NR_ST = tregister($02000008);
NR_MM0 = tregister($03000000);
NR_MM1 = tregister($03000001);
NR_MM2 = tregister($03000002);
NR_MM3 = tregister($03000003);
NR_MM4 = tregister($03000004);
NR_MM5 = tregister($03000005);
NR_MM6 = tregister($03000006);
NR_MM7 = tregister($03000007);
NR_XMM0 = tregister($04000000);
NR_XMM1 = tregister($04000001);
NR_XMM2 = tregister($04000002);
NR_XMM3 = tregister($04000003);
NR_XMM4 = tregister($04000004);
NR_XMM5 = tregister($04000005);
NR_XMM6 = tregister($04000006);
NR_XMM7 = tregister($04000007);

View File

@ -1,72 +1,72 @@
{ don't edit, this file is generated from x86reg.dat }
$00000000,
$01010000,
$01020000,
$01030000,
$01040000,
$01010001,
$01020001,
$01030001,
$01040001,
$01010002,
$01020002,
$01030002,
$01040002,
$01010003,
$01020003,
$01030003,
$01040003,
$01030004,
$01040004,
$01030005,
$01040005,
$01030006,
$01040006,
$01030007,
$01040007,
$05000001,
$05000002,
$05000003,
$05000004,
$05000005,
$05000006,
$05000007,
$05000008,
$05000009,
$0500000a,
$0500000b,
$0500000c,
$0500000d,
$0500000e,
$0500000f,
$05000010,
$05000011,
$05000012,
$05000013,
$05000014,
$05000015,
$02000000,
$02000001,
$02000002,
$02000003,
$02000004,
$02000005,
$02000006,
$02000007,
$02000008,
$03000000,
$03000001,
$03000002,
$03000003,
$03000004,
$03000005,
$03000006,
$03000007,
$04000000,
$04000001,
$04000002,
$04000003,
$04000004,
$04000005,
$04000006,
$04000007
tregister($00000000),
tregister($01010000),
tregister($01020000),
tregister($01030000),
tregister($01040000),
tregister($01010001),
tregister($01020001),
tregister($01030001),
tregister($01040001),
tregister($01010002),
tregister($01020002),
tregister($01030002),
tregister($01040002),
tregister($01010003),
tregister($01020003),
tregister($01030003),
tregister($01040003),
tregister($01030004),
tregister($01040004),
tregister($01030005),
tregister($01040005),
tregister($01030006),
tregister($01040006),
tregister($01030007),
tregister($01040007),
tregister($05000001),
tregister($05000002),
tregister($05000003),
tregister($05000004),
tregister($05000005),
tregister($05000006),
tregister($05000007),
tregister($05000008),
tregister($05000009),
tregister($0500000a),
tregister($0500000b),
tregister($0500000c),
tregister($0500000d),
tregister($0500000e),
tregister($0500000f),
tregister($05000010),
tregister($05000011),
tregister($05000012),
tregister($05000013),
tregister($05000014),
tregister($05000015),
tregister($02000000),
tregister($02000001),
tregister($02000002),
tregister($02000003),
tregister($02000004),
tregister($02000005),
tregister($02000006),
tregister($02000007),
tregister($02000008),
tregister($03000000),
tregister($03000001),
tregister($03000002),
tregister($03000003),
tregister($03000004),
tregister($03000005),
tregister($03000006),
tregister($03000007),
tregister($04000000),
tregister($04000001),
tregister($04000002),
tregister($04000003),
tregister($04000004),
tregister($04000005),
tregister($04000006),
tregister($04000007)

View File

@ -113,7 +113,7 @@ implementation
if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
internalerror(200304235);
location_release(exprasmlist,left.location);
allocate_tempparaloc;
// allocate_tempparaloc;
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
end;
@ -137,7 +137,7 @@ implementation
if left.resulttype.def.deftype=floatdef then
begin
location_release(exprasmlist,left.location);
allocate_tempparaloc;
// allocate_tempparaloc;
{$ifdef i386}
if tempparaloc.loc<>LOC_REFERENCE then
internalerror(200309291);
@ -215,7 +215,6 @@ implementation
aktcallnode.procdefinition.proccalloption) then
begin
location_release(exprasmlist,left.location);
allocate_tempparaloc;
{$ifdef i386}
if tempparaloc.loc<>LOC_REFERENCE then
internalerror(200309292);
@ -249,14 +248,14 @@ implementation
if cgsize in [OS_64,OS_S64] then
begin
inc(tcgcallnode(aktcallnode).pushedparasize,8);
allocate_tempparaloc;
// allocate_tempparaloc;
cg64.a_param64_loc(exprasmlist,left.location,tempparaloc);
location_release(exprasmlist,left.location);
end
else
begin
location_release(exprasmlist,left.location);
allocate_tempparaloc;
// allocate_tempparaloc;
inc(tcgcallnode(aktcallnode).pushedparasize,align(tcgsize2size[tempparaloc.size],tempparaloc.alignment));
cg.a_param_loc(exprasmlist,left.location,tempparaloc);
end;
@ -266,7 +265,7 @@ implementation
LOC_CMMXREGISTER:
begin
location_release(exprasmlist,left.location);
allocate_tempparaloc;
// allocate_tempparaloc;
inc(tcgcallnode(aktcallnode).pushedparasize,8);
cg.a_parammm_reg(exprasmlist,left.location.register);
end;
@ -301,6 +300,8 @@ implementation
objectlibrary.getlabel(falselabel);
secondpass(left);
allocate_tempparaloc;
{ handle varargs first, because paraitem.parasym is not valid }
if (nf_varargs_para in flags) then
begin
@ -337,7 +338,7 @@ implementation
begin
inc(tcgcallnode(aktcallnode).pushedparasize,POINTER_SIZE);
location_release(exprasmlist,left.location);
allocate_tempparaloc;
// allocate_tempparaloc;
cg.a_param_loc(exprasmlist,left.location,tempparaloc);
end
else
@ -1129,7 +1130,13 @@ begin
end.
{
$Log$
Revision 1.145 2003-12-07 12:41:32 jonas
Revision 1.146 2003-12-15 21:25:48 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.145 2003/12/07 12:41:32 jonas
* fixed ansistring/widestring results: deallocate result reg only after
it has been stored to memory, as the storing itself may require extra
results (e.g. on ppc)

View File

@ -526,26 +526,32 @@ implementation
tt.def.needs_inittable) then
generate_inittable(newtype);
{ Always generate RTTI info for all types. This is to have typeinfo() return
the same pointer }
generate_rtti(newtype);
{ for objects we should write the vmt and interfaces.
This need to be done after the rtti has been written, because
it can contain a reference to that data (PFV)
This is not for forward classes }
if (tt.def.deftype=objectdef) and
not(oo_is_forward in tobjectdef(tt.def).objectoptions) then
if (tt.def.deftype=objectdef) then
begin
ch:=cclassheader.create(tobjectdef(tt.def));
{ generate and check virtual methods, must be done
before RTTI is written }
ch.genvmt;
if is_interface(tobjectdef(tt.def)) then
ch.writeinterfaceids;
if (oo_has_vmt in tobjectdef(tt.def).objectoptions) then
ch.writevmt;
ch.free;
if not(oo_is_forward in tobjectdef(tt.def).objectoptions) then
begin
ch:=cclassheader.create(tobjectdef(tt.def));
{ generate and check virtual methods, must be done
before RTTI is written }
ch.genvmt;
{ Generate RTTI for class }
generate_rtti(newtype);
if is_interface(tobjectdef(tt.def)) then
ch.writeinterfaceids;
if (oo_has_vmt in tobjectdef(tt.def).objectoptions) then
ch.writevmt;
ch.free;
end;
end
else
begin
{ Always generate RTTI info for all types. This is to have typeinfo() return
the same pointer }
generate_rtti(newtype);
end;
aktfilepos:=oldfilepos;
@ -656,7 +662,13 @@ implementation
end.
{
$Log$
Revision 1.74 2003-12-12 12:09:40 marco
Revision 1.75 2003-12-15 21:25:48 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.74 2003/12/12 12:09:40 marco
* always generate RTTI patch from peter
Revision 1.73 2003/12/10 16:37:01 peter

View File

@ -749,10 +749,7 @@ implementation
{ The procedure body is finished, we can now
allocate the registers }
if not(cs_no_regalloc in aktglobalswitches) then
begin
cg.do_register_allocation(aktproccode,headertai);
end;
cg.do_register_allocation(aktproccode,headertai);
{ Add save and restore of used registers }
aktfilepos:=entrypos;
@ -1333,7 +1330,13 @@ implementation
end.
{
$Log$
Revision 1.176 2003-12-10 16:37:01 peter
Revision 1.177 2003-12-15 21:25:48 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.176 2003/12/10 16:37:01 peter
* global property support for fpc modes
Revision 1.175 2003/12/03 23:13:20 peter

View File

@ -146,6 +146,9 @@ unit rgobj;
Treginfoflagset=set of Treginfoflag;
Treginfo=record
live_start,
live_end : Tai;
subreg : tsubregister;
alias : Tsuperregister;
{ The register allocator assigns each register a colour }
colour : Tsuperregister;
@ -156,21 +159,6 @@ unit rgobj;
end;
Preginfo=^TReginfo;
{ This is the base class used for a register allocator. }
trgbase=class
function getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;virtual;abstract;
{# Get the register specified.}
procedure getexplicitregister(list:Taasmoutput;r:Tregister);virtual;abstract;
{# Get multiple registers specified.}
procedure allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;abstract;
{# Free multiple registers specified.}
procedure deallocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);virtual;abstract;
function uses_registers:boolean;virtual;abstract;
{# Deallocate any kind of register }
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;abstract;
end;
{#------------------------------------------------------------------
This class implements the default register allocator. It is used by the
@ -181,7 +169,7 @@ unit rgobj;
by cpu-specific implementations.
--------------------------------------------------------------------}
trgobj=class(trgbase)
trgobj=class
preserved_by_proc : tcpuregisterset;
used_in_proc : tcpuregisterset;
// is_reg_var : Tsuperregisterset; {old regvars}
@ -206,37 +194,18 @@ unit rgobj;
function uses_registers:boolean;virtual;
{# Deallocate any kind of register }
procedure ungetregister(list:Taasmoutput;r:Tregister);virtual;
procedure add_constraints(reg:Tregister);virtual;
procedure add_reg_instruction(instr:Tai;r:tregister);
procedure add_move_instruction(instr:Taicpu);
{# Do the register allocation.}
procedure do_register_allocation(list:Taasmoutput;headertai:tai);virtual;
{ procedure resetusableregisters;virtual;}
{ procedure makeregvar(reg:Tsuperregister);}
{$ifdef EXTDEBUG}
procedure writegraph(loopidx:longint);
{$endif EXTDEBUG}
procedure add_move_instruction(instr:Taicpu);
{# Prepare the register colouring.}
procedure prepare_colouring;
{# Clean up after register colouring.}
procedure epilogue_colouring;
{# Colour the registers; that is do the register allocation.}
procedure colour_registers;
{# Spills certain registers in the specified assembler list.}
function spill_registers(list:Taasmoutput;headertai:tai):boolean;
procedure translate_registers(list:Taasmoutput);
{# Adds an interference edge.}
procedure add_edge(u,v:Tsuperregister);
procedure check_unreleasedregs;
protected
regtype : Tregistertype;
{ default subregister used }
defaultsub : tsubregister;
{# Adds an interference edge.}
procedure add_edge(u,v:Tsuperregister);
procedure add_constraints(reg:Tregister);virtual;
private
{# First imaginary register.}
first_imaginary : Tsuperregister;
{# Highest register allocated until now.}
@ -259,7 +228,21 @@ unit rgobj;
coalesced_moves,
constrained_moves : Tlinkedlist;
live_registers:Tsuperregisterworklist;
function getnewreg:tsuperregister;
{$ifdef EXTDEBUG}
procedure writegraph(loopidx:longint);
{$endif EXTDEBUG}
{# Prepare the register colouring.}
procedure prepare_colouring;
{# Clean up after register colouring.}
procedure epilogue_colouring;
{# Colour the registers; that is do the register allocation.}
procedure colour_registers;
{# Spills certain registers in the specified assembler list.}
procedure insert_regalloc_info(list:Taasmoutput;headertai:tai);
procedure generate_interference_graph(list:Taasmoutput;headertai:tai);
procedure translate_registers(list:Taasmoutput);
function spill_registers(list:Taasmoutput;headertai:tai):boolean;
function getnewreg(subreg:tsubregister):tsuperregister;
procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
procedure add_edges_used(u:Tsuperregister);
@ -429,7 +412,7 @@ implementation
end;
function trgobj.getnewreg:tsuperregister;
function trgobj.getnewreg(subreg:tsubregister):tsuperregister;
var
oldmaxreginfo : tsuperregister;
begin
@ -447,24 +430,16 @@ implementation
{ Do we really need it to clear it ? At least for 1.0.x (PFV) }
fillchar(reginfo[oldmaxreginfo],(maxreginfo-oldmaxreginfo)*sizeof(treginfo),0);
end;
reginfo[result].subreg:=subreg;
end;
function trgobj.getregister(list:Taasmoutput;subreg:Tsubregister):Tregister;
var
p : Tsuperregister;
r : Tregister;
begin
p:=getnewreg;
live_registers.add(p);
if defaultsub=R_SUBNONE then
r:=newreg(regtype,p,R_SUBNONE)
result:=newreg(regtype,getnewreg(R_SUBNONE),R_SUBNONE)
else
r:=newreg(regtype,p,subreg);
list.concat(Tai_regalloc.alloc(r));
add_edges_used(p);
add_constraints(r);
result:=r;
result:=newreg(regtype,getnewreg(subreg),subreg);
end;
@ -475,29 +450,23 @@ implementation
procedure trgobj.ungetregister(list:Taasmoutput;r:Tregister);
var supreg:Tsuperregister;
begin
supreg:=getsupreg(r);
if live_registers.delete(supreg) then
list.concat(Tai_regalloc.dealloc(r));
end;
begin
{ Only explicit allocs insert regalloc info }
if getsupreg(r)<first_imaginary then
list.concat(Tai_regalloc.dealloc(r));
end;
procedure trgobj.getexplicitregister(list:Taasmoutput;r:Tregister);
var supreg:Tsuperregister;
begin
supreg:=getsupreg(r);
live_registers.add(supreg);
if supreg<first_imaginary then
var
supreg:Tsuperregister;
begin
supreg:=getsupreg(r);
if supreg>=first_imaginary then
internalerror(2003121503);
include(used_in_proc,supreg);
list.concat(Tai_regalloc.alloc(r));
add_edges_used(supreg);
add_constraints(r);
end;
list.concat(Tai_regalloc.alloc(r));
end;
procedure trgobj.allocexplicitregisters(list:Taasmoutput;r:Tcpuregisterset);
@ -507,7 +476,7 @@ implementation
begin
for i:=0 to first_imaginary-1 do
if i in r then
getexplicitregister(list,i);
getexplicitregister(list,newreg(regtype,i,defaultsub));
end;
@ -518,7 +487,7 @@ implementation
begin
for i:=0 to first_imaginary-1 do
if i in r then
ungetregister(list,i);
ungetregister(list,newreg(regtype,i,defaultsub));
end;
@ -527,6 +496,12 @@ implementation
spillingcounter:byte;
endspill:boolean;
begin
{ Insert regalloc info for imaginary registers }
insert_regalloc_info(list,headertai);
generate_interference_graph(list,headertai);
{ Don't do the real allocation when -sr is passed }
if (cs_no_regalloc in aktglobalswitches) then
exit;
{Do register allocation.}
spillingcounter:=0;
repeat
@ -542,6 +517,7 @@ implementation
endspill:=not spill_registers(list,headertai);
end;
until endspill;
translate_registers(list);
end;
@ -588,8 +564,9 @@ implementation
var i:word;
begin
for i:=0 to live_registers.length-1 do
add_edge(u,live_registers.buf[i]);
if live_registers.length>0 then
for i:=0 to live_registers.length-1 do
add_edge(u,live_registers.buf[i]);
end;
{$ifdef EXTDEBUG}
@ -644,6 +621,21 @@ implementation
inc(reginfo[u].movelist^.count);
end;
procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
var
supreg : tsuperregister;
begin
supreg:=getsupreg(r);
if supreg>=first_imaginary then
begin
if not assigned(reginfo[supreg].live_start) then
reginfo[supreg].live_start:=instr;
reginfo[supreg].live_end:=instr;
end;
end;
procedure trgobj.add_move_instruction(instr:Taicpu);
{This procedure notifies a certain as a move instruction so the
@ -827,8 +819,8 @@ implementation
procedure trgobj.simplify;
var adj : Psuperregisterworklist;
p,n : Tsuperregister;
min,i:word;
n : Tsuperregister;
i : word;
begin
{We take the element with the least interferences out of the
simplifyworklist. Since the simplifyworklist is now sorted, we
@ -1367,7 +1359,7 @@ implementation
var p:Tsuperregister;
r:Tregister;
begin
p:=getnewreg;
p:=getnewreg(subreg);
live_registers.add(p);
r:=newreg(regtype,p,subreg);
if position=nil then
@ -1395,6 +1387,105 @@ implementation
end;
procedure trgobj.insert_regalloc_info(list:Taasmoutput;headertai:tai);
var
supreg : tsuperregister;
p : tai;
r : tregister;
begin
{ Insert regallocs for all imaginary registers }
for supreg:=first_imaginary to maxreg-1 do
begin
r:=newreg(regtype,supreg,reginfo[supreg].subreg);
if assigned(reginfo[supreg].live_start) then
begin
{$ifdef EXTDEBUG}
if reginfo[supreg].live_start=reginfo[supreg].live_end then
Comment(V_Warning,'Register '+std_regname(r)+' is only used once');
{$endif EXTDEBUG}
list.insertbefore(Tai_regalloc.alloc(r),reginfo[supreg].live_start);
{ Insert live end deallocation before reg allocations
to reduce conflicts }
p:=reginfo[supreg].live_end;
while assigned(p) and
assigned(p.previous) and
(tai(p.previous).typ=ait_regalloc) and
tai_regalloc(p.previous).allocation do
p:=tai(p.previous);
list.insertbefore(Tai_regalloc.dealloc(r),p);
end
{$ifdef EXTDEBUG}
else
Comment(V_Warning,'Register '+std_regname(r)+' not used');
{$endif EXTDEBUG}
end;
end;
procedure trgobj.generate_interference_graph(list:Taasmoutput;headertai:tai);
var
p : tai;
i : integer;
supreg : tsuperregister;
begin
{ All allocations are available. Now we can generate the
interference graph. Walk through all instructions, we can
start with the headertai, because before the header tai is
only symbols. }
live_registers.clear;
p:=headertai;
while assigned(p) do
begin
case p.typ of
ait_regalloc:
begin
if (getregtype(Tai_regalloc(p).reg)=regtype) then
begin
supreg:=getsupreg(Tai_regalloc(p).reg);
if Tai_regalloc(p).allocation then
live_registers.add(supreg)
else
live_registers.delete(supreg);
add_edges_used(supreg);
add_constraints(Tai_regalloc(p).reg);
end;
end;
{ ait_instruction:
begin
aktfilepos:=Taicpu_abstract(p).fileinfo;
for i:=0 to Taicpu_abstract(p).ops-1 do
with Taicpu_abstract(p).oper[i]^ do
begin
case typ of
top_reg :
begin
add_edges_used(getsupreg(reg));
add_constraints(reg);
end;
top_ref :
begin
add_edges_used(getsupreg(ref^.base));
add_constraints(ref^.base);
add_edges_used(getsupreg(ref^.index));
add_constraints(ref^.index);
end;
end;
end;
end; }
end;
p:=Tai(p.next);
end;
{$ifdef EXTDEBUG}
if live_registers.length>0 then
begin
for i:=0 to live_registers.length-1 do
Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,live_registers.buf[i],defaultsub))+' not released');
end;
{$endif}
end;
function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
{Returns true if any help registers have been used.}
@ -1473,8 +1564,7 @@ implementation
live_registers,
spill_temps^) then
spill_registers:=true;
if Taicpu_abstract(p).is_move then
if Taicpu_abstract(p).is_reg_move then
add_move_instruction(Taicpu(p));
end;
end;
@ -1579,15 +1669,16 @@ implementation
end;
procedure Trgobj.check_unreleasedregs;
begin
end;
end.
{
$Log$
Revision 1.102 2003-12-15 16:37:47 daniel
Revision 1.103 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.102 2003/12/15 16:37:47 daniel
* More microoptimizations
Revision 1.101 2003/12/15 15:58:58 peter

View File

@ -13,6 +13,7 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
{$mode objfpc}
{$i+}
program mkx86reg;
@ -383,8 +384,8 @@ begin
end
else
first:=false;
writeln(confile,names[i],' = ',numbers[i],';');
write(numfile,numbers[i]);
writeln(confile,names[i],' = ','tregister(',numbers[i],')',';');
write(numfile,'tregister(',numbers[i],')');
write(stdfile,'''',stdnames[i],'''');
write(attfile,'''',attnames[i],'''');
if not(x86_64) then
@ -457,7 +458,13 @@ begin
end.
{
$Log$
Revision 1.3 2003-09-24 17:11:33 florian
Revision 1.4 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.3 2003/09/24 17:11:33 florian
* x86_64 support; turn on by passing x86_64
Revision 1.2 2003/09/03 15:55:02 peter

View File

@ -201,7 +201,7 @@ interface
procedure Pass2(sec:TAsmObjectdata);virtual;
procedure SetOperandOrder(order:TOperandOrder);
function is_nop:boolean;override;
function is_move:boolean;override;
function is_reg_move:boolean;override;
function spill_registers(list:Taasmoutput;
rgget:Trggetproc;
rgunget:Trgungetproc;
@ -1904,7 +1904,7 @@ implementation
(opcode=A_XCHG) and (oper[0]^.typ=top_reg) and (oper[1]^.typ=top_reg) and (oper[0]^.reg=oper[1]^.reg);
end;
function Taicpu.is_move:boolean;
function Taicpu.is_reg_move:boolean;
begin
{We do not check the number of operands; we assume that nobody constructs
@ -1912,7 +1912,7 @@ implementation
a move between a reference and a register is not a move that is of
interrest to the register allocation, therefore we only return true
for a move between two registers. (DM)}
is_move:=((opcode=A_MOV) or (opcode=A_MOVZX) or (opcode=A_MOVSX)) and
result:=((opcode=A_MOV) or (opcode=A_MOVZX) or (opcode=A_MOVSX)) and
((oper[0]^.typ=top_reg) and (oper[1]^.typ=top_reg));
end;
@ -2344,7 +2344,13 @@ implementation
end.
{
$Log$
Revision 1.39 2003-12-14 20:24:28 daniel
Revision 1.40 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.39 2003/12/14 20:24:28 daniel
* Register allocator speed optimizations
- Worklist no longer a ringbuffer
- No find operations are left

View File

@ -43,10 +43,10 @@ unit cgx86;
function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
procedure ungetregister(list:Taasmoutput;r:Tregister);override;
procedure ungetreference(list:Taasmoutput;const r:Treference);override;
procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
function uses_registers(rt:Tregistertype):boolean;override;
procedure add_reg_instruction(instr:Tai;r:tregister);override;
procedure dec_fpu_stack;
procedure inc_fpu_stack;
@ -211,15 +211,6 @@ unit cgx86;
end;
procedure tcgx86.ungetreference(list:Taasmoutput;const r:Treference);
begin
if r.base<>NR_NO then
ungetregister(list,r.base);
if r.index<>NR_NO then
ungetregister(list,r.index);
end;
procedure Tcgx86.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
begin
if rt<>R_FPUREGISTER then
@ -243,6 +234,13 @@ unit cgx86;
end;
procedure tcgx86.add_reg_instruction(instr:Tai;r:tregister);
begin
if getregtype(r)<>R_FPUREGISTER then
inherited add_reg_instruction(instr,r);
end;
procedure tcgx86.dec_fpu_stack;
begin
dec(rgfpu.fpuvaroffset);
@ -1426,18 +1424,18 @@ unit cgx86;
system_i386_win32,
{$endif}
system_i386_freebsd,
system_i386_netbsd,
// system_i386_openbsd,
system_i386_netbsd,
// system_i386_openbsd,
system_i386_wdosx,
system_i386_linux:
begin
Case target_info.system Of
system_i386_freebsd : mcountprefix:='.';
system_i386_netbsd : mcountprefix:='__';
// system_i386_openbsd : mcountprefix:='.';
else
mcountPrefix:='';
end;
Case target_info.system Of
system_i386_freebsd : mcountprefix:='.';
system_i386_netbsd : mcountprefix:='__';
// system_i386_openbsd : mcountprefix:='.';
else
mcountPrefix:='';
end;
objectlibrary.getaddrlabel(pl);
list.concat(Tai_section.Create(sec_data));
list.concat(Tai_align.Create(4));
@ -1684,7 +1682,13 @@ unit cgx86;
end.
{
$Log$
Revision 1.90 2003-12-12 17:16:18 peter
Revision 1.91 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.90 2003/12/12 17:16:18 peter
* rg[tregistertype] added in tcg
Revision 1.89 2003/12/06 01:15:23 florian

View File

@ -176,7 +176,7 @@ uses
{$endif x86_64}
);
regstabs_table : array[tregisterindex] of tregister = (
regstabs_table : array[tregisterindex] of shortint = (
{$ifdef x86_64}
{$i r8664stab.inc}
{$else x86_64}
@ -526,7 +526,13 @@ implementation
end.
{
$Log$
Revision 1.30 2003-10-31 09:22:55 mazen
Revision 1.31 2003-12-15 21:25:49 peter
* reg allocations for imaginary register are now inserted just
before reg allocation
* tregister changed to enum to allow compile time check
* fixed several tregister-tsuperregister errors
Revision 1.30 2003/10/31 09:22:55 mazen
* using findreg_by_<name|number>_table directly to decrease heap overheading
Revision 1.29 2003/10/30 17:13:18 peter