Explorar el Código

* Fixed the strength reduction optimization for loops containing 'continue'.
The compiler now cycles properly with -O3 -OoSTRENGTH.

Yuriy Sydorov hace 3 años
padre
commit
bd4c206472
Se han modificado 1 ficheros con 72 adiciones y 17 borrados
  1. 72 17
      compiler/optloop.pas

+ 72 - 17
compiler/optloop.pas

@@ -256,7 +256,17 @@ unit optloop;
       templist : tfplist;
       inductionexprs : tfplist;
       changedforloop,
-      containsnestedforloop : boolean;
+      containsnestedforloop,
+      docalcatend: boolean;
+
+    function checkcontinue(var n:tnode; arg: pointer): foreachnoderesult;
+      begin
+        if n.nodetype=continuen then
+          result:=fen_norecurse_true
+        else
+          result:=fen_false;
+      end;
+
 
     function is_loop_invariant(loop : tnode;expr : tnode) : boolean;
       begin
@@ -330,9 +340,20 @@ unit optloop;
             end;
         end;
 
+
+      procedure CheckCalcAtEnd;
+        begin
+          if not assigned(initcode) then
+            docalcatend:=not(foreachnodestatic(tfornode(arg).t2,@checkcontinue,nil)) and
+              not(assigned(tfornode(arg).entrylabel));
+        end;
+
+
       var
         tempnode : ttempcreatenode;
         dummy : longint;
+        nn : tnode;
+        nt : tnodetype;
       begin
         result:=fen_false;
         case n.nodetype of
@@ -346,9 +367,7 @@ unit optloop;
                 { plain read of the loop variable? }
                 not(nf_write in taddnode(n).right.flags) and
                 not(nf_modify in taddnode(n).right.flags) and
-                is_loop_invariant(tfornode(arg),taddnode(n).left) and
-                { for now, we can handle only constant lower borders }
-                is_constnode(tfornode(arg).right) then
+                is_loop_invariant(tfornode(arg),taddnode(n).left) then
                 taddnode(n).swapleftright;
 
               if (taddnode(n).left.nodetype=loadn) and
@@ -356,14 +375,19 @@ unit optloop;
                 { plain read of the loop variable? }
                 not(nf_write in taddnode(n).left.flags) and
                 not(nf_modify in taddnode(n).left.flags) and
-                is_loop_invariant(tfornode(arg),taddnode(n).right) and
-                { for now, we can handle only constant lower borders }
-                is_constnode(tfornode(arg).right) then
+                is_loop_invariant(tfornode(arg),taddnode(n).right) then
                 begin
                   changedforloop:=true;
                   { did we use the same expression before already? }
                   if not(findpreviousstrengthreduction) then
                     begin
+{$ifdef DEBUG_OPTSTRENGTH}
+                      writeln('**********************************************************************************');
+                      writeln(parser_current_file, ': Found expression for strength reduction (MUL): ');
+                      printnode(n);
+                      writeln('**********************************************************************************');
+{$endif DEBUG_OPTSTRENGTH}
+                      CheckCalcAtEnd;
                       tempnode:=ctempcreatenode.create(n.resultdef,n.resultdef.size,tt_persistent,
                         tstoreddef(n.resultdef).is_intregable or tstoreddef(n.resultdef).is_fpuregable);
 
@@ -381,11 +405,23 @@ unit optloop;
                           ccallparanode.create(ctemprefnode.create(tempnode),ccallparanode.create(taddnode(n).right.getcopy,nil))));
 
                       addstatement(initcodestatements,tempnode);
+                      nn:=tfornode(arg).right.getcopy;
+                      { If the calculation is not performed at the end
+                        it is needed to adjust the starting value }
+                      if not docalcatend then
+                        begin
+                          if lnf_backward in tfornode(arg).loopflags then
+                            nt:=addn
+                          else
+                            nt:=subn;
+                          nn:=caddnode.create_internal(nt,nn,
+                             cordconstnode.create(1,nn.resultdef,false));
+                        end;
                       addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
-                        caddnode.create(muln,tfornode(arg).right.getcopy,
-                          taddnode(n).right.getcopy)
-                        )
-                      );
+                          caddnode.create(muln,nn,
+                            taddnode(n).right.getcopy)
+                          )
+                        );
 
                       { finally replace the node by a temp. ref }
                       n:=ctemprefnode.create(tempnode);
@@ -426,10 +462,11 @@ unit optloop;
                     begin
 {$ifdef DEBUG_OPTSTRENGTH}
                       writeln('**********************************************************************************');
-                      writeln('Found expression for strength reduction: ');
+                      writeln(parser_current_file,': Found expression for strength reduction (VEC): ');
                       printnode(n);
                       writeln('**********************************************************************************');
 {$endif DEBUG_OPTSTRENGTH}
+                      CheckCalcAtEnd;
                       tempnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
 
                       templist.Add(tempnode);
@@ -448,11 +485,22 @@ unit optloop;
                           cordconstnode.create(tcgvecnode(n).get_mul_size,sizeuinttype,false),nil))));
 
                       addstatement(initcodestatements,tempnode);
-                      addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),
-                        caddrnode.create(
+                      nn:=caddrnode.create(
                           cvecnode.create(tvecnode(n).left.getcopy,tfornode(arg).right.getcopy)
-                        )
-                      ));
+                        );
+                      { If the calculation is not performed at the end
+                        it is needed to adjust the starting value }
+                      if not docalcatend then
+                        begin
+                          if lnf_backward in tfornode(arg).loopflags then
+                            nt:=addn
+                          else
+                            nt:=subn;
+                          nn:=caddnode.create_internal(nt,
+                             ctypeconvnode.create_internal(nn,voidpointertype),
+                             cordconstnode.create(tcgvecnode(n).get_mul_size,sizeuinttype,false));
+                        end;
+                      addstatement(initcodestatements,cassignmentnode.create(ctemprefnode.create(tempnode),nn));
 
                       { finally replace the node by a temp. ref }
                       n:=ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),n.resultdef);
@@ -489,6 +537,7 @@ unit optloop;
         initcodestatements:=nil;
         calccodestatements:=nil;
         deletecodestatements:=nil;
+        docalcatend:=false;
         { find all expressions being candidates for strength reduction
           and replace them }
         foreachnodestatic(pm_postprocess,node,@dostrengthreductiontest,node);
@@ -511,8 +560,11 @@ unit optloop;
             node:=fornode;
 
             loopcode:=internalstatements(loopcodestatements);
+            if not docalcatend then
+              addstatement(loopcodestatements,calccode);
             addstatement(loopcodestatements,tfornode(node).t2);
-            addstatement(loopcodestatements,calccode);
+            if docalcatend then
+              addstatement(loopcodestatements,calccode);
             tfornode(node).t2:=loopcode;
             do_firstpass(node);
 
@@ -556,6 +608,9 @@ unit optloop;
 
     function OptimizeInductionVariables(node : tnode) : boolean;
       begin
+        Result:=false;
+        if not(pi_dfaavailable in current_procinfo.flags) then
+          exit;
         changedforloop:=false;
         foreachnodestatic(pm_postprocess,node,@OptimizeInductionVariables_iterforloops,nil);
         Result:=changedforloop;