Selaa lähdekoodia

+ transform for loop into equivalent while loop during pass 1 to simplify code generation

git-svn-id: trunk@34788 -
florian 8 vuotta sitten
vanhempi
commit
0610187878
2 muutettua tiedostoa jossa 195 lisäystä ja 471 poistoa
  1. 6 434
      compiler/ncgflw.pas
  2. 189 37
      compiler/nflw.pas

+ 6 - 434
compiler/ncgflw.pas

@@ -42,10 +42,7 @@ interface
        end;
 
        tcgfornode = class(tfornode)
-          usedregvars: tusedregvars;
-
           procedure pass_generate_code;override;
-          procedure sync_regvars(checkusedregvars: boolean);
        end;
 
        tcgexitnode = class(texitnode)
@@ -186,15 +183,15 @@ implementation
 
          hlcg.a_label(current_asmdata.CurrAsmList,lcont);
          if lnf_checknegate in loopflags then
-           begin
+          begin
              truelabel:=lbreak;
              falselabel:=lloop;
-           end
+          end
          else
-           begin
+          begin
              truelabel:=lloop;
              falselabel:=lbreak;
-           end;
+          end;
          secondpass(left);
 
          hlcg.maketojumpboollabels(current_asmdata.CurrAsmList,left,truelabel,falselabel);
@@ -379,435 +376,10 @@ implementation
                               SecondFor
 *****************************************************************************}
 
-    procedure tcgfornode.sync_regvars(checkusedregvars: boolean);
-      begin
-         if (cs_opt_regvar in current_settings.optimizerswitches) and
-            not(pi_has_label in current_procinfo.flags) then
-           begin
-             if checkusedregvars then
-               begin
-                 usedregvars.intregvars.init;
-                 usedregvars.addrregvars.init;
-                 usedregvars.fpuregvars.init;
-                 usedregvars.mmregvars.init;
-
-                 { We have to synchronise the loop variable and loop body. }
-                 { The loop end is not necessary, unless it's a register   }
-                 { variable. The start value also doesn't matter.          }
-
-                 { loop var }
-                 get_used_regvars(left,usedregvars);
-                 { loop body }
-                 get_used_regvars(t2,usedregvars);
-                 { end value can't be a regvar, but may be a temp in register }
-                 get_used_regvars(t1,usedregvars);
-
-                 gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
-               end
-             else
-               begin
-                 gen_sync_regvars(current_asmdata.CurrAsmList,usedregvars);
-                 usedregvars.intregvars.done;
-                 usedregvars.addrregvars.done;
-                 usedregvars.fpuregvars.done;
-                 usedregvars.mmregvars.done;
-               end;
-           end;
-      end;
-
-
     procedure tcgfornode.pass_generate_code;
-      var
-         l3,oldclabel,oldblabel : tasmlabel;
-         temptovalue : boolean;
-         hop : topcg;
-         hcond : topcmp;
-         opsize : tcgsize;
-         count_var_is_signed,do_loopvar_at_end : boolean;
-         cmp_const:Tconstexprint;
-         oldflowcontrol : tflowcontrol;
-         oldexecutionweight : longint;
       begin
-         location_reset(location,LOC_VOID,OS_NO);
-
-         oldclabel:=current_procinfo.CurrContinueLabel;
-         oldblabel:=current_procinfo.CurrBreakLabel;
-         current_asmdata.getjumplabel(current_procinfo.CurrContinueLabel);
-         current_asmdata.getjumplabel(current_procinfo.CurrBreakLabel);
-         current_asmdata.getjumplabel(l3);
-
-         { only calculate reference }
-         opsize := def_cgsize(left.resultdef);
-         count_var_is_signed:=is_signed(left.resultdef);
-
-         { first set the to value
-           because the count var can be in the expression ! }
-         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
-           end
-         }
-           and not(assigned(entrylabel));
-
-        secondpass(t1);
-        if t1.location.loc in [LOC_FLAGS,LOC_JUMP] then
-          hlcg.location_force_reg(current_asmdata.CurrAsmList,t1.location,t1.resultdef,t1.resultdef,false);
-         { calculate pointer value and check if changeable and if so }
-         { load into temporary variable                       }
-         if t1.nodetype<>ordconstn then
-           begin
-              do_loopvar_at_end:=false;
-              temptovalue:=true;
-           end
-         else
-           temptovalue:=false;
-
-         { load loopvar, prefer loopvar being a register variable }
-         oldexecutionweight:=cg.executionweight;
-         inc(cg.executionweight,8);
-         secondpass(left);
-         cg.executionweight:=oldexecutionweight;
-
-         { load from value }
-         secondpass(right);
-         if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
-           hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
-
-         hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
-         oldflowcontrol:=flowcontrol;
-         include(flowcontrol,fc_inflowcontrol);
-         exclude(flowcontrol,fc_unwind_loop);
-         { produce start assignment }
-         case left.location.loc of
-           LOC_REFERENCE,
-           LOC_CREFERENCE :
-             hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.reference);
-           LOC_REGISTER,
-           LOC_CREGISTER:
-             hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.register);
-           LOC_SUBSETREG,
-           LOC_CSUBSETREG :
-             hlcg.a_load_loc_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location,left.location.sreg);
-           else
-             internalerror(200501311);
-         end;
-
-         if lnf_backward in loopflags then
-           if count_var_is_signed then
-             hcond:=OC_LT
-           else
-             hcond:=OC_B
-         else
-           if count_var_is_signed then
-             hcond:=OC_GT
-           else
-             hcond:=OC_A;
-
-         sync_regvars(true);
-{$ifdef OLDREGVARS}
-         load_all_regvars(current_asmdata.CurrAsmList);
-{$endif OLDREGVARS}
-
-         if temptovalue then
-           begin
-             case t1.location.loc of
-               LOC_REGISTER,LOC_CREGISTER:
-                 hlcg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
-                   t1.location.register,left.location,current_procinfo.CurrBreakLabel);
-               LOC_REFERENCE,LOC_CREFERENCE:
-                 hlcg.a_cmp_ref_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
-                   t1.location.reference,left.location,current_procinfo.CurrBreakLabel);
-             else
-               InternalError(2013051601);
-             end;
-           end
-         else
-           begin
-             if lnf_testatbegin in loopflags then
-               begin
-                 hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
-                   tordconstnode(t1).value.svalue,
-                   left.location,current_procinfo.CurrBreakLabel);
-               end;
-           end;
-
-         {If the loopvar doesn't mind on exit, we avoid this ugly
-          dec instruction and do the loopvar inc/dec after the loop
-          body.}
-         if not do_loopvar_at_end then
-            begin
-              if lnf_backward in loopflags then
-                hop:=OP_ADD
-              else
-                hop:=OP_SUB;
-              hlcg.a_op_const_loc(current_asmdata.CurrAsmList,hop,left.resultdef,1,left.location);
-            end;
-
-         if assigned(entrylabel) then
-           hlcg.a_jmp_always(current_asmdata.CurrAsmList,tcglabelnode(entrylabel).getasmlabel);
-
-         { align loop target }
-         if not(cs_opt_size in current_settings.optimizerswitches) then
-            current_asmdata.CurrAsmList.concat(Tai_align.Create(current_settings.alignment.loopalign));
-         hlcg.a_label(current_asmdata.CurrAsmList,l3);
-
-         {If the loopvar doesn't mind on exit, we avoid the loopvar inc/dec
-          after the loop body instead of here.}
-         if not do_loopvar_at_end then
-            begin
-              { according to count direction DEC or INC... }
-              if lnf_backward in loopflags then
-                hop:=OP_SUB
-              else
-                hop:=OP_ADD;
-              hlcg.a_op_const_loc(current_asmdata.CurrAsmList,hop,left.resultdef,1,left.location);
-            end;
-
-         if assigned(t2) then
-           begin
-             { Calc register weight }
-             oldexecutionweight:=cg.executionweight;
-             cg.executionweight:=cg.executionweight*8;
-             secondpass(t2);
-             cg.executionweight:=oldexecutionweight;
-{$ifdef OLDREGVARS}
-             load_all_regvars(current_asmdata.CurrAsmList);
-{$endif OLDREGVARS}
-           end;
-
-         {If the loopvar doesn't mind on exit, we do the loopvar inc/dec
-          after the loop body instead of here.}
-         if do_loopvar_at_end then
-            begin
-              { according to count direction DEC or INC... }
-              if lnf_backward in loopflags then
-                hop:=OP_SUB
-              else
-                hop:=OP_ADD;
-              hlcg.a_op_const_loc(current_asmdata.CurrAsmList,hop,left.resultdef,1,left.location);
-            end;
-
-         hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel);
-
-         if do_loopvar_at_end then
-           if lnf_backward in loopflags then
-             if count_var_is_signed then
-               hcond:=OC_GTE
-             else
-               hcond:=OC_AE
-            else
-              if count_var_is_signed then
-                hcond:=OC_LTE
-              else
-                hcond:=OC_BE
-         else
-           if lnf_backward in loopflags then
-             if count_var_is_signed then
-               hcond:=OC_GT
-             else
-               hcond:=OC_A
-            else
-              if count_var_is_signed then
-                hcond:=OC_LT
-              else
-                hcond:=OC_B;
-{$ifdef OLDREGVARS}
-         load_all_regvars(current_asmdata.CurrAsmList);
-{$endif OLDREGVARS}
-
-         { produce comparison and the corresponding }
-         { jump                                     }
-         if temptovalue then
-           begin
-             case t1.location.loc of
-               LOC_REGISTER,LOC_CREGISTER:
-                 hlcg.a_cmp_reg_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,t1.location.register,
-                   left.location,l3);
-               LOC_REFERENCE,LOC_CREFERENCE:
-                 hlcg.a_cmp_ref_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,t1.location.reference,
-                   left.location,l3);
-             else
-               InternalError(2013051602);
-             end;
-           end
-         else
-           begin
-             cmp_const:=Tordconstnode(t1).value;
-             if do_loopvar_at_end then
-               begin
-                 {Watch out for wrap around 255 -> 0.}
-                 {Ugly: This code is way to long... Use tables?}
-                 case opsize of
-                   OS_8:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if byte(cmp_const.svalue)=low(byte) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=high(byte);
-                             end
-                         end
-                       else
-                         begin
-                           if byte(cmp_const.svalue)=high(byte) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=low(byte);
-                             end
-                         end
-                     end;
-                   OS_16:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if word(cmp_const.svalue)=high(word) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=low(word);
-                             end
-                         end
-                       else
-                         begin
-                           if word(cmp_const.svalue)=low(word) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=high(word);
-                             end
-                         end
-                     end;
-                   OS_32:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if cardinal(cmp_const.svalue)=high(cardinal) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=low(cardinal);
-                             end
-                         end
-                       else
-                         begin
-                           if cardinal(cmp_const.svalue)=low(cardinal) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=high(cardinal);
-                             end
-                         end
-                     end;
-                   OS_64:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if qword(cmp_const.uvalue)=high(qword) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=low(qword);
-                             end
-                         end
-                       else
-                         begin
-                           if qword(cmp_const.uvalue)=low(qword) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=high(qword);
-                             end
-                         end
-                     end;
-                   OS_S8:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if shortint(cmp_const.svalue)=low(shortint) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=high(shortint);
-                             end
-                         end
-                       else
-                         begin
-                           if shortint(cmp_const.svalue)=high(shortint) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=int64(low(shortint));
-                             end
-                         end
-                     end;
-                   OS_S16:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if integer(cmp_const.svalue)=high(smallint) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=int64(low(smallint));
-                             end
-                         end
-                       else
-                         begin
-                           if integer(cmp_const.svalue)=low(smallint) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=int64(high(smallint));
-                             end
-                         end
-                     end;
-                   OS_S32:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if longint(cmp_const.svalue)=high(longint) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=int64(low(longint));
-                             end
-                         end
-                       else
-                         begin
-                           if longint(cmp_const.svalue)=low(longint) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=int64(high(longint));
-                             end
-                         end
-                     end;
-                   OS_S64:
-                     begin
-                       if lnf_backward in loopflags then
-                         begin
-                           if int64(cmp_const.svalue)=high(int64) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=low(int64);
-                             end
-                         end
-                       else
-                         begin
-                           if int64(cmp_const.svalue)=low(int64) then
-                             begin
-                               hcond:=OC_NE;
-                               cmp_const:=high(int64);
-                             end
-                         end
-                     end;
-                   else
-                     internalerror(200201021);
-                 end;
-               end;
-
-             hlcg.a_cmp_const_loc_label(current_asmdata.CurrAsmList,left.resultdef,hcond,
-               tcgint(cmp_const.svalue),left.location,l3);
-           end;
-
-         { this is the break label: }
-         hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel);
-
-         sync_regvars(false);
-
-         current_procinfo.CurrContinueLabel:=oldclabel;
-         current_procinfo.CurrBreakLabel:=oldblabel;
-         { a break/continue in a while/repeat block can't be seen outside }
-         flowcontrol:=oldflowcontrol+(flowcontrol-[fc_break,fc_continue,fc_inflowcontrol]);
+        { for nodes are converted in pass_1 in a while loop }
+        internalerror(2015082501);
       end;
 
 

+ 189 - 37
compiler/nflw.pas

@@ -72,6 +72,9 @@ interface
        end;
 
        twhilerepeatnode = class(tloopnode)
+          { l: condition; r: body; tab: test at begin; cn: negate condition
+            x,y,true,false: while loop
+            x,y,false,true: repeat until loop }
           constructor create(l,r:Tnode;tab,cn:boolean);virtual;reintroduce;
           function pass_typecheck:tnode;override;
           function pass_1 : tnode;override;
@@ -101,7 +104,6 @@ interface
           loopiteration : tnode;
           loopvar_notid:cardinal;
           constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;reintroduce;
-          function wrap_to_value:tnode;
           function pass_typecheck:tnode;override;
           function pass_1 : tnode;override;
           function simplify(forinline : boolean) : tnode;override;
@@ -1475,29 +1477,6 @@ implementation
       end;
 
 
-    function tfornode.wrap_to_value:tnode;
-      var
-        statements: tstatementnode;
-        temp: ttempcreatenode;
-      begin
-        result:=internalstatements(statements);
-        temp:=ctempcreatenode.create(t1.resultdef,t1.resultdef.size,tt_persistent,true);
-        addstatement(statements,temp);
-        addstatement(statements,cassignmentnode.create(
-          ctemprefnode.create(temp),
-          t1));
-        { create a new for node, it is cheaper than cloning entire loop body }
-        addstatement(statements,cfornode.create(
-          left,right,ctemprefnode.create(temp),t2,lnf_backward in loopflags));
-        addstatement(statements,ctempdeletenode.create(temp));
-        { all child nodes are reused }
-        left:=nil;
-        right:=nil;
-        t1:=nil;
-        t2:=nil;
-      end;
-
-
     function tfornode.pass_typecheck:tnode;
       var
         res : tnode;
@@ -1545,23 +1524,196 @@ implementation
 
 
     function tfornode.pass_1 : tnode;
+      var
+        ifblock,whileblock,loopblock : tblocknode;
+        ifstatements,statements,loopstatements : tstatementnode;
+        fromtemp,totemp : ttempcreatenode;
+        do_loopvar_at_end : Boolean;
+        { if the lower and/or upper bound are variable, we need a surrounding if }
+        needsifblock : Boolean;
+        cond : tnodetype;
+        fromexpr : tnode;
+        toexpr : tnode;
+        { if the upper bound is not constant, it must be store in a temp initially }
+        usetotemp : boolean;
+        { if the lower bound is not constant, it must be store in a temp before calculating the upper bound }
+        usefromtemp : boolean;
+
+      procedure iterate_counter(var s : tstatementnode;fw : boolean);
+        begin
+          if fw then
+            addstatement(s,
+              cassignmentnode.create_internal(left.getcopy,cinlinenode.createintern(in_succ_x,false,left.getcopy)))
+          else
+            addstatement(s,
+              cassignmentnode.create_internal(left.getcopy,cinlinenode.createintern(in_pred_x,false,left.getcopy)));
+        end;
+
+      function iterate_counter_func(arg : tnode;fw : boolean) : tnode;
+        begin
+          if fw then
+            result:=cinlinenode.createintern(in_succ_x,false,arg)
+          else
+            result:=cinlinenode.createintern(in_pred_x,false,arg);
+        end;
+
       begin
-         result:=nil;
-         expectloc:=LOC_VOID;
+        result:=nil;
+        expectloc:=LOC_VOID;
+        fromtemp:=nil;
+        totemp:=nil;
 
-         firstpass(left);
-         firstpass(right);
-         firstpass(t1);
+        firstpass(left);
+        firstpass(right);
+        firstpass(t1);
 
-         if assigned(t2) then
-           firstpass(t2);
-         if codegenerror then
-           exit;
+        if assigned(t2) then
+          begin
+            firstpass(t2);
+            if codegenerror then
+              exit;
+          end;
+
+        { first set the to value
+          because the count var can be in the expression ! }
+        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
+          end
+        }
+          and not(assigned(entrylabel));
+
+         { calculate pointer value and check if changeable and if so
+           load into temporary variable                              }
+         if (right.nodetype<>ordconstn) or (t1.nodetype<>ordconstn) then
+           begin
+             do_loopvar_at_end:=false;
+             needsifblock:=true;
+           end
+         else
+           needsifblock:=false;
+
+        { convert the for loop into a while loop }
+        result:=internalstatements(statements);
+        ifblock:=internalstatements(ifstatements);
+        loopblock:=internalstatements(loopstatements);
+
+        usefromtemp:=(might_have_sideeffects(t1) and not(is_const(right))) or (node_complexity(right)>1);
+        usetotemp:=not(is_const(t1));
+
+        if needsifblock then
+          begin
+            { do not generate a temp. for the from node, if it is a const, it can be copied directly since
+              no side effect might change it }
+            if usefromtemp then
+              begin
+                fromtemp:=ctempcreatenode.create(right.resultdef,right.resultdef.size,tt_persistent,true);
+                { the if block might be optimized out, so we put the deletetempnode after the if-block, however,
+                  this causes a long life time of the fromtemp. If the final regsync is left away, the reg. allocator
+                  figures out the needed life time. As their are no loops involved between the uses of the fromtemp,
+                  this does no hurt }
+                fromtemp.includetempflag(ti_no_final_regsync);
+                addstatement(statements,fromtemp);
+                { while it would be beneficial to fold the initial reverse succ/pred into this assignment, this is
+                  not possible because it might wrap around and the if check later on goes wrong }
+                addstatement(statements,cassignmentnode.create_internal(ctemprefnode.create(fromtemp),right.getcopy));
+              end;
+
+            if usetotemp then
+              begin
+                totemp:=ctempcreatenode.create(t1.resultdef,t1.resultdef.size,tt_persistent,true);
+                addstatement(statements,totemp);
+                addstatement(statements,cassignmentnode.create_internal(ctemprefnode.create(totemp),t1.getcopy));
+              end;
+
+            if usefromtemp then
+              begin
+                addstatement(ifstatements,cassignmentnode.create_internal(left.getcopy,ctemprefnode.create(fromtemp)));
+                if not(do_loopvar_at_end) then
+                  iterate_counter(ifstatements,lnf_backward in loopflags);
+              end
+            else
+              begin
+                if not(do_loopvar_at_end) then
+                  addstatement(ifstatements,cassignmentnode.create_internal(left.getcopy,
+                    iterate_counter_func(right.getcopy,lnf_backward in loopflags)))
+                else
+                  addstatement(ifstatements,cassignmentnode.create_internal(left.getcopy,right.getcopy));
+              end;
+          end
+        else
+          begin
+            if not(do_loopvar_at_end) then
+              addstatement(ifstatements,cassignmentnode.create_internal(left.getcopy,
+                iterate_counter_func(right.getcopy,lnf_backward in loopflags)))
+            else
+              addstatement(ifstatements,cassignmentnode.create_internal(left.getcopy,right.getcopy));
+          end;
+
+        if assigned(entrylabel) then
+          addstatement(ifstatements,cgotonode.create(tlabelnode(entrylabel).labsym));
+
+        if not(do_loopvar_at_end) then
+          iterate_counter(loopstatements,not(lnf_backward in loopflags));
+
+        { avoid copying t2, it is used only once and it might be big }
+        addstatement(loopstatements,t2);
+        t2:=nil;
+
+        if do_loopvar_at_end then
+         iterate_counter(loopstatements,not(lnf_backward in loopflags));
+
+        if do_loopvar_at_end then
+          begin
+            if lnf_backward in loopflags then
+              cond:=ltn
+            else
+              cond:=gtn;
+          end
+        else
+          begin
+            if lnf_backward in loopflags then
+              cond:=lten
+            else
+              cond:=gten;
+          end;
+
+        if needsifblock then
+          begin
+            if usetotemp then
+              toexpr:=ctemprefnode.create(totemp)
+            else
+              toexpr:=t1.getcopy;
+
+            addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create(cond,left.getcopy,toexpr),loopblock,false,true));
 
-         { 'to' value must be evaluated once before loop, so its possible modifications
-           inside loop body do not affect the number of iterations (see webtbs/tw8883). }
-         if not (t1.nodetype in [ordconstn,temprefn]) then
-           result:=wrap_to_value;
+            if usefromtemp then
+              fromexpr:=ctemprefnode.create(fromtemp)
+            else
+              fromexpr:=right.getcopy;
+
+            if usetotemp then
+              toexpr:=ctemprefnode.create(totemp)
+            else
+              toexpr:=t1.getcopy;
+
+            if lnf_backward in loopflags then
+              addstatement(statements,cifnode.create(caddnode.create(gten,
+                fromexpr,toexpr),ifblock,nil))
+            else
+              addstatement(statements,cifnode.create(caddnode.create(lten,
+                fromexpr,toexpr),ifblock,nil));
+
+            if usetotemp then
+              addstatement(statements,ctempdeletenode.create(totemp));
+            if usefromtemp then
+              addstatement(statements,ctempdeletenode.create(fromtemp));
+          end
+        else
+          begin
+            addstatement(ifstatements,cwhilerepeatnode.create(caddnode.create(cond,left.getcopy,t1.getcopy),loopblock,false,true));
+            addstatement(statements,ifblock);
+          end;
       end;