Browse Source

* check for more controll flow statements before doing loop unrolling

git-svn-id: trunk@39083 -
florian 7 years ago
parent
commit
8f472d5212
3 changed files with 65 additions and 5 deletions
  1. 1 0
      .gitattributes
  2. 5 5
      compiler/optloop.pas
  3. 59 0
      tests/test/tunroll2.pp

+ 1 - 0
.gitattributes

@@ -13755,6 +13755,7 @@ tests/test/tunit1.pp svneol=native#text/plain
 tests/test/tunit2.pp svneol=native#text/plain
 tests/test/tunit3.pp svneol=native#text/plain
 tests/test/tunroll1.pp svneol=native#text/plain
+tests/test/tunroll2.pp svneol=native#text/pascal
 tests/test/tutf81.pp svneol=native#text/plain
 tests/test/tutf82.pp svneol=native#text/plain
 tests/test/tutf8cpl.pp svneol=native#text/plain

+ 5 - 5
compiler/optloop.pas

@@ -74,9 +74,9 @@ unit optloop;
       end;
       preplaceinfo = ^treplaceinfo;
 
-    function checkbreakcontinue(var n:tnode; arg: pointer): foreachnoderesult;
+    function checkcontrollflowstatements(var n:tnode; arg: pointer): foreachnoderesult;
       begin
-        if n.nodetype in [breakn,continuen] then
+        if n.nodetype in [breakn,continuen,goton,labeln,exitn,raisen] then
           result:=fen_norecurse_true
         else
           result:=fen_false;
@@ -105,7 +105,7 @@ unit optloop;
         unrollblock : tblocknode;
         getridoffor : boolean;
         replaceinfo : treplaceinfo;
-        usesbreakcontinue : boolean;
+        hascontrollflowstatements : boolean;
       begin
         result:=nil;
         if (cs_opt_size in current_settings.optimizerswitches) then
@@ -129,7 +129,7 @@ unit optloop;
                 else
                   counts:=tordconstnode(tfornode(node).t1).value-tordconstnode(tfornode(node).right).value+1;
 
-                usesbreakcontinue:=foreachnodestatic(tfornode(node).t2,@checkbreakcontinue,nil);
+                hascontrollflowstatements:=foreachnodestatic(tfornode(node).t2,@checkcontrollflowstatements,nil);
 
                 { don't unroll more than we need,
 
@@ -143,7 +143,7 @@ unit optloop;
                 unrollblock:=internalstatements(unrollstatement);
 
                 { can we get rid completly of the for ? }
-                getridoffor:=(unrolls=counts) and not(usesbreakcontinue) and
+                getridoffor:=(unrolls=counts) and not(hascontrollflowstatements) and
                   { TP/Macpas allows assignments to the for-variables, so we cannot get rid of the for }
                   ([m_tp7,m_mac]*current_settings.modeswitches=[]);
 

+ 59 - 0
tests/test/tunroll2.pp

@@ -0,0 +1,59 @@
+{ %OPT=-Ooloopunroll -Sg }
+{$mode objfpc}
+
+uses
+  sysutils;
+
+var
+  c,i : Integer;
+
+
+function f1 : Integer;
+  begin
+    for Result:=1 to 2 do
+      if (i=1234) and (Result=2) then
+        Exit;
+  end;
+
+
+function f2 : Integer;
+  begin
+    for Result:=1 to 2 do
+      if (i=1234) and (Result=2) then
+        Break;
+  end;
+
+function f3 : Integer;
+  label
+    Stop;
+  begin
+    for Result:=1 to 2 do
+      if (i=1234) and (Result=2) then
+        Goto Stop;
+  Stop:
+  end;
+
+function f4 : Integer;
+  begin
+    Result:=-1;
+    for c:=1 to 2 do
+      if (i=1234) and (Result=2) then
+        Raise Exception.Create('Test');
+  end;
+
+begin
+  i:=1234;
+  if f1<>2 then
+    halt(1);
+  if f2<>2 then
+    halt(1);
+  if f3<>2 then
+    halt(1);
+  try
+    f4;
+  except
+    if c<>2 then
+      halt(1);
+  end;
+  writeln('ok');
+end.