* optimized register allocation for tempnodes

git-svn-id: trunk@2221 -
This commit is contained in:
Jonas Maebe 2006-01-08 12:53:43 +00:00
parent 8039c477af
commit e4451558c4
3 changed files with 84 additions and 40 deletions

View File

@ -133,6 +133,8 @@ interface
{ a node which is a reference to a certain temp }
ttemprefnode = class(tnode)
tempinfo: ptempinfo;
constructor create(const temp: ttempcreatenode); virtual;
constructor create_offset(const temp: ttempcreatenode;aoffset:longint);
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
@ -145,9 +147,8 @@ interface
function docompare(p: tnode): boolean; override;
procedure printnodedata(var t:text);override;
protected
tempinfo: ptempinfo;
offset : longint;
private
private
tempidx : longint;
end;
ttemprefnodeclass = class of ttemprefnode;

View File

@ -66,7 +66,7 @@ interface
implementation
uses
globtype,systems,
globtype,globals,systems,
cutils,verbose,
aasmbase,aasmtai,aasmcpu,symsym,symconst,
defutil,
@ -430,8 +430,15 @@ interface
if not tempinfo^.valid then
internalerror(200108231);
location:=tempinfo^.location;
if tempinfo^.location.loc=LOC_REFERENCE then
inc(location.reference.offset,offset);
case tempinfo^.location.loc of
LOC_REFERENCE:
begin
inc(location.reference.offset,offset);
{ tempinfo^.valid should be set to false it it's a normal temp }
end;
LOC_REGISTER,LOC_FPUREGISTER:
tempinfo^.valid := false;
end;
end;
@ -467,33 +474,48 @@ interface
if release_to_normal then
tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tt_normal)
else
tg.UnGetTemp(exprasmlist,tempinfo^.location.reference);
begin
tg.UnGetTemp(exprasmlist,tempinfo^.location.reference);
tempinfo^.valid := false;
end;
end;
LOC_CREGISTER,
LOC_REGISTER:
begin
{ make sure the register allocator doesn't reuse the }
{ register e.g. in the middle of a loop }
{$ifndef cpu64bit}
if tempinfo^.location.size in [OS_64,OS_S64] then
if not(cs_regvars in aktglobalswitches) or
(pi_has_goto in current_procinfo.flags) then
begin
cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reghi);
cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reglo);
end
else
{ make sure the register allocator doesn't reuse the }
{ register e.g. in the middle of a loop }
{$ifndef cpu64bit}
if tempinfo^.location.size in [OS_64,OS_S64] then
begin
cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reghi);
cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reglo);
end
else
{$endif cpu64bit}
cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
end;
if release_to_normal then
tempinfo^.location.loc := LOC_REGISTER;
tempinfo^.location.loc := LOC_REGISTER
else
tempinfo^.valid := false;
end;
LOC_CFPUREGISTER,
LOC_FPUREGISTER:
begin
{ make sure the register allocator doesn't reuse the }
{ register e.g. in the middle of a loop }
cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
if not(cs_regvars in aktglobalswitches) or
(pi_has_goto in current_procinfo.flags) then
begin
{ make sure the register allocator doesn't reuse the }
{ register e.g. in the middle of a loop }
cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
end;
if release_to_normal then
tempinfo^.location.loc := LOC_FPUREGISTER;
tempinfo^.location.loc := LOC_FPUREGISTER
else
tempinfo^.valid := false;
end;
else
internalerror(200507161);

View File

@ -159,7 +159,7 @@ implementation
procinfo,paramgr,fmodule,
regvars,dwarf,dbgbase,
pass_1,pass_2,
ncon,nld,nutils,
nbas,ncon,nld,nutils,
tgobj,cgobj
{$ifdef powerpc}
, cpupi
@ -2121,29 +2121,50 @@ implementation
end;
procedure add_regvars(var rv: tusedregvars; const location: tlocation);
begin
case location.loc of
LOC_CREGISTER:
{$ifndef cpu64bit}
if location.size in [OS_64,OS_S64] then
begin
rv.intregvars.addnodup(getsupreg(location.register64.reglo));
rv.intregvars.addnodup(getsupreg(location.register64.reghi));
end
else
{$endif cpu64bit}
rv.intregvars.addnodup(getsupreg(location.register));
LOC_CFPUREGISTER:
rv.fpuregvars.addnodup(getsupreg(location.register));
LOC_CMMREGISTER:
rv.mmregvars.addnodup(getsupreg(location.register));
end;
end;
function do_get_used_regvars(var n: tnode; arg: pointer): foreachnoderesult;
var
rv: pusedregvars absolute arg;
begin
if (n.nodetype = loadn) and
(tloadnode(n).symtableentry.typ in [globalvarsym,localvarsym,paravarsym]) then
with tabstractnormalvarsym(tloadnode(n).symtableentry).localloc do
case loc of
LOC_CREGISTER:
{$ifndef cpu64bit}
if size in [OS_64,OS_S64] then
begin
rv^.intregvars.addnodup(getsupreg(register64.reglo));
rv^.intregvars.addnodup(getsupreg(register64.reghi));
end
else
{$endif cpu64bit}
rv^.intregvars.addnodup(getsupreg(register));
LOC_CFPUREGISTER:
rv^.fpuregvars.addnodup(getsupreg(register));
LOC_CMMREGISTER:
rv^.mmregvars.addnodup(getsupreg(register));
end;
case (n.nodetype) of
temprefn:
{ We only have to synchronise a tempnode before a loop if it is }
{ not created inside the loop, and only synchronise after the }
{ loop if it's not destroyed inside the loop. If it's created }
{ before the loop and not yet destroyed, then before the loop }
{ is secondpassed tempinfo^.valid will be true, and we get the }
{ correct registers. If it's not destroyed inside the loop, }
{ then after the loop has been secondpassed tempinfo^.valid }
{ be true and we also get the right registers. In other cases, }
{ tempinfo^.valid will be false and so we do not add }
{ unnecessary registers. This way, we don't have to look at }
{ tempcreate and tempdestroy nodes to get this info (JM) }
if (ttemprefnode(n).tempinfo^.valid) then
add_regvars(rv^,ttemprefnode(n).tempinfo^.location);
loadn:
if (tloadnode(n).symtableentry.typ in [globalvarsym,localvarsym,paravarsym]) then
add_regvars(rv^,tabstractnormalvarsym(tloadnode(n).symtableentry).localloc);
end;
result := fen_true;
end;