mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 01:49:20 +02:00
* Improved the parentfp optimization to properly handle cases when a nested routine calls other nested routines.
git-svn-id: trunk@45665 -
This commit is contained in:
parent
c15b6f4516
commit
7bffafdf8b
@ -3516,7 +3516,19 @@ implementation
|
|||||||
if not assigned(right) then
|
if not assigned(right) then
|
||||||
begin
|
begin
|
||||||
if assigned(procdefinition.owner.defowner) then
|
if assigned(procdefinition.owner.defowner) then
|
||||||
hiddentree:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner),lpf_forpara)
|
begin
|
||||||
|
if paramanager.can_opt_unused_para(currpara) and
|
||||||
|
(procdefinition<>current_procinfo.procdef) then
|
||||||
|
{ If parentfp is unused by the target proc, create loadparentfpnode which loads
|
||||||
|
the current frame pointer to prevent generation of unneeded code. }
|
||||||
|
hiddentree:=cloadparentfpnode.create(current_procinfo.procdef,lpf_forpara)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
hiddentree:=cloadparentfpnode.create(tprocdef(procdefinition.owner.defowner),lpf_forpara);
|
||||||
|
if is_nested_pd(current_procinfo.procdef) then
|
||||||
|
current_procinfo.set_needs_parentfp(tprocdef(procdefinition.owner.defowner).parast.symtablelevel);
|
||||||
|
end;
|
||||||
|
end
|
||||||
{ exceptfilters called from main level are not owned }
|
{ exceptfilters called from main level are not owned }
|
||||||
else if procdefinition.proctypeoption=potype_exceptfilter then
|
else if procdefinition.proctypeoption=potype_exceptfilter then
|
||||||
hiddentree:=cloadparentfpnode.create(current_procinfo.procdef,lpf_forpara)
|
hiddentree:=cloadparentfpnode.create(current_procinfo.procdef,lpf_forpara)
|
||||||
|
@ -138,29 +138,6 @@ implementation
|
|||||||
wpobase;
|
wpobase;
|
||||||
|
|
||||||
|
|
||||||
function can_opt_unused_para(parasym: tparavarsym): boolean;
|
|
||||||
var
|
|
||||||
pd: tprocdef;
|
|
||||||
begin
|
|
||||||
{ The parameter can be optimized as unused when:
|
|
||||||
optimization level 1 and higher
|
|
||||||
this is a direct call to a routine, not a procvar
|
|
||||||
and the routine is not an exception filter
|
|
||||||
and the parameter is not used by the routine
|
|
||||||
and implementation of the routine is already processed.
|
|
||||||
}
|
|
||||||
result:=(cs_opt_level1 in current_settings.optimizerswitches) and
|
|
||||||
assigned(parasym.Owner) and
|
|
||||||
(parasym.Owner.defowner.typ=procdef);
|
|
||||||
if not result then
|
|
||||||
exit;
|
|
||||||
pd:=tprocdef(parasym.Owner.defowner);
|
|
||||||
result:=(pd.proctypeoption<>potype_exceptfilter) and
|
|
||||||
not parasym.is_used and
|
|
||||||
pd.is_implemented;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function can_skip_para_push(parasym: tparavarsym): boolean;
|
function can_skip_para_push(parasym: tparavarsym): boolean;
|
||||||
begin
|
begin
|
||||||
{ We can skip passing the parameter when:
|
{ We can skip passing the parameter when:
|
||||||
@ -169,7 +146,7 @@ implementation
|
|||||||
and fixed stack is used
|
and fixed stack is used
|
||||||
or the parameter is in a register
|
or the parameter is in a register
|
||||||
or the parameter is $parentfp. }
|
or the parameter is $parentfp. }
|
||||||
result:=can_opt_unused_para(parasym) and
|
result:=paramanager.can_opt_unused_para(parasym) and
|
||||||
not paramanager.has_strict_proc_signature and
|
not paramanager.has_strict_proc_signature and
|
||||||
(paramanager.use_fixed_stack or
|
(paramanager.use_fixed_stack or
|
||||||
(vo_is_parentfp in parasym.varoptions) or
|
(vo_is_parentfp in parasym.varoptions) or
|
||||||
@ -322,7 +299,7 @@ implementation
|
|||||||
function tcgcallparanode.maybe_push_unused_para: boolean;
|
function tcgcallparanode.maybe_push_unused_para: boolean;
|
||||||
begin
|
begin
|
||||||
{ Check if the parameter is unused and can be optimized }
|
{ Check if the parameter is unused and can be optimized }
|
||||||
result:=can_opt_unused_para(parasym);
|
result:=paramanager.can_opt_unused_para(parasym);
|
||||||
if not result then
|
if not result then
|
||||||
exit;
|
exit;
|
||||||
{ If we can't skip loading of the parameter, load an undefined dummy value. }
|
{ If we can't skip loading of the parameter, load an undefined dummy value. }
|
||||||
|
@ -357,6 +357,7 @@ implementation
|
|||||||
if assigned(left) then
|
if assigned(left) then
|
||||||
internalerror(200309289);
|
internalerror(200309289);
|
||||||
left:=cloadparentfpnode.create(tprocdef(symtable.defowner),lpf_forload);
|
left:=cloadparentfpnode.create(tprocdef(symtable.defowner),lpf_forload);
|
||||||
|
current_procinfo.set_needs_parentfp(tprocdef(symtable.defowner).parast.symtablelevel);
|
||||||
{ reference in nested procedures, variable needs to be in memory }
|
{ reference in nested procedures, variable needs to be in memory }
|
||||||
{ and behaves as if its address escapes its parent block }
|
{ and behaves as if its address escapes its parent block }
|
||||||
make_not_regable(self,[ra_different_scope]);
|
make_not_regable(self,[ra_different_scope]);
|
||||||
|
@ -316,8 +316,6 @@ implementation
|
|||||||
internalerror(200309284);
|
internalerror(200309284);
|
||||||
parentpd:=pd;
|
parentpd:=pd;
|
||||||
kind:=fpkind;
|
kind:=fpkind;
|
||||||
if current_procinfo.procdef.parast.symtablelevel>pd.parast.symtablelevel then
|
|
||||||
current_procinfo.set_needs_parentfp(pd.parast.symtablelevel);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,6 +165,8 @@ unit paramgr;
|
|||||||
and checked by the runtime/backend compiler (e.g. JVM, LLVM).
|
and checked by the runtime/backend compiler (e.g. JVM, LLVM).
|
||||||
The default implementation returns false. }
|
The default implementation returns false. }
|
||||||
function has_strict_proc_signature: boolean; virtual;
|
function has_strict_proc_signature: boolean; virtual;
|
||||||
|
{ Returns true if parasym is unused and can be optimized. }
|
||||||
|
function can_opt_unused_para(parasym: tparavarsym): boolean;
|
||||||
strict protected
|
strict protected
|
||||||
{ common part of get_funcretloc; returns true if retloc is completely
|
{ common part of get_funcretloc; returns true if retloc is completely
|
||||||
initialized afterwards }
|
initialized afterwards }
|
||||||
@ -195,6 +197,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
systems,
|
systems,
|
||||||
|
globals,
|
||||||
cgobj,tgobj,
|
cgobj,tgobj,
|
||||||
defutil,verbose,
|
defutil,verbose,
|
||||||
hlcgobj;
|
hlcgobj;
|
||||||
@ -833,6 +836,28 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tparamanager.can_opt_unused_para(parasym: tparavarsym): boolean;
|
||||||
|
var
|
||||||
|
pd: tprocdef;
|
||||||
|
begin
|
||||||
|
{ The parameter can be optimized as unused when:
|
||||||
|
optimization level 1 and higher
|
||||||
|
this is a direct call to a routine, not a procvar
|
||||||
|
and the routine is not an exception filter
|
||||||
|
and the parameter is not used by the routine
|
||||||
|
and implementation of the routine is already processed.
|
||||||
|
}
|
||||||
|
result:=(cs_opt_level1 in current_settings.optimizerswitches) and
|
||||||
|
assigned(parasym.Owner) and
|
||||||
|
(parasym.Owner.defowner.typ=procdef);
|
||||||
|
if not result then
|
||||||
|
exit;
|
||||||
|
pd:=tprocdef(parasym.Owner.defowner);
|
||||||
|
result:=(pd.proctypeoption<>potype_exceptfilter) and
|
||||||
|
not parasym.is_used and
|
||||||
|
pd.is_implemented;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
;
|
;
|
||||||
finalization
|
finalization
|
||||||
|
@ -439,9 +439,10 @@ implementation
|
|||||||
pi : tprocinfo;
|
pi : tprocinfo;
|
||||||
p : tparavarsym;
|
p : tparavarsym;
|
||||||
begin
|
begin
|
||||||
if (procdef.parast.symtablelevel<=normal_function_level)
|
if procdef.parast.symtablelevel<=normal_function_level then
|
||||||
or (procdef.parast.symtablelevel<=parent_level) then
|
|
||||||
Internalerror(2020050302);
|
Internalerror(2020050302);
|
||||||
|
if procdef.parast.symtablelevel<=parent_level then
|
||||||
|
exit;
|
||||||
if parent_level<normal_function_level then
|
if parent_level<normal_function_level then
|
||||||
parent_level:=normal_function_level;
|
parent_level:=normal_function_level;
|
||||||
{ Mark parentfp as used for the current proc }
|
{ Mark parentfp as used for the current proc }
|
||||||
|
Loading…
Reference in New Issue
Block a user