+ also optimize assignments from calls to by-reference "results":

o it's a by-reference parameter, but ignore that since it's
      guaranteed to be safe because of the escape analysis
    o it's wrapped in an absolute type conversion -> added
      actualtargetnode method to tnode which digs through that

git-svn-id: trunk@9412 -
This commit is contained in:
Jonas Maebe 2007-12-07 17:58:25 +00:00
parent 915aa94e2d
commit 742ff35c48
3 changed files with 37 additions and 10 deletions

View File

@ -1657,6 +1657,7 @@ implementation
procedure tcallnode.maybe_create_funcret_node;
var
temp : ttempcreatenode;
realassignmenttarget: tnode;
begin
{ For the function result we need to create a temp node for:
- Inlined functions
@ -1683,6 +1684,8 @@ implementation
of the refcount before being assigned. This is all done after the call so there
is no issue with exceptions and possible use of the old value in the called
function }
if assigned(aktassignmentnode) then
realassignmenttarget:=aktassignmentnode.left.actualtargetnode;
if assigned(aktassignmentnode) and
(aktassignmentnode.right=self) and
(aktassignmentnode.left.resultdef=resultdef) and
@ -1700,27 +1703,30 @@ implementation
is_simple_para_load(aktassignmentnode.left,false)
) or
(
(aktassignmentnode.left.nodetype = temprefn) and
not(ti_addr_taken in ttemprefnode(aktassignmentnode.left).tempinfo^.flags) and
not(ti_may_be_in_reg in ttemprefnode(aktassignmentnode.left).tempinfo^.flags)
(realassignmenttarget.nodetype=temprefn) and
not(ti_addr_taken in ttemprefnode(realassignmenttarget).tempinfo^.flags) and
not(ti_may_be_in_reg in ttemprefnode(realassignmenttarget).tempinfo^.flags)
) or
(
(aktassignmentnode.left.nodetype = loadn) and
(realassignmenttarget.nodetype=loadn) and
{ nested procedures may access the current procedure's locals }
(procdefinition.parast.symtablelevel=normal_function_level) and
{ must be a local variable or a value para }
{ must be a local variable, a value para or a hidden function result }
{ parameter (which can be passed by address, but in that case it got }
{ through these same checks at the caller side and is thus safe }
(
(tloadnode(aktassignmentnode.left).symtableentry.typ = localvarsym) or
(tloadnode(realassignmenttarget).symtableentry.typ=localvarsym) or
(
(tloadnode(aktassignmentnode.left).symtableentry.typ = paravarsym) and
(tparavarsym(tloadnode(aktassignmentnode.left).symtableentry).varspez = vs_value)
(tloadnode(realassignmenttarget).symtableentry.typ=paravarsym) and
((tparavarsym(tloadnode(realassignmenttarget).symtableentry).varspez = vs_value) or
(vo_is_funcret in tparavarsym(tloadnode(realassignmenttarget).symtableentry).varoptions))
)
) and
{ the address may not have been taken of the variable/parameter, because }
{ otherwise it's possible that the called function can access it via a }
{ global variable or other stored state }
not(tabstractvarsym(tloadnode(aktassignmentnode.left).symtableentry).addr_taken) and
(tabstractvarsym(tloadnode(aktassignmentnode.left).symtableentry).varregable in [vr_none,vr_addr])
not(tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).addr_taken) and
(tabstractvarsym(tloadnode(realassignmenttarget).symtableentry).varregable in [vr_none,vr_addr])
)
) then
begin

View File

@ -47,6 +47,7 @@ interface
procedure buildderefimpl;override;
procedure derefimpl;override;
function dogetcopy : tnode;override;
function actualtargetnode: tnode;override;
procedure printnodeinfo(var t : text);override;
function pass_1 : tnode;override;
function pass_typecheck:tnode;override;
@ -1631,6 +1632,16 @@ implementation
end;
function ttypeconvnode.actualtargetnode: tnode;
begin
result:=self;
while (result.nodetype=typeconvn) and
(nf_absolute in result.flags) and
(resultdef.size=left.resultdef.size) do
result:=ttypeconvnode(result).left;
end;
function ttypeconvnode.pass_typecheck:tnode;
var

View File

@ -343,6 +343,10 @@ interface
{ does the real copying of a node }
function dogetcopy : tnode;virtual;
{ returns the real loadn/temprefn a node refers to,
skipping (absolute) equal type conversions }
function actualtargetnode: tnode;virtual;
procedure insertintolist(l : tnodelist);virtual;
{ writes a node for debugging purpose, shouldn't be called }
@ -871,6 +875,12 @@ implementation
end;
function tnode.actualtargetnode: tnode;
begin
result:=self;
end;
procedure tnode.insertintolist(l : tnodelist);
begin
end;