* 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;
function pass_typecheck:tnode;override;
function pass_1 : tnode;override;
function makewhileloop : tnode;
function simplify(forinline : boolean) : tnode;override;
end;
tfornodeclass = class of tfornode;
@ -280,6 +281,10 @@ interface
enumerator_get, enumerator_move: tprocdef; enumerator_current: tpropertysym): 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
uses
@ -993,6 +998,28 @@ implementation
current_filepos:=storefilepos;
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
*****************************************************************************}
@ -1702,6 +1729,20 @@ implementation
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
ifblock,loopblock : tblocknode;
ifstatements,statements,loopstatements : tstatementnode;
@ -1716,6 +1757,7 @@ implementation
usetotemp : boolean;
{ if the lower bound is not constant, it must be store in a temp before calculating the upper bound }
usefromtemp : boolean;
storefilepos: tfileposinfo;
procedure iterate_counter(var s : tstatementnode;fw : boolean);
begin
@ -1737,21 +1779,10 @@ implementation
begin
result:=nil;
expectloc:=LOC_VOID;
fromtemp:=nil;
totemp:=nil;
firstpass(left);
firstpass(right);
firstpass(t1);
if assigned(t2) then
begin
firstpass(t2);
if codegenerror then
exit;
end;
fromtemp:=nil;
storefilepos:=current_filepos;
current_filepos:=fileinfo;
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,
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(statements,ifblock);
end;
current_filepos:=storefilepos;
end;

View File

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

View File

@ -1139,6 +1139,7 @@ implementation
procedure tcgprocinfo.OptimizeNodeTree;
var
i : integer;
RedoDFA: Boolean;
{RedoDFA : boolean;}
begin
{ do this before adding the entry code else the tail recursion recognition won't work,
@ -1158,6 +1159,24 @@ implementation
dfabuilder:=TDFABuilder.Create;
dfabuilder.createdfainfo(code);
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
variables ...
@ -1186,19 +1205,15 @@ implementation
tabstractnormalvarsym(tloadnode(dfabuilder.nodemap[i]).symtableentry).noregvarinitneeded:=true
end;
end;
end
else
begin
ConvertForLoops(code);
end;
if (pi_dfaavailable in flags) and (cs_opt_dead_store_eliminate in current_settings.optimizerswitches) then
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
(procdef.proctypeoption in [potype_operator,potype_procedure,potype_function]) and
(code.nodetype=blockn) and (tblocknode(code).statements=nil) then