Просмотр исходного кода

* dfa fixes by Sergei Gorelkin, resolve #15402

git-svn-id: trunk@14455 -
florian 15 лет назад
Родитель
Сommit
9955e6b2bf
5 измененных файлов с 120 добавлено и 26 удалено
  1. 2 0
      .gitattributes
  2. 44 25
      compiler/optdfa.pas
  3. 1 1
      compiler/psub.pas
  4. 19 0
      tests/test/opt/tdfa1.pp
  5. 54 0
      tests/test/opt/tdfa2.pp

+ 2 - 0
.gitattributes

@@ -8737,6 +8737,8 @@ tests/test/opt/tcmov.pp svneol=native#text/plain
 tests/test/opt/tcse1.pp svneol=native#text/plain
 tests/test/opt/tcse2.pp svneol=native#text/plain
 tests/test/opt/tcse3.pp svneol=native#text/plain
+tests/test/opt/tdfa1.pp svneol=native#text/pascal
+tests/test/opt/tdfa2.pp svneol=native#text/pascal
 tests/test/opt/tgotoreg.pp svneol=native#text/plain
 tests/test/opt/treg1.pp svneol=native#text/plain
 tests/test/opt/treg2.pp svneol=native#text/plain

+ 44 - 25
compiler/optdfa.pas

@@ -241,6 +241,7 @@ unit optdfa;
         var
           dfainfo : tdfainfo;
           l : TDFASet;
+          save: TDFASet;
           i : longint;
 
         begin
@@ -265,34 +266,50 @@ unit optdfa;
           case node.nodetype of
             whilerepeatn:
               begin
-                calclife(node);
-                { take care of repeat until! }
-                if lnf_testatbegin in twhilerepeatnode(node).loopflags then
+                { analyze the loop condition }
+                if not(assigned(node.optinfo^.def)) and
+                   not(assigned(node.optinfo^.use)) then
                   begin
-                    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);
+                    dfainfo.use:[email protected]^.use;
+                    dfainfo.def:[email protected]^.def;
+                    dfainfo.map:=map;
+                    foreachnodestatic(pm_postprocess,twhilerepeatnode(node).left,@AddDefUse,@dfainfo);
+                  end;
 
-                    { now iterate through the loop }
-                    CreateInfo(twhilerepeatnode(node).right);
+                { NB: this node should typically have empty def set }                  
+                if assigned(node.successor) then
+                  DFASetDiff(l,node.successor.optinfo^.life,node.optinfo^.def)
+                else if assigned(resultnode) then
+                  DFASetDiff(l,resultnode.optinfo^.life,node.optinfo^.def)
+                else
+                  l:=nil;
 
-                    { 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);
+                { for repeat..until, node use set in included at the end of loop }
+                if not (lnf_testatbegin in twhilerepeatnode(node).loopflags) then
+                  DFASetIncludeSet(l,node.optinfo^.use);
 
-                    { ... and a second iteration for fast convergence }
-                    CreateInfo(twhilerepeatnode(node).right);
-                  end;
+                DFASetIncludeSet(l,node.optinfo^.life);
+
+                save:=node.optinfo^.life;
+                { to process body correctly, we need life info in place (because
+                  whilerepeatnode is successor of its body). }
+                node.optinfo^.life:=l;
+
+                { now process the body }
+                CreateInfo(twhilerepeatnode(node).right);
+
+                { restore, to prevent infinite recursion via changed flag }
+                node.optinfo^.life:=save;
+
+                { for while loops, node use set is included at the beginning of loop }
+                l:=twhilerepeatnode(node).right.optinfo^.life;
+                if lnf_testatbegin in twhilerepeatnode(node).loopflags then
+                  DFASetIncludeSet(l,node.optinfo^.use);
+
+                UpdateLifeInfo(node,l);
+
+                { ... and a second iteration for fast convergence }
+                CreateInfo(twhilerepeatnode(node).right);
               end;
 
             forn:
@@ -326,9 +343,11 @@ unit optdfa;
 
                 { update for node }
                 { life:=life+use+body }
-                l:=node.optinfo^.life;
+                l:=copy(node.optinfo^.life);
                 DFASetIncludeSet(l,node.optinfo^.use);
                 DFASetIncludeSet(l,tfornode(node).t2.optinfo^.life);
+                { the for loop always updates its control variable }
+                DFASetDiff(l,l,node.optinfo^.def);
                 UpdateLifeInfo(node,l);
 
                 { ... and a second iteration for fast convergence }

+ 1 - 1
compiler/psub.pas

@@ -792,7 +792,7 @@ implementation
                               CGMessage(sym_w_function_result_uninitialized)
                             else
                               begin
-                                if varsym.owner=procdef.localst then
+                                if (varsym.owner=procdef.localst) and not (vo_is_typed_const in varsym.varoptions) then
                                   CGMessage1(sym_w_uninitialized_local_variable,varsym.realname);
                               end;
                           end;

+ 19 - 0
tests/test/opt/tdfa1.pp

@@ -0,0 +1,19 @@
+{ %OPT=-Oodfa -Sew -vw}
+{ %NORUN}
+{ %FAIL}
+
+program tdfa1;
+
+procedure p;
+var
+  counter: Integer;
+  c1: Word;
+begin
+  repeat
+    c1 := counter;  // counter not initialized
+    counter:=15;
+  until counter>=10;
+end;
+
+begin
+end.

+ 54 - 0
tests/test/opt/tdfa2.pp

@@ -0,0 +1,54 @@
+{ %OPT=-Oodfa -Sew -vw}
+unit tdfa;
+{$mode objfpc}{$h+}
+
+interface
+
+implementation
+
+procedure test0;
+const
+  c: array[0..3] of integer = (0,1,2,3);
+begin
+  writeln(c[1]);
+end;
+
+procedure test1;
+var
+  i: integer;
+begin
+  for i:=0 to 10 do
+    if i=5 then
+    ;
+end;
+
+function test2(S1: PWideChar; Len: Integer): Integer;
+var
+  counter: Integer;
+  c1: Word;
+begin
+  counter:=0;  
+  repeat
+    c1 := ord(s1[counter]);
+    counter:=counter+1;
+  until counter>=len;
+  result := c1;
+end;
+
+function test3(S1: PWideChar; Len: Integer): Integer;
+var
+  counter: Integer;
+  c1: Word;
+begin
+  counter:=0;  
+  while counter<len do
+  begin
+    c1 := ord(s1[counter]);
+    counter:=counter+1;
+  end;
+  result := c1;
+end;
+
+
+
+end.