mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 14:21:36 +01:00
* optimized register allocation for tempnodes
git-svn-id: trunk@2221 -
This commit is contained in:
parent
8039c477af
commit
e4451558c4
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user