Quellcode durchsuchen

+ convert case <boolean> of into if statement, resolves #10517

git-svn-id: trunk@10873 -
florian vor 17 Jahren
Ursprung
Commit
8fe43377e1
3 geänderte Dateien mit 183 neuen und 3 gelöschten Zeilen
  1. 1 0
      .gitattributes
  2. 70 3
      compiler/nset.pas
  3. 112 0
      tests/test/opt/tcaseopt1.pp

+ 1 - 0
.gitattributes

@@ -7270,6 +7270,7 @@ tests/test/cg/variants/tvarol96.pp svneol=native#text/plain
 tests/test/dumpclass.pp svneol=native#text/plain
 tests/test/dumpmethods.pp svneol=native#text/plain
 tests/test/opt/README -text
+tests/test/opt/tcaseopt1.pp svneol=native#text/plain
 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

+ 70 - 3
compiler/nset.pas

@@ -116,7 +116,7 @@ implementation
       verbose,
       symconst,symdef,symsym,symtable,defutil,defcmp,
       htypechk,pass_1,
-      nbas,ncnv,ncon,nld,cgobj,cgbase;
+      nbas,ncnv,ncon,nld,nflw,cgobj,cgbase;
 
 
 {*****************************************************************************
@@ -609,10 +609,10 @@ implementation
       end;
 
 
-
     function tcasenode.pass_1 : tnode;
       var
          i  : integer;
+         node_thenblock,node_elseblock : tnode;
       begin
          result:=nil;
          expectloc:=LOC_VOID;
@@ -628,7 +628,74 @@ implementation
 
          { may be handle else tree }
          if assigned(elseblock) then
-           firstpass(elseblock);
+           begin
+             firstpass(elseblock);
+
+             { kill case? }
+             if blocks.count=0 then
+               begin
+                 result:=elseblock;
+                 elseblock:=nil;
+                 exit;
+               end;
+           end
+         else
+           if blocks.count=0 then
+             begin
+               result:=cnothingnode.create;
+               exit;
+             end;
+
+         if is_boolean(left.resultdef) then
+           begin
+             case blocks.count of
+               2:
+                 begin
+                   if boolean(qword(labels^._low))=false then
+                     begin
+                       node_thenblock:=pcaseblock(blocks[labels^.greater^.blockid])^.statement;
+                       node_elseblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+                       pcaseblock(blocks[labels^.greater^.blockid])^.statement:=nil;
+                     end
+                   else
+                     begin
+                       node_thenblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+                       node_elseblock:=pcaseblock(blocks[labels^.less^.blockid])^.statement;
+                       pcaseblock(blocks[labels^.less^.blockid])^.statement:=nil;
+                     end;
+                   pcaseblock(blocks[labels^.blockid])^.statement:=nil;
+                 end;
+               1:
+                 begin
+                   if labels^._low=labels^._high then
+                     begin
+                       if boolean(qword(labels^._low))=false then
+                         begin
+                           node_thenblock:=elseblock;
+                           node_elseblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+                         end
+                       else
+                         begin
+                           node_thenblock:=pcaseblock(blocks[labels^.blockid])^.statement;
+                           node_elseblock:=elseblock;
+                         end;
+                       pcaseblock(blocks[labels^.blockid])^.statement:=nil;
+                       elseblock:=nil;
+                     end
+                   else
+                     begin
+                       result:=pcaseblock(blocks[labels^.blockid])^.statement;
+                       pcaseblock(blocks[labels^.blockid])^.statement:=nil;
+                       elseblock:=nil;
+                       exit;
+                     end;
+                 end;
+             else
+               internalerror(200805031);
+           end;
+           result:=cifnode.create(left,node_thenblock,node_elseblock);
+           left:=nil;
+         end;
       end;
 
 

+ 112 - 0
tests/test/opt/tcaseopt1.pp

@@ -0,0 +1,112 @@
+Procedure TestCaseBool;
+Var
+  L1, L2: LongWord;
+  b : boolean;
+begin
+  b:=false;
+
+  l1:=$deadbeef;
+  case b of
+    true:
+      l1:=0;
+    else
+      l1:=1234;
+  end;
+  if l1<>1234 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    false:
+      l1:=1234;
+    else
+      l1:=0;
+  end;
+  if l1<>1234 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    true:
+      l1:=0;
+    false:
+      l1:=1234;
+  end;
+  if l1<>1234 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    false..true:
+      l1:=1234;
+    else
+      l1:=0;
+  end;
+  if l1<>1234 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    false..true:
+      l1:=1234;
+  end;
+  if l1<>1234 then
+    halt(1);
+
+
+  { set b to true }
+  b:=true;
+
+  l1:=$deadbeef;
+  case b of
+    true:
+      l1:=0;
+    else
+      l1:=1234;
+  end;
+  if l1<>0 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    false:
+      l1:=1234;
+    else
+      l1:=0;
+  end;
+  if l1<>0 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    true:
+      l1:=0;
+    false:
+      l1:=1234;
+  end;
+  if l1<>0 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    false..true:
+      l1:=1234;
+    else
+      l1:=0;
+  end;
+  if l1<>1234 then
+    halt(1);
+
+  l1:=$deadbeef;
+  case b of
+    false..true:
+      l1:=1234;
+  end;
+  if l1<>1234 then
+    halt(1);
+end;
+
+begin
+  TestCaseBool;
+  writeln('ok');
+end.