فهرست منبع

+ OptimizeForLoop: convert for-loops into zero-based backward for-loops if possible, for most architectures, this results in simpler code

git-svn-id: trunk@44287 -
florian 5 سال پیش
والد
کامیت
aca9727418
3فایلهای تغییر یافته به همراه90 افزوده شده و 4 حذف شده
  1. 10 2
      compiler/nflw.pas
  2. 71 2
      compiler/optloop.pas
  3. 9 0
      compiler/psub.pas

+ 10 - 2
compiler/nflw.pas

@@ -46,7 +46,10 @@ interface
          { Should the value of the loop variable on exit be correct. }
          lnf_dont_mind_loopvar_on_exit,
          { Loop simplify flag }
-         lnf_simplify_processing);
+         lnf_simplify_processing,
+         { set if in a for loop the counter is not used, so an easier exit check
+           can be carried out }
+         lnf_counter_not_used);
        tloopflags = set of tloopflag;
 
     const
@@ -1957,7 +1960,12 @@ implementation
           end
         else
           begin
-            addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(cond,left.getcopy,t1.getcopy),loopblock,false,true));
+            { is a simple comparision for equality sufficient? }
+            if do_loopvar_at_end and (lnf_backward in loopflags) and (lnf_counter_not_used in loopflags) then
+              addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(equaln,left.getcopy,
+                caddnode.create_internal(subn,t1.getcopy,cordconstnode.create(1,t1.resultdef,false))),loopblock,false,true))
+            else
+              addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create_internal(cond,left.getcopy,t1.getcopy),loopblock,false,true));
             addstatement(statements,ifblock);
           end;
         current_filepos:=storefilepos;

+ 71 - 2
compiler/optloop.pas

@@ -24,6 +24,7 @@ unit optloop;
 {$i fpcdefs.inc}
 
 { $define DEBUG_OPTSTRENGTH}
+{ $define DEBUG_OPTFORLOOP}
 
   interface
 
@@ -32,6 +33,7 @@ unit optloop;
 
     function unroll_loop(node : tnode) : tnode;
     function OptimizeInductionVariables(node : tnode) : boolean;
+    function OptimizeForLoop(var node : tnode) : boolean;
 
   implementation
 
@@ -523,7 +525,7 @@ unit optloop;
       end;
 
 
-    function iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
+    function OptimizeInductionVariables_iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
       var
         hp : tnode;
       begin
@@ -553,7 +555,74 @@ unit optloop;
     function OptimizeInductionVariables(node : tnode) : boolean;
       begin
         changedforloop:=false;
-        foreachnodestatic(pm_postprocess,node,@iterforloops,nil);
+        foreachnodestatic(pm_postprocess,node,@OptimizeInductionVariables_iterforloops,nil);
+        Result:=changedforloop;
+      end;
+
+
+    function OptimizeForLoop_iterforloops(var n: tnode; arg: pointer): foreachnoderesult;
+      var
+        hp : tnode;
+      begin
+        Result:=fen_false;
+        if (n.nodetype=forn) and
+          not(lnf_backward in tfornode(n).loopflags) and
+          (lnf_dont_mind_loopvar_on_exit in tfornode(n).loopflags) and
+          is_constintnode(tfornode(n).right) and
+          { this is not strictly necessary, but we do it for now }
+          is_constnode(tfornode(n).t1) and
+          (([cs_check_overflow,cs_check_range]*n.localswitches)=[]) and
+          (([cs_check_overflow,cs_check_range]*tfornode(n).left.localswitches)=[]) and
+          ((tfornode(n).left.nodetype=loadn) and (tloadnode(tfornode(n).left).symtableentry is tabstractvarsym) and
+            not(tabstractvarsym(tloadnode(tfornode(n).left).symtableentry).addr_taken) and
+            not(tabstractvarsym(tloadnode(tfornode(n).left).symtableentry).different_scope)) then
+          begin
+            { do we have DFA available? }
+            if pi_dfaavailable in current_procinfo.flags then
+              begin
+                CalcUseSum(tfornode(n).t2);
+                CalcDefSum(tfornode(n).t2);
+              end
+            else
+              Internalerror(2017122801);
+            if not(assigned(tfornode(n).left.optinfo)) then
+              exit;
+            if not(DFASetIn(tfornode(n).t2.optinfo^.usesum,tfornode(n).left.optinfo^.index)) and
+              not(DFASetIn(tfornode(n).t2.optinfo^.defsum,tfornode(n).left.optinfo^.index))  then
+              begin
+                { convert the loop from i:=a to b into i:=b-a+1 to 1 as this simplifies the
+                  abort condition }
+{$ifdef DEBUG_OPTFORLOOP}
+                writeln('**********************************************************************************');
+                writeln('Found loop for reverting: ');
+                printnode(n);
+                writeln('**********************************************************************************');
+{$endif DEBUG_OPTFORLOOP}
+                include(tfornode(n).loopflags,lnf_backward);
+                tfornode(n).right:=caddnode.create_internal(addn,caddnode.create_internal(subn,tfornode(n).t1,tfornode(n).right),
+                  cordconstnode.create(1,tfornode(n).left.resultdef,false));
+                tfornode(n).t1:=cordconstnode.create(1,tfornode(n).left.resultdef,false);
+                include(tfornode(n).loopflags,lnf_counter_not_used);
+                exclude(n.flags,nf_pass1_done);
+                do_firstpass(n);
+{$ifdef DEBUG_OPTFORLOOP}
+                writeln('Loop reverted: ');
+                printnode(n);
+                writeln('**********************************************************************************');
+{$endif DEBUG_OPTFORLOOP}
+                changedforloop:=true;
+              end;
+          end;
+      end;
+
+
+    function OptimizeForLoop(var node : tnode) : boolean;
+      begin
+        Result:=false;
+        if not(pi_dfaavailable in current_procinfo.flags) then
+          exit;
+        changedforloop:=false;
+        foreachnodestatic(pm_postprocess,node,@OptimizeForLoop_iterforloops,nil);
         Result:=changedforloop;
       end;
 

+ 9 - 0
compiler/psub.pas

@@ -1179,6 +1179,15 @@ implementation
                RedoDFA:=OptimizeInductionVariables(code);
              end;
 
+           if RedoDFA then
+             begin
+               dfabuilder.resetdfainfo(code);
+               dfabuilder.createdfainfo(code);
+               include(flags,pi_dfaavailable);
+             end;
+
+           RedoDFA:=OptimizeForLoop(code);
+
            RedoDFA:=ConvertForLoops(code) or RedoDFA;
 
            if RedoDFA then