mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 09:49:35 +02:00
* patch by J. Gareth Moreton: Nothing (NOP) node optimisation, resolves #38194
git-svn-id: trunk@49054 -
This commit is contained in:
parent
e89e010155
commit
c2ff85ac5b
@ -706,10 +706,31 @@ implementation
|
|||||||
|
|
||||||
|
|
||||||
function tblocknode.simplify(forinline : boolean): tnode;
|
function tblocknode.simplify(forinline : boolean): tnode;
|
||||||
{$ifdef break_inlining}
|
|
||||||
var
|
var
|
||||||
|
hp, nextp: TStatementNode;
|
||||||
|
lastp: TNode;
|
||||||
|
{$ifdef break_inlining}
|
||||||
a : array[0..3] of tstatementnode;
|
a : array[0..3] of tstatementnode;
|
||||||
{$endif break_inlining}
|
{$endif break_inlining}
|
||||||
|
|
||||||
|
procedure EraseCurrentStatement;
|
||||||
|
begin
|
||||||
|
{ make sure the nf_block_with_exit and nf_usercode_entry flags are safeguarded }
|
||||||
|
if Assigned(nextp) then
|
||||||
|
nextp.flags := nextp.flags + (hp.left.flags * [nf_block_with_exit, nf_usercode_entry]);
|
||||||
|
|
||||||
|
hp.right := nil;
|
||||||
|
hp.Free;
|
||||||
|
hp := nextp;
|
||||||
|
if not Assigned(lastp) then
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
if lastp = Self then
|
||||||
|
TBlockNode(lastp).left := nextp
|
||||||
|
else
|
||||||
|
TStatementNode(lastp).right := nextp;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
result := nil;
|
result := nil;
|
||||||
{ Warning: never replace a blocknode with another node type,
|
{ Warning: never replace a blocknode with another node type,
|
||||||
@ -717,9 +738,14 @@ implementation
|
|||||||
main program body, and those nodes should always be blocknodes
|
main program body, and those nodes should always be blocknodes
|
||||||
since that's what the compiler expects elsewhere. }
|
since that's what the compiler expects elsewhere. }
|
||||||
|
|
||||||
if assigned(left) and
|
lastp := Self;
|
||||||
not assigned(tstatementnode(left).right) then
|
hp := TStatementNode(left);
|
||||||
|
|
||||||
|
if Assigned(hp) then
|
||||||
begin
|
begin
|
||||||
|
if not assigned(tstatementnode(left).right) then
|
||||||
|
begin
|
||||||
|
{ Simplify single-statement blocks }
|
||||||
case tstatementnode(left).left.nodetype of
|
case tstatementnode(left).left.nodetype of
|
||||||
blockn:
|
blockn:
|
||||||
begin
|
begin
|
||||||
@ -728,7 +754,7 @@ implementation
|
|||||||
this block with that other block. }
|
this block with that other block. }
|
||||||
result:=tstatementnode(left).left;
|
result:=tstatementnode(left).left;
|
||||||
tstatementnode(left).left:=nil;
|
tstatementnode(left).left:=nil;
|
||||||
{ make sure the nf_block_with_exit flag is safeguarded }
|
{ make sure the nf_block_with_exit and nf_usercode_entry flags are safeguarded }
|
||||||
result.flags:=result.flags+(flags*[nf_block_with_exit,nf_usercode_entry]);
|
result.flags:=result.flags+(flags*[nf_block_with_exit,nf_usercode_entry]);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -743,7 +769,62 @@ implementation
|
|||||||
else
|
else
|
||||||
;
|
;
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
repeat
|
||||||
|
nextp := TStatementNode(hp.Right);
|
||||||
|
case hp.left.nodetype of
|
||||||
|
blockn:
|
||||||
|
if not Assigned(TBlockNode(hp.left).left) then
|
||||||
|
begin
|
||||||
|
{ Empty block - delete statement (and block within),
|
||||||
|
but only if the nf_usercode_entry flag is not set}
|
||||||
|
if hp.left.flags * [nf_usercode_entry] = [] then
|
||||||
|
begin
|
||||||
|
EraseCurrentStatement;
|
||||||
|
Continue;
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if (TStatementNode(TBlockNode(hp.left).left).left.nodetype = nothingn) and
|
||||||
|
not Assigned(TStatementNode(TBlockNode(hp.left).left).right) then
|
||||||
|
begin
|
||||||
|
{ Block contains only a statement->nothingn branch }
|
||||||
|
EraseCurrentStatement;
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Assigned(nextp) then
|
||||||
|
begin
|
||||||
|
{ If the last statement contains a block, Merge them
|
||||||
|
(statements within will already be simplified) }
|
||||||
|
|
||||||
|
{ Internal error is triggered if the calling block only
|
||||||
|
had one statement - code flow should have exited
|
||||||
|
earlier. }
|
||||||
|
nextp := TStatementNode(TBlockNode(hp.left).left);
|
||||||
|
TBlockNode(hp.left).left := nil;
|
||||||
|
EraseCurrentStatement;
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
nothingn:
|
||||||
|
{ Make sure it's not the only node left }
|
||||||
|
begin
|
||||||
|
{ Delete statement (and nothing node within) }
|
||||||
|
EraseCurrentStatement;
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end;
|
||||||
|
|
||||||
|
lastp := hp;
|
||||||
|
hp := nextp;
|
||||||
|
until not Assigned(hp);
|
||||||
|
end;
|
||||||
|
|
||||||
{$ifdef break_inlining}
|
{$ifdef break_inlining}
|
||||||
{ simple sequence of tempcreate, assign and return temp.? }
|
{ simple sequence of tempcreate, assign and return temp.? }
|
||||||
if GetStatements(left,a) and
|
if GetStatements(left,a) and
|
||||||
|
Loading…
Reference in New Issue
Block a user