mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-23 00:09:31 +02:00
+ be able to handle CSE's of records/arrays/objects
* consider static array/records/object variables during CSE determination on non x86 CPUs git-svn-id: trunk@21985 -
This commit is contained in:
parent
89ec13deeb
commit
a27cc3e5f2
@ -55,7 +55,7 @@ unit optcse;
|
||||
verbose,
|
||||
nutils,
|
||||
procinfo,
|
||||
nbas,nld,ninl,ncal,ncnv,nadd,
|
||||
nbas,nld,ninl,ncal,ncnv,nadd,nmem,
|
||||
pass_1,
|
||||
symconst,symtype,symdef,symsym,
|
||||
defutil,
|
||||
@ -125,38 +125,51 @@ unit optcse;
|
||||
if (n.flags*[nf_write,nf_modify]=[]) and
|
||||
{ node possible to add? }
|
||||
assigned(n.resultdef) and
|
||||
(tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) and
|
||||
{ is_int/fpuregable allows arrays and records to be in registers, cse cannot handle this }
|
||||
not(n.resultdef.typ in [arraydef,recorddef]) and
|
||||
{ same for voiddef }
|
||||
not(is_void(n.resultdef)) and
|
||||
{ adding tempref nodes is worthless but their complexity is probably <= 1 anyways }
|
||||
not(n.nodetype in [temprefn]) and
|
||||
(
|
||||
((tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable) and
|
||||
{ is_int/fpuregable allows arrays and records to be in registers, cse cannot handle this }
|
||||
(not(n.resultdef.typ in [arraydef,recorddef])) and
|
||||
{ same for voiddef }
|
||||
not(is_void(n.resultdef)) and
|
||||
{ adding tempref nodes is worthless but their complexity is probably <= 1 anyways }
|
||||
not(n.nodetype in [temprefn]) and
|
||||
|
||||
{ node worth to add?
|
||||
{ node worth to add?
|
||||
|
||||
We consider almost every node because even loading a variables from
|
||||
a register instead of memory is more beneficial. This behaviour should
|
||||
not increase register pressure because if a variable is already
|
||||
in a register, the reg. allocator can merge the nodes. If a variable
|
||||
is loaded from memory, loading this variable and spilling another register
|
||||
should not add a speed penalty.
|
||||
}
|
||||
{
|
||||
load nodes are not considered if they load para or local symbols from the
|
||||
current stack frame, those are in registers anyways if possible
|
||||
}
|
||||
(not(n.nodetype=loadn) or
|
||||
not(tloadnode(n).symtableentry.typ in [paravarsym,localvarsym]) or
|
||||
(tloadnode(n).symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel)
|
||||
) and
|
||||
We consider almost every node because even loading a variables from
|
||||
a register instead of memory is more beneficial. This behaviour should
|
||||
not increase register pressure because if a variable is already
|
||||
in a register, the reg. allocator can merge the nodes. If a variable
|
||||
is loaded from memory, loading this variable and spilling another register
|
||||
should not add a speed penalty.
|
||||
}
|
||||
{
|
||||
load nodes are not considered if they load para or local symbols from the
|
||||
current stack frame, those are in registers anyways if possible
|
||||
}
|
||||
(not(n.nodetype=loadn) or
|
||||
not(tloadnode(n).symtableentry.typ in [paravarsym,localvarsym]) or
|
||||
(tloadnode(n).symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel)
|
||||
) and
|
||||
|
||||
{
|
||||
Const nodes however are only considered if their complexity is >1
|
||||
This might be the case for the risc architectures if they need
|
||||
more than one instruction to load this particular value
|
||||
}
|
||||
(not(is_constnode(n)) or (node_complexity(n)>1)) then
|
||||
{
|
||||
Const nodes however are only considered if their complexity is >1
|
||||
This might be the case for the risc architectures if they need
|
||||
more than one instruction to load this particular value
|
||||
}
|
||||
(not(is_constnode(n)) or (node_complexity(n)>1)))
|
||||
{$ifndef x86}
|
||||
or
|
||||
{ loading the address of a global symbol takes typically more than
|
||||
one instruction on every platform except x86
|
||||
so consider in this case loading the address of the data
|
||||
}
|
||||
(((n.resultdef.typ in [arraydef,recorddef]) or is_object(n.resultdef)) and
|
||||
(n.nodetype=loadn) and
|
||||
(tloadnode(n).symtableentry.typ=staticvarsym)
|
||||
)
|
||||
{$endif x86}
|
||||
) then
|
||||
begin
|
||||
plists(arg)^.nodelist.Add(n);
|
||||
plists(arg)^.locationlist.Add(@n);
|
||||
@ -207,6 +220,7 @@ unit optcse;
|
||||
creates,
|
||||
statements : tstatementnode;
|
||||
hp : ttempcreatenode;
|
||||
addrstored : boolean;
|
||||
begin
|
||||
result:=fen_false;
|
||||
if n.nodetype in cseinvariant then
|
||||
@ -245,8 +259,17 @@ unit optcse;
|
||||
end;
|
||||
|
||||
def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
|
||||
templist[i]:=ctempcreatenode.create_value(def,def.size,tt_persistent,
|
||||
def.is_intregable or def.is_fpuregable,tnode(lists.nodelist[i]));
|
||||
{ we cannot handle register stored records or array in CSE yet
|
||||
but we can store their reference }
|
||||
addrstored:=(def.typ in [arraydef,recorddef]) or is_object(def);
|
||||
|
||||
if addrstored then
|
||||
templist[i]:=ctempcreatenode.create_value(getpointerdef(def),voidpointertype.size,tt_persistent,
|
||||
true,caddrnode.create(tnode(lists.nodelist[i])))
|
||||
else
|
||||
templist[i]:=ctempcreatenode.create_value(def,def.size,tt_persistent,
|
||||
def.is_intregable or def.is_fpuregable,tnode(lists.nodelist[i]));
|
||||
|
||||
{ make debugging easier and set temp. location to the original location }
|
||||
tnode(templist[i]).fileinfo:=tnode(lists.nodelist[i]).fileinfo;
|
||||
|
||||
@ -258,7 +281,10 @@ unit optcse;
|
||||
do_firstpass(tnode(hp));
|
||||
templist[i]:=hp;
|
||||
|
||||
pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[i]));
|
||||
if addrstored then
|
||||
pnode(lists.locationlist[i])^:=cderefnode.Create(ctemprefnode.create(ttempcreatenode(templist[i])))
|
||||
else
|
||||
pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[i]));
|
||||
{ make debugging easier and set temp. location to the original location }
|
||||
pnode(lists.locationlist[i])^.fileinfo:=tnode(lists.nodelist[i]).fileinfo;
|
||||
|
||||
@ -270,13 +296,21 @@ unit optcse;
|
||||
{ current node reference to another node? }
|
||||
else if lists.equalto[i]<>pointer(-1) then
|
||||
begin
|
||||
def:=tstoreddef(tnode(lists.nodelist[i]).resultdef);
|
||||
{ we cannot handle register stored records or array in CSE yet
|
||||
but we can store their reference }
|
||||
addrstored:=(def.typ in [arraydef,recorddef]) or is_object(def);
|
||||
|
||||
{$if defined(csedebug) or defined(csestats)}
|
||||
printnode(output,tnode(lists.nodelist[i]));
|
||||
writeln(i,' equals ',ptrint(lists.equalto[i]));
|
||||
printnode(output,tnode(lists.nodelist[ptrint(lists.equalto[i])]));
|
||||
{$endif defined(csedebug) or defined(csestats)}
|
||||
templist[i]:=templist[ptrint(lists.equalto[i])];
|
||||
pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[ptrint(lists.equalto[i])]));
|
||||
if addrstored then
|
||||
pnode(lists.locationlist[i])^:=cderefnode.Create(ctemprefnode.create(ttempcreatenode(templist[ptrint(lists.equalto[i])])))
|
||||
else
|
||||
pnode(lists.locationlist[i])^:=ctemprefnode.create(ttempcreatenode(templist[ptrint(lists.equalto[i])]));
|
||||
|
||||
{ make debugging easier and set temp. location to the original location }
|
||||
pnode(lists.locationlist[i])^.fileinfo:=tnode(lists.nodelist[i]).fileinfo;
|
||||
|
Loading…
Reference in New Issue
Block a user