Browse Source

+ first basically working (not all node types yet) dfa implementation determining life information

git-svn-id: trunk@7294 -
florian 18 years ago
parent
commit
45cda67f3f
6 changed files with 318 additions and 91 deletions
  1. 18 0
      compiler/defcmp.pas
  2. 3 2
      compiler/globtype.pas
  3. 78 16
      compiler/optbase.pas
  4. 147 49
      compiler/optdfa.pas
  5. 65 23
      compiler/optutils.pas
  6. 7 1
      compiler/psub.pas

+ 18 - 0
compiler/defcmp.pas

@@ -914,6 +914,24 @@ implementation
                          eq:=te_convert_l1;
                          eq:=te_convert_l1;
                        end;
                        end;
                    end;
                    end;
+{
+                 enumdef :
+                   begin
+                     { allow explicit typecasts from enums to pointer.
+		       Support for delphi compatibility
+                     }
+                     if (eq=te_incompatible) and
+                        (((cdo_explicit in cdoptions) and
+                          (m_delphi in current_settings.modeswitches)
+ 		         ) or
+			 (cdo_internal in cdoptions)
+			) then
+                       begin
+                         doconv:=tc_int_2_int;
+                         eq:=te_convert_l1;
+                       end;
+                   end;
+}
                  arraydef :
                  arraydef :
                    begin
                    begin
                      { string constant (which can be part of array constructor)
                      { string constant (which can be part of array constructor)

+ 3 - 2
compiler/globtype.pas

@@ -153,7 +153,8 @@ interface
        toptimizerswitch = (cs_opt_none,
        toptimizerswitch = (cs_opt_none,
          cs_opt_level1,cs_opt_level2,cs_opt_level3,
          cs_opt_level1,cs_opt_level2,cs_opt_level3,
          cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
          cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
-         cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse
+         cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse,
+         cs_opt_nodedfa
        );
        );
        toptimizerswitches = set of toptimizerswitch;
        toptimizerswitches = set of toptimizerswitch;
 
 
@@ -161,7 +162,7 @@ interface
        OptimizerSwitchStr : array[toptimizerswitch] of string[10] = ('',
        OptimizerSwitchStr : array[toptimizerswitch] of string[10] = ('',
          'LEVEL1','LEVEL2','LEVEL3',
          'LEVEL1','LEVEL2','LEVEL3',
          'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
          'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
-         'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE'
+         'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE','DFA'
        );
        );
 
 
        { switches being applied to all CPUs at the given level }
        { switches being applied to all CPUs at the given level }

+ 78 - 16
compiler/optbase.pas

@@ -32,6 +32,7 @@ unit optbase;
       { this should maybe replaced by a spare set,
       { this should maybe replaced by a spare set,
         using a dyn. array makes assignments cheap }
         using a dyn. array makes assignments cheap }
       tdfaset = array of byte;
       tdfaset = array of byte;
+      PDFASet = ^TDFASet;
 
 
       toptinfo = record
       toptinfo = record
         { index of the current node inside the dfa sets, aword(-1) if no entry }
         { index of the current node inside the dfa sets, aword(-1) if no entry }
@@ -44,31 +45,69 @@ unit optbase;
       poptinfo = ^toptinfo;
       poptinfo = ^toptinfo;
 
 
     { basic set operations for dfa sets }
     { basic set operations for dfa sets }
-    procedure TDFASetInclude(var s : tdfaset;e : integer);
-    procedure TDFASetExclude(var s : tdfaset;e : integer);
-    function TDFASetIn(const s : tdfaset;e : integer) : boolean;
-    procedure TDFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
-    procedure TDFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
-    procedure TDFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
+
+    { add e to s }
+    procedure DFASetInclude(var s : tdfaset;e : integer);
+
+    { add s to d }
+    procedure DFASetIncludeSet(var d : tdfaset;const s : tdfaset);
+
+    { remove e from s }
+    procedure DFASetExclude(var s : tdfaset;e : integer);
+
+    { test if s contains e }
+    function DFASetIn(const s : tdfaset;e : integer) : boolean;
+
+    { d:=s1+s2; }
+    procedure DFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
+
+    { d:=s1*s2; }
+    procedure DFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
+
+    { d:=s1-s2; }
+    procedure DFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
+
+    { s1<>s2; }
     function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
     function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
 
 
+    { output DFA set }
+    procedure PrintDFASet(var f : text;s : TDFASet);
+
   implementation
   implementation
 
 
     uses
     uses
       cutils;
       cutils;
 
 
-    procedure TDFASetInclude(var s : tdfaset;e : integer);
+    procedure DFASetInclude(var s : tdfaset;e : integer);
       var
       var
+        i,
+        oldhigh,
         e8 : Integer;
         e8 : Integer;
       begin
       begin
         e8:=e div 8;
         e8:=e div 8;
         if e8>high(s) then
         if e8>high(s) then
-          SetLength(s,e8+1);
+          begin
+            oldhigh:=high(s);
+            SetLength(s,e8+1);
+            for i:=oldhigh+1 to high(s) do
+              s[i]:=0;
+          end;
         s[e8]:=s[e8] or (1 shl (e mod 8));
         s[e8]:=s[e8] or (1 shl (e mod 8));
       end;
       end;
 
 
 
 
-    procedure TDFASetExclude(var s : tdfaset;e : integer);
+    procedure DFASetIncludeSet(var d : tdfaset;const s : tdfaset);
+      var
+        i : integer;
+      begin
+        if length(s)>length(d) then
+          SetLength(d,length(s));
+        for i:=0 to high(s) do
+          d[i]:=d[i] or s[i];
+      end;
+
+
+    procedure DFASetExclude(var s : tdfaset;e : integer);
       var
       var
         e8 : Integer;
         e8 : Integer;
       begin
       begin
@@ -79,7 +118,7 @@ unit optbase;
       end;
       end;
 
 
 
 
-    function TDFASetIn(const s : tdfaset;e : integer) : boolean;
+    function DFASetIn(const s : tdfaset;e : integer) : boolean;
       var
       var
         e8 : Integer;
         e8 : Integer;
       begin
       begin
@@ -91,7 +130,7 @@ unit optbase;
       end;
       end;
 
 
 
 
-    procedure TDFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
+    procedure DFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
       var
       var
         i : integer;
         i : integer;
       begin
       begin
@@ -103,7 +142,7 @@ unit optbase;
       end;
       end;
 
 
 
 
-    procedure TDFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
+    procedure DFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
       var
       var
         i : integer;
         i : integer;
       begin
       begin
@@ -113,13 +152,16 @@ unit optbase;
       end;
       end;
 
 
 
 
-    procedure TDFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
+    procedure DFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
       var
       var
         i : integer;
         i : integer;
       begin
       begin
-        SetLength(d,min(Length(s1),Length(s2)));
-        for i:=0 to min(high(s1),high(s2)) do
-          d[i]:=s1[i] and not(s2[i]);
+        SetLength(d,length(s1));
+        for i:=0 to high(d) do
+          if i>high(s2) then
+            d[i]:=s1[i]
+          else
+            d[i]:=s1[i] and not(s2[i]);
       end;
       end;
 
 
 
 
@@ -152,4 +194,24 @@ unit optbase;
         result:=false;
         result:=false;
       end;
       end;
 
 
+
+    procedure PrintDFASet(var f : text;s : TDFASet);
+      var
+        i : integer;
+        first : boolean;
+      begin
+        first:=true;
+        for i:=0 to Length(s)*8 do
+          begin
+            if DFASetIn(s,i) then
+              begin
+                if not(first) then
+                  write(f,',');
+                write(f,i);
+                first:=false;
+              end;
+          end;
+      end;
+
+
 end.
 end.

+ 147 - 49
compiler/optdfa.pas

@@ -19,6 +19,10 @@
 
 
  ****************************************************************************
  ****************************************************************************
 }
 }
+
+{ $define DEBUG_DFA}
+
+{ this unit implements routines to perform dfa }
 unit optdfa;
 unit optdfa;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
@@ -32,18 +36,21 @@ unit optdfa;
       if the tree has been changed without updating dfa }
       if the tree has been changed without updating dfa }
     procedure resetdfainfo(node : tnode);
     procedure resetdfainfo(node : tnode);
 
 
-    procedure createoptinfo(node : tnode);
+    procedure createdfainfo(node : tnode);
 
 
   implementation
   implementation
 
 
     uses
     uses
       globtype,globals,
       globtype,globals,
+      verbose,
       cpuinfo,
       cpuinfo,
+      symdef,
       nutils,
       nutils,
       nbas,nflw,ncon,ninl,ncal,
       nbas,nflw,ncon,ninl,ncal,
-      optutils;
+      optbase,optutils;
 
 
 
 
+    (*
     function initnodes(var n:tnode; arg: pointer) : foreachnoderesult;
     function initnodes(var n:tnode; arg: pointer) : foreachnoderesult;
       begin
       begin
         { node worth to add? }
         { node worth to add? }
@@ -56,7 +63,7 @@ unit optdfa;
         else
         else
           result:=fen_norecurse_false;
           result:=fen_norecurse_false;
       end;
       end;
-
+    *)
 
 
     {
     {
       x:=f;         read: [f]
       x:=f;         read: [f]
@@ -85,61 +92,104 @@ unit optdfa;
 
 
     type
     type
       tdfainfo = record
       tdfainfo = record
-        use : TDFASet;
-        def : TDFASet;
+        use : PDFASet;
+        def : PDFASet;
         map : TIndexedNodeSet
         map : TIndexedNodeSet
       end;
       end;
+      pdfainfo = ^tdfainfo;
 
 
-    procedure AddDefUse(s : TDFASet;m : ;n : tnode);
+    function AddDefUse(var n: tnode; arg: pointer): foreachnoderesult;
       begin
       begin
-        while true do
-          begin
-            case n.nodetype of
-              typeconvn:
-                n:=ttypeconvnode(n).left;
-              loadn:
-                begin
-                  m.Add(n);
-                  TDFASetInclude(s,n.optinfo^.index);
-                end;
+        case n.nodetype of
+          loadn:
+            begin
+              pdfainfo(arg)^.map.Add(n);
+              if nf_write in n.flags then
+                DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
               else
               else
-                internalerror(2007050601);
+                DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
+              {
+              write('Use Set: ');
+              PrintDFASet(output,pdfainfo(arg)^.use^);
+              write(' Def Set: ');
+              PrintDFASet(output,pdfainfo(arg)^.def^);
+              writeln;
+              }
             end;
             end;
-          end;
+        end;
+        result:=fen_false;
       end;
       end;
 
 
 
 
-    procedure CreateLifeInfo(node : tnode);
+    procedure CreateLifeInfo(node : tnode;map : TIndexedNodeSet);
 
 
       var
       var
         changed : boolean;
         changed : boolean;
 
 
       procedure CreateInfo(node : tnode);
       procedure CreateInfo(node : tnode);
 
 
+        { update life entry of a node with l, set changed if this changes
+          life info for the node
+        }
         procedure updatelifeinfo(n : tnode;l : TDFASet);
         procedure updatelifeinfo(n : tnode;l : TDFASet);
+          var
+            b : boolean;
           begin
           begin
-            changed:=changed or DFASetNotEqual(l,n.life);
-            node.life:=l;
+            b:=DFASetNotEqual(l,n.optinfo^.life);
+            {
+            if b then
+              begin
+                printnode(output,n);
+                printdfaset(output,l);
+                writeln;
+                printdfaset(output,n.optinfo^.life);
+                writeln;
+              end;
+            }
+            changed:=changed or b;
+            node.optinfo^.life:=l;
           end;
           end;
 
 
         procedure calclife(n : tnode);
         procedure calclife(n : tnode);
           var
           var
-            l : TDFANode;
+            l : TDFASet;
           begin
           begin
-            if assigned(successor) then
+            n.allocoptinfo;
+            if assigned(n.successor) then
               begin
               begin
-                DFASetDiff(l,successor.optinfo^.life,n.optinfo^.def);
+                {
+                write('Successor Life: ');
+                printdfaset(output,n.successor.optinfo^.life);
+                writeln;
+                write('Def.');
+                printdfaset(output,n.optinfo^.def);
+                writeln;
+                }
+                { ensure we can access optinfo }
+                DFASetDiff(l,n.successor.optinfo^.life,n.optinfo^.def);
+                {
+                printdfaset(output,l);
+                writeln;
+                }
                 DFASetIncludeSet(l,n.optinfo^.use);
                 DFASetIncludeSet(l,n.optinfo^.use);
-                updatelifeinfo(n,l);
+                DFASetIncludeSet(l,n.optinfo^.life);
               end
               end
-          end
+            else
+              l:=n.optinfo^.use;
+            updatelifeinfo(n,l);
+          end;
 
 
         var
         var
           dfainfo : tdfainfo;
           dfainfo : tdfainfo;
+          l : TDFASet;
+
         begin
         begin
+          if node=nil then
+            exit;
+
           if nf_processing in node.flags then
           if nf_processing in node.flags then
             exit;
             exit;
-          include(node,nf_processing);
+          include(node.flags,nf_processing);
 
 
           if assigned(node.successor) then
           if assigned(node.successor) then
             CreateInfo(node.successor);
             CreateInfo(node.successor);
@@ -147,20 +197,36 @@ unit optdfa;
           { life:=succesorlive-definition+use }
           { life:=succesorlive-definition+use }
 
 
           case node.nodetype of
           case node.nodetype of
-            whilen:
+            whilerepeatn:
               begin
               begin
-                { first, do things as usual, get life information from the successor }
-
-                { life:=succesorlive-definition+use }
-
-                { now iterate through the loop }
-                CreateInfo(twhilenode(node).left);
-
-                { update while node }
-                { life:=life+left.life }
-
-                { ... and a second iteration for fast convergence }
-                CreateInfo(twhilenode(node).left);
+                calclife(node);
+                if lnf_testatbegin in twhilerepeatnode(node).loopflags then
+                  begin
+                    { first, do things as usual, get life information from the successor }
+                    node.allocoptinfo;
+                    if not(assigned(node.optinfo^.def)) and
+                       not(assigned(node.optinfo^.use)) then
+                      begin
+                        dfainfo.use:[email protected]^.use;
+                        dfainfo.def:[email protected]^.def;
+                        dfainfo.map:=map;
+                        foreachnodestatic(pm_postprocess,twhilerepeatnode(node).left,@AddDefUse,@dfainfo);
+                      end;
+                    calclife(node);
+
+                    { now iterate through the loop }
+                    CreateInfo(twhilerepeatnode(node).right);
+
+                    { update while node }
+                    { life:=life+use+right.life }
+                    l:=node.optinfo^.life;
+                    DFASetIncludeSet(l,node.optinfo^.use);
+                    DFASetIncludeSet(l,twhilerepeatnode(node).right.optinfo^.life);
+                    UpdateLifeInfo(node,l);
+
+                    { ... and a second iteration for fast convergence }
+                    CreateInfo(twhilerepeatnode(node).right);
+                  end;
               end;
               end;
             statementn:
             statementn:
               begin
               begin
@@ -168,30 +234,58 @@ unit optdfa;
                 case tstatementnode(node).statement.nodetype of
                 case tstatementnode(node).statement.nodetype of
                   assignn:
                   assignn:
                     begin
                     begin
-                      tstatementnode(node).allocoptinfo;
-                      if not(assigned(tstatementnode(node).optinfo^.def)) or
-                        not(assigned(tstatementnode(node).optinfo^.use)) then
+                      node.allocoptinfo;
+                      if not(assigned(node.optinfo^.def)) and
+                        not(assigned(node.optinfo^.use)) then
                         begin
                         begin
-                          dfainfo.use:=tstatementnode(node).optinfo^.use;
-                          dfainfo.def:=tstatementnode(node).optinfo^.def;
-                          Foreach
+                          dfainfo.use:[email protected]^.use;
+                          dfainfo.def:[email protected]^.def;
+                          dfainfo.map:=map;
+                          foreachnodestatic(pm_postprocess,tstatementnode(node).left,@AddDefUse,@dfainfo);
                         end;
                         end;
                       calclife(node);
                       calclife(node);
                     end;
                     end;
+                  else
+                    begin
+                      { nested statement }
+                      CreateInfo(tstatementnode(node).statement);
+                      { inherit info }
+                      node.allocoptinfo;
+                      node.optinfo^.life:=tstatementnode(node).statement.optinfo^.life;
+                    end;
                 end;
                 end;
               end;
               end;
+            blockn:
+              begin
+                CreateInfo(tblocknode(node).statements);
+                node.allocoptinfo;
+                if assigned(tblocknode(node).statements) then
+                  node.optinfo^.life:=tblocknode(node).statements.optinfo^.life;
+              end;
             else
             else
               internalerror(2007050502);
               internalerror(2007050502);
           end;
           end;
 
 
-          exclude(node,nf_processing);
+          exclude(node.flags,nf_processing);
         end;
         end;
 
 
+      var
+        runs : integer;
+
       begin
       begin
+        runs:=0;
         repeat
         repeat
+          inc(runs);
           changed:=false;
           changed:=false;
           CreateInfo(node);
           CreateInfo(node);
+{$ifdef DEBUG_DFA}
+          PrintIndexedNodeSet(output,map);
+          PrintDFAInfo(output,node);
+{$endif DEBUG_DFA}
         until not(changed);
         until not(changed);
+{$ifdef DEBUG_DFA}
+        writeln('DFA solver iterations: ',runs);
+{$endif DEBUG_DFA}
       end;
       end;
 
 
 
 
@@ -203,13 +297,17 @@ unit optdfa;
 
 
 
 
     procedure createdfainfo(node : tnode);
     procedure createdfainfo(node : tnode);
+      var
+        map : TIndexedNodeSet;
       begin
       begin
+        map:=TIndexedNodeSet.Create;
         { add controll flow information }
         { add controll flow information }
         SetNodeSucessors(node);
         SetNodeSucessors(node);
 
 
         { now, collect life information }
         { now, collect life information }
-        CreateLifeInfo(node);
-      end;
+        CreateLifeInfo(node,map);
 
 
+        map.free;
+      end;
 
 
 end.
 end.

+ 65 - 23
compiler/optutils.pas

@@ -26,6 +26,7 @@ unit optutils;
   interface
   interface
 
 
     uses
     uses
+      cclasses,
       node;
       node;
 
 
     type
     type
@@ -37,16 +38,16 @@ unit optutils;
         function Remove(node : tnode) : boolean;
         function Remove(node : tnode) : boolean;
       end;
       end;
 
 
-      TNodeMap = class(TNodeSet)
-        function (node : tnode) : boolean;
-      end;
-
     procedure SetNodeSucessors(p : tnode);
     procedure SetNodeSucessors(p : tnode);
+    procedure PrintDFAInfo(var f : text;p : tnode);
+    procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
 
 
   implementation
   implementation
 
 
     uses
     uses
-      nbas,nflw;
+      verbose,
+      optbase,
+      nbas,nflw,nutils;
 
 
     function TIndexedNodeSet.Add(node : tnode) : boolean;
     function TIndexedNodeSet.Add(node : tnode) : boolean;
       var
       var
@@ -62,7 +63,7 @@ unit optutils;
           end
           end
         else
         else
           begin
           begin
-            i:=Add(node);
+            i:=inherited Add(node);
             node.optinfo^.index:=i;
             node.optinfo^.index:=i;
             result:=true;
             result:=true;
           end
           end
@@ -73,10 +74,10 @@ unit optutils;
       var
       var
         i : longint;
         i : longint;
       begin
       begin
-        for i:=0 to FCount-1 do
-          if tnode(FList^[i]).isequal(node) then
+        for i:=0 to Count-1 do
+          if tnode(List^[i]).isequal(node) then
             begin
             begin
-              result:=tnode(FList^[i]);
+              result:=tnode(List^[i]);
               exit;
               exit;
             end;
             end;
         result:=nil;
         result:=nil;
@@ -91,23 +92,47 @@ unit optutils;
         p:=Includes(node);
         p:=Includes(node);
         if assigned(p) then
         if assigned(p) then
           begin
           begin
-            if Remove(p)<>-1 then
+            if inherited Remove(p)<>-1 then
               result:=true;
               result:=true;
           end;
           end;
       end;
       end;
 
 
 
 
-    procedure PrintIndexedNodeSet(f : text;s : TIndexedNodeSet);
+    procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
+      var
+        i : integer;
       begin
       begin
-        for i:=0 to high(s) do
+        for i:=0 to s.count-1 do
           begin
           begin
             writeln(f,'=============================== Node ',i,' ===============================');
             writeln(f,'=============================== Node ',i,' ===============================');
-            printnode(f,s[i]);
+            printnode(f,tnode(s[i]));
             writeln(f);
             writeln(f);
           end;
           end;
       end;
       end;
 
 
 
 
+    function PrintNodeDFA(var n: tnode; arg: pointer): foreachnoderesult;
+      begin
+        if assigned(n.optinfo) and ((n.optinfo^.life<>nil) or (n.optinfo^.use<>nil) or (n.optinfo^.def<>nil)) then
+          begin
+            write(text(arg^),nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,') Life: ');
+            PrintDFASet(text(arg^),n.optinfo^.life);
+            write(text(arg^),' Def: ');
+            PrintDFASet(text(arg^),n.optinfo^.def);
+            write(text(arg^),' Use: ');
+            PrintDFASet(text(arg^),n.optinfo^.use);
+            writeln(text(arg^));
+          end;
+        result:=fen_false;
+      end;
+
+
+    procedure PrintDFAInfo(var f : text;p : tnode);
+      begin
+        foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
+      end;
+
+
     procedure SetNodeSucessors(p : tnode);
     procedure SetNodeSucessors(p : tnode);
       var
       var
         Continuestack : TFPList;
         Continuestack : TFPList;
@@ -119,6 +144,8 @@ unit optutils;
           hp1,hp2 : tnode;
           hp1,hp2 : tnode;
         begin
         begin
           result:=nil;
           result:=nil;
+          if p=nil then
+            exit;
           case p.nodetype of
           case p.nodetype of
             statementn:
             statementn:
               begin
               begin
@@ -126,36 +153,41 @@ unit optutils;
                 result:=p;
                 result:=p;
                 while assigned(hp1) do
                 while assigned(hp1) do
                   begin
                   begin
-                    if assigned(tstatementnode(hp1).right) then
+                    { does another statement follow? }
+                    if assigned(tstatementnode(hp1).next) then
                       begin
                       begin
                         hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
                         hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
                         if assigned(hp2) then
                         if assigned(hp2) then
                           tstatementnode(hp1).successor:=hp2
                           tstatementnode(hp1).successor:=hp2
                         else
                         else
-                          tstatementnode(hp1).successor:=tstatementnode(hp1).right;
+                          tstatementnode(hp1).successor:=tstatementnode(hp1).next;
                       end
                       end
                     else
                     else
                       begin
                       begin
-                        hp2:=DoSet(tstatementnode(hp1).statement,successor);
+                        hp2:=DoSet(tstatementnode(hp1).statement,succ);
                         if assigned(hp2) then
                         if assigned(hp2) then
                           tstatementnode(hp1).successor:=hp2
                           tstatementnode(hp1).successor:=hp2
                         else
                         else
-                          tstatementnode(hp1).successor:=successor;
+                          tstatementnode(hp1).successor:=succ;
                       end;
                       end;
+                    hp1:=tstatementnode(hp1).next;
                   end;
                   end;
               end;
               end;
             blockn:
             blockn:
               begin
               begin
-                result:=DoSet(tblocknode(p).statements,successor);
+                result:=p;
+                DoSet(tblocknode(p).statements,succ);
+                p.successor:=succ;
               end;
               end;
             forn:
             forn:
               begin
               begin
-                Breakstack.Add(successor);
+                Breakstack.Add(succ);
                 Continuestack.Add(p);
                 Continuestack.Add(p);
                 result:=p;
                 result:=p;
-                DoSet(tfornode(p).statements,successor);
-                Breakstack.Delete(Count-1);
-                Continuestack.Delete(Count-1);
+                { the successor of the last node of the for body is the for node itself }
+                DoSet(tfornode(p).t2,p);
+                Breakstack.Delete(Breakstack.Count-1);
+                Continuestack.Delete(Continuestack.Count-1);
               end;
               end;
             breakn:
             breakn:
               begin
               begin
@@ -167,6 +199,17 @@ unit optutils;
                 result:=p;
                 result:=p;
                 p.successor:=tnode(Continuestack.Last);
                 p.successor:=tnode(Continuestack.Last);
               end;
               end;
+            whilerepeatn:
+              begin
+                Breakstack.Add(succ);
+                Continuestack.Add(p);
+                result:=p;
+                { the successor of the last node of the for body is the while node itself }
+                DoSet(twhilerepeatnode(p).right,p);
+                p.successor:=succ;
+                Breakstack.Delete(Breakstack.Count-1);
+                Continuestack.Delete(Continuestack.Count-1);
+              end;
             { exit is actually a jump to some final. code
             { exit is actually a jump to some final. code
             exitn:
             exitn:
               begin
               begin
@@ -175,7 +218,6 @@ unit optutils;
               end;
               end;
             }
             }
             ifn,
             ifn,
-            whilerepeatn,
             exitn,
             exitn,
             withn,
             withn,
             casen,
             casen,

+ 7 - 1
compiler/psub.pas

@@ -103,7 +103,8 @@ implementation
        tgobj,cgbase,cgobj,dbgbase,
        tgobj,cgbase,cgobj,dbgbase,
        ncgutil,regvars,
        ncgutil,regvars,
        opttail,
        opttail,
-       optcse
+       optcse,
+       optdfa
 {$if defined(arm) or defined(powerpc) or defined(powerpc64)}
 {$if defined(arm) or defined(powerpc) or defined(powerpc64)}
        ,aasmcpu
        ,aasmcpu
 {$endif arm}
 {$endif arm}
@@ -755,6 +756,11 @@ implementation
           (pi_is_recursive in flags) then
           (pi_is_recursive in flags) then
           do_opttail(code,procdef);
           do_opttail(code,procdef);
 
 
+        if cs_opt_nodedfa in current_settings.optimizerswitches then
+          begin
+            createdfainfo(code);
+          end;
+
         if cs_opt_nodecse in current_settings.optimizerswitches then
         if cs_opt_nodecse in current_settings.optimizerswitches then
           do_optcse(code);
           do_optcse(code);