mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-05 15:30:52 +02:00
* load all complex loads of parameters that are needed multiple times
to a temp to prevent calling functions twice
This commit is contained in:
parent
50bbe3c205
commit
521b7cfa3b
@ -221,28 +221,35 @@ type
|
||||
|
||||
|
||||
procedure maybe_load_para_in_temp(var p:tnode);
|
||||
|
||||
function is_simple_node(hp:tnode):boolean;
|
||||
begin
|
||||
is_simple_node:=(hp.nodetype in [typen,loadvmtaddrn,loadn,arrayconstructorn]);
|
||||
end;
|
||||
|
||||
var
|
||||
hp : tnode;
|
||||
hp,
|
||||
loadp,
|
||||
refp : tnode;
|
||||
htype : ttype;
|
||||
ptemp : ttempcreatenode;
|
||||
usederef : boolean;
|
||||
newinitstatement,
|
||||
newdonestatement : tstatementnode;
|
||||
begin
|
||||
if not assigned(aktcallnode) then
|
||||
internalerror(200410121);
|
||||
|
||||
{ Load all complex loads into a temp to prevent
|
||||
double calls to a function. We can't simply check for a hp.nodetype=calln
|
||||
}
|
||||
hp:=p;
|
||||
while assigned(hp) and
|
||||
(hp.nodetype=typeconvn) do
|
||||
(hp.nodetype=typeconvn) and
|
||||
(ttypeconvnode(hp).convtype=tc_equal) do
|
||||
hp:=tunarynode(hp).left;
|
||||
if assigned(hp) and
|
||||
(
|
||||
{ call result must always be loaded in temp to prevent
|
||||
double creation }
|
||||
(hp.nodetype=calln)
|
||||
{ Also optimize also complex loads }
|
||||
{$warning Complex loads can also be optimized}
|
||||
// or not(hp.nodetype in [typen,loadvmtaddrn,loadn])
|
||||
) then
|
||||
not is_simple_node(hp) then
|
||||
begin
|
||||
if not assigned(aktcallnode.methodpointerinit) then
|
||||
begin
|
||||
@ -255,17 +262,35 @@ type
|
||||
newdonestatement:=laststatement(aktcallnode.methodpointerdone);
|
||||
end;
|
||||
{ temp create }
|
||||
ptemp:=ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent,true);
|
||||
usederef:=(p.resulttype.def.deftype in [arraydef,recorddef]) or
|
||||
is_shortstring(p.resulttype.def) or
|
||||
is_object(p.resulttype.def);
|
||||
if usederef then
|
||||
htype.setdef(tpointerdef.create(p.resulttype))
|
||||
else
|
||||
htype:=p.resulttype;
|
||||
ptemp:=ctempcreatenode.create(htype,htype.def.size,tt_persistent,true);
|
||||
if usederef then
|
||||
begin
|
||||
loadp:=caddrnode.create_internal(p);
|
||||
refp:=cderefnode.create(ctemprefnode.create(ptemp));
|
||||
end
|
||||
else
|
||||
begin
|
||||
loadp:=p;
|
||||
refp:=ctemprefnode.create(ptemp);
|
||||
end;
|
||||
addstatement(newinitstatement,ptemp);
|
||||
addstatement(newinitstatement,cassignmentnode.create(
|
||||
ctemprefnode.create(ptemp),
|
||||
p));
|
||||
resulttypepass(aktcallnode.methodpointerinit);
|
||||
loadp));
|
||||
{ new tree is only a temp reference }
|
||||
p:=ctemprefnode.create(ptemp);
|
||||
resulttypepass(p);
|
||||
p:=refp;
|
||||
{ temp release }
|
||||
addstatement(newdonestatement,ctempdeletenode.create(ptemp));
|
||||
{ call resulttypepass for new nodes }
|
||||
resulttypepass(p);
|
||||
resulttypepass(aktcallnode.methodpointerinit);
|
||||
resulttypepass(aktcallnode.methodpointerdone);
|
||||
end;
|
||||
end;
|
||||
@ -504,6 +529,8 @@ type
|
||||
{ set some settings needed for arrayconstructor }
|
||||
if is_array_constructor(left.resulttype.def) then
|
||||
begin
|
||||
if left.nodetype<>arrayconstructorn then
|
||||
internalerror(200504041);
|
||||
if is_array_of_const(parasym.vartype.def) then
|
||||
begin
|
||||
{ force variant array }
|
||||
@ -2520,7 +2547,11 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.282 2005-03-28 15:05:17 peter
|
||||
Revision 1.283 2005-04-05 21:07:43 peter
|
||||
* load all complex loads of parameters that are needed multiple times
|
||||
to a temp to prevent calling functions twice
|
||||
|
||||
Revision 1.282 2005/03/28 15:05:17 peter
|
||||
fix type of temps generated for parameters during inlining
|
||||
|
||||
Revision 1.281 2005/03/25 22:20:18 peter
|
||||
|
Loading…
Reference in New Issue
Block a user