diff --git a/compiler/nflw.pas b/compiler/nflw.pas index 90902a4367..25fd4b98a0 100644 --- a/compiler/nflw.pas +++ b/compiler/nflw.pas @@ -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; diff --git a/compiler/optdfa.pas b/compiler/optdfa.pas index d25227104b..2f3b5709c8 100644 --- a/compiler/optdfa.pas +++ b/compiler/optdfa.pas @@ -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; diff --git a/compiler/psub.pas b/compiler/psub.pas index abb0e9e75d..ad2ec35b11 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -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