|
@@ -4944,6 +4944,14 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
+ function UsesTmp(var n: tnode; arg: pointer): foreachnoderesult;
|
|
|
|
+ begin
|
|
|
|
+ Result:=fen_false;
|
|
|
|
+ if (n.nodetype=temprefn) and (ttemprefnode(n).tempinfo=arg) then
|
|
|
|
+ Result:=fen_norecurse_true;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
function tcallnode.optimize_funcret_assignment(inlineblock: tblocknode): tnode;
|
|
function tcallnode.optimize_funcret_assignment(inlineblock: tblocknode): tnode;
|
|
var
|
|
var
|
|
hp : tstatementnode;
|
|
hp : tstatementnode;
|
|
@@ -4955,6 +4963,10 @@ implementation
|
|
not(cnf_return_value_used in callnodeflags) then
|
|
not(cnf_return_value_used in callnodeflags) then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
|
|
+ { block already optimized? }
|
|
|
|
+ if not(inlineblock.nodetype=blockn) then
|
|
|
|
+ exit;
|
|
|
|
+
|
|
{ tempcreatenode for the function result }
|
|
{ tempcreatenode for the function result }
|
|
hp:=tstatementnode(inlineblock.left);
|
|
hp:=tstatementnode(inlineblock.left);
|
|
if not(assigned(hp)) or
|
|
if not(assigned(hp)) or
|
|
@@ -4962,13 +4974,22 @@ implementation
|
|
not(nf_is_funcret in hp.left.flags) then
|
|
not(nf_is_funcret in hp.left.flags) then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
- { constant assignment? right must be a constant (mainly to avoid trying
|
|
|
|
- to reuse local temps which may already be freed afterwards once these
|
|
|
|
- checks are made looser) }
|
|
|
|
hp:=tstatementnode(hp.right);
|
|
hp:=tstatementnode(hp.right);
|
|
if not(assigned(hp)) or
|
|
if not(assigned(hp)) or
|
|
- (hp.left.nodetype<>assignn) or
|
|
|
|
- not is_constnode(tassignmentnode(hp.left).right) then
|
|
|
|
|
|
+ (hp.left.nodetype<>assignn)
|
|
|
|
+ { FK: check commented, original comment was:
|
|
|
|
+
|
|
|
|
+ constant assignment? right must be a constant (mainly to avoid trying
|
|
|
|
+ to reuse local temps which may already be freed afterwards once these
|
|
|
|
+ checks are made looser)
|
|
|
|
+
|
|
|
|
+ or
|
|
|
|
+ not is_constnode(tassignmentnode(hp.left).right)
|
|
|
|
+
|
|
|
|
+ So far I found no example why removing this check might be a problem.
|
|
|
|
+ If this needs to be revert, issue #36279 must be checked/solved again.
|
|
|
|
+ }
|
|
|
|
+ then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
{ left must be function result }
|
|
{ left must be function result }
|
|
@@ -4979,7 +5000,9 @@ implementation
|
|
if (hp2.nodetype=typeconvn) and (ttypeconvnode(hp2).convtype=tc_equal) then
|
|
if (hp2.nodetype=typeconvn) and (ttypeconvnode(hp2).convtype=tc_equal) then
|
|
hp2:=ttypeconvnode(hp2).left;
|
|
hp2:=ttypeconvnode(hp2).left;
|
|
if (hp2.nodetype<>temprefn) or
|
|
if (hp2.nodetype<>temprefn) or
|
|
- not(nf_is_funcret in hp2.flags) then
|
|
|
|
|
|
+ { check if right references the temp. being removed, i.e. using an uninitialized result }
|
|
|
|
+ foreachnodestatic(resassign.right,@UsesTmp,ttemprefnode(hp2).tempinfo) or
|
|
|
|
+ not(nf_is_funcret in hp2.flags) then
|
|
exit;
|
|
exit;
|
|
|
|
|
|
{ tempdelete to normal of the function result }
|
|
{ tempdelete to normal of the function result }
|
|
@@ -5000,7 +5023,7 @@ implementation
|
|
exit;
|
|
exit;
|
|
|
|
|
|
{ we made it! }
|
|
{ we made it! }
|
|
- result:=tassignmentnode(resassign).right.getcopy;
|
|
|
|
|
|
+ result:=ctypeconvnode.create_internal(tassignmentnode(resassign).right.getcopy,hp2.resultdef);
|
|
firstpass(result);
|
|
firstpass(result);
|
|
end;
|
|
end;
|
|
|
|
|