From 742ff35c480cfc4e63804d5cc9d72bd687fcf1f8 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Fri, 7 Dec 2007 17:58:25 +0000 Subject: [PATCH] + 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 - --- compiler/ncal.pas | 26 ++++++++++++++++---------- compiler/ncnv.pas | 11 +++++++++++ compiler/node.pas | 10 ++++++++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/compiler/ncal.pas b/compiler/ncal.pas index 1ec34a7760..1e8969ff89 100644 --- a/compiler/ncal.pas +++ b/compiler/ncal.pas @@ -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 diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index ecaa7467f4..8d7326c6b1 100644 --- a/compiler/ncnv.pas +++ b/compiler/ncnv.pas @@ -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 diff --git a/compiler/node.pas b/compiler/node.pas index 1f183e849d..b9bde1f14f 100644 --- a/compiler/node.pas +++ b/compiler/node.pas @@ -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;