* moved conversion of for into while loops in a separate pass, so node optimizations on the node tree can be

carried out without losing information from for loops

git-svn-id: trunk@43910 -
This commit is contained in:
florian 2020-01-11 16:08:45 +00:00
parent 3b39ec84e4
commit 2f2b378c03
3 changed files with 73 additions and 22 deletions

View File

@ -110,6 +110,7 @@ interface
constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce; constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
function pass_typecheck:tnode;override; function pass_typecheck:tnode;override;
function pass_1 : tnode;override; function pass_1 : tnode;override;
function makewhileloop : tnode;
function simplify(forinline : boolean) : tnode;override; function simplify(forinline : boolean) : tnode;override;
end; end;
tfornodeclass = class of tfornode; tfornodeclass = class of tfornode;
@ -280,6 +281,10 @@ interface
enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode; enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): tnode;
function create_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode; function create_for_in_loop(hloopvar, hloopbody, expr: tnode): tnode;
{ converts all for nodes in the tree into while nodes,
returns true if something was converted }
function ConvertForLoops(var n : tnode) : Boolean;
implementation implementation
uses uses
@ -993,6 +998,28 @@ implementation
current_filepos:=storefilepos; current_filepos:=storefilepos;
end; end;
function _ConvertForLoops(var n: tnode; arg: pointer): foreachnoderesult;
var
hp : tnode;
begin
Result:=fen_false;
if n.nodetype=forn then
begin
Result:=fen_true;
hp:=n;
n:=tfornode(n).makewhileloop;
do_firstpass(n);
hp.Free;
end;
end;
function ConvertForLoops(var n : tnode) : boolean;
begin
result:=foreachnodestatic(pm_postprocess,n,@_ConvertForLoops,nil);
end;
{**************************************************************************** {****************************************************************************
TLOOPNODE TLOOPNODE
*****************************************************************************} *****************************************************************************}
@ -1702,6 +1729,20 @@ implementation
function tfornode.pass_1 : tnode; function tfornode.pass_1 : tnode;
begin
result:=nil;
expectloc:=LOC_VOID;
firstpass(left);
firstpass(right);
firstpass(t1);
if assigned(t2) then
firstpass(t2);
end;
function tfornode.makewhileloop : tnode;
var var
ifblock,loopblock : tblocknode; ifblock,loopblock : tblocknode;
ifstatements,statements,loopstatements : tstatementnode; ifstatements,statements,loopstatements : tstatementnode;
@ -1716,6 +1757,7 @@ implementation
usetotemp : boolean; usetotemp : boolean;
{ if the lower bound is not constant, it must be store in a temp before calculating the upper bound } { if the lower bound is not constant, it must be store in a temp before calculating the upper bound }
usefromtemp : boolean; usefromtemp : boolean;
storefilepos: tfileposinfo;
procedure iterate_counter(var s : tstatementnode;fw : boolean); procedure iterate_counter(var s : tstatementnode;fw : boolean);
begin begin
@ -1737,21 +1779,10 @@ implementation
begin begin
result:=nil; result:=nil;
expectloc:=LOC_VOID;
fromtemp:=nil;
totemp:=nil; totemp:=nil;
fromtemp:=nil;
firstpass(left); storefilepos:=current_filepos;
firstpass(right); current_filepos:=fileinfo;
firstpass(t1);
if assigned(t2) then
begin
firstpass(t2);
if codegenerror then
exit;
end;
do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags) do_loopvar_at_end:=(lnf_dont_mind_loopvar_on_exit in loopflags)
{ if the loop is unrolled and there is a jump into the loop, { if the loop is unrolled and there is a jump into the loop,
then we can't do the trick with incrementing the loop var only at the then we can't do the trick with incrementing the loop var only at the
@ -1890,6 +1921,7 @@ implementation
addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(cond,left.getcopy,t1.getcopy),loopblock,false,true)); addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(cond,left.getcopy,t1.getcopy),loopblock,false,true));
addstatement(statements,ifblock); addstatement(statements,ifblock);
end; end;
current_filepos:=storefilepos;
end; end;

View File

@ -602,6 +602,10 @@ unit optdfa;
if the tree has been changed without updating dfa } if the tree has been changed without updating dfa }
procedure TDFABuilder.resetdfainfo(node : tnode); procedure TDFABuilder.resetdfainfo(node : tnode);
begin begin
nodemap.Free;
nodemap:=nil;
resultnode.Free;
resultnode:=nil;
foreachnodestatic(pm_postprocess,node,@ResetDFA,nil); foreachnodestatic(pm_postprocess,node,@ResetDFA,nil);
end; end;

View File

@ -1139,6 +1139,7 @@ implementation
procedure tcgprocinfo.OptimizeNodeTree; procedure tcgprocinfo.OptimizeNodeTree;
var var
i : integer; i : integer;
RedoDFA: Boolean;
{RedoDFA : boolean;} {RedoDFA : boolean;}
begin begin
{ do this before adding the entry code else the tail recursion recognition won't work, { do this before adding the entry code else the tail recursion recognition won't work,
@ -1158,6 +1159,24 @@ implementation
dfabuilder:=TDFABuilder.Create; dfabuilder:=TDFABuilder.Create;
dfabuilder.createdfainfo(code); dfabuilder.createdfainfo(code);
include(flags,pi_dfaavailable); include(flags,pi_dfaavailable);
RedoDFA:=false;
if (cs_opt_loopstrength in current_settings.optimizerswitches)
{ our induction variable strength reduction doesn't like
for loops with more than one entry }
and not(pi_has_label in flags) then
begin
RedoDFA:=OptimizeInductionVariables(code);
end;
RedoDFA:=ConvertForLoops(code) or RedoDFA;
if RedoDFA then
begin
dfabuilder.resetdfainfo(code);
dfabuilder.createdfainfo(code);
include(flags,pi_dfaavailable);
end;
{ when life info is available, we can give more sophisticated warning about uninitialized { when life info is available, we can give more sophisticated warning about uninitialized
variables ... variables ...
@ -1186,19 +1205,15 @@ implementation
tabstractnormalvarsym(tloadnode(dfabuilder.nodemap[i]).symtableentry).noregvarinitneeded:=true tabstractnormalvarsym(tloadnode(dfabuilder.nodemap[i]).symtableentry).noregvarinitneeded:=true
end; end;
end; end;
end
else
begin
ConvertForLoops(code);
end; end;
if (pi_dfaavailable in flags) and (cs_opt_dead_store_eliminate in current_settings.optimizerswitches) then if (pi_dfaavailable in flags) and (cs_opt_dead_store_eliminate in current_settings.optimizerswitches) then
do_optdeadstoreelim(code); do_optdeadstoreelim(code);
if (cs_opt_loopstrength in current_settings.optimizerswitches)
{ our induction variable strength reduction doesn't like
for loops with more than one entry }
and not(pi_has_label in flags) then
begin
{RedoDFA:=}OptimizeInductionVariables(code);
end;
if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
(procdef.proctypeoption in [potype_operator,potype_procedure,potype_function]) and (procdef.proctypeoption in [potype_operator,potype_procedure,potype_function]) and
(code.nodetype=blockn) and (tblocknode(code).statements=nil) then (code.nodetype=blockn) and (tblocknode(code).statements=nil) then