浏览代码

+ optimize (a and b) or (c and not(b)) into c xor ((c xor a) and b)
+ test

git-svn-id: trunk@48841 -

florian 4 年之前
父节点
当前提交
e0a1bc6675
共有 4 个文件被更改,包括 107 次插入0 次删除
  1. 1 0
      .gitattributes
  2. 36 0
      compiler/nadd.pas
  3. 36 0
      compiler/nutils.pas
  4. 34 0
      tests/test/tandorandnot1.pp

+ 1 - 0
.gitattributes

@@ -14475,6 +14475,7 @@ tests/test/talign1.pp svneol=native#text/plain
 tests/test/talign2.pp svneol=native#text/plain
 tests/test/taligned1.pp svneol=native#text/pascal
 tests/test/tand1.pp svneol=native#text/plain
+tests/test/tandorandnot1.pp svneol=native#text/pascal
 tests/test/targ1a.pp svneol=native#text/plain
 tests/test/targ1b.pp svneol=native#text/plain
 tests/test/tarray1.pp svneol=native#text/plain

+ 36 - 0
compiler/nadd.pas

@@ -489,6 +489,20 @@ implementation
         end;
 
 
+      function IsAndOrAndNot(n1,n2,n3,n4 : tnode): Boolean;
+        begin
+          result:=(n4.nodetype=notn) and
+            tnotnode(n4).left.isequal(n2);
+        end;
+
+
+      function TransformAndOrAndNot(n1,n2,n3,n4 : tnode): tnode;
+        begin
+          result:=caddnode.create_internal(xorn,n3.getcopy,
+            caddnode.create_internal(andn,caddnode.create_internal(xorn,n3.getcopy,n1.getcopy),n2.getcopy));
+        end;
+
+
       function SwapRightWithLeftRight : tnode;
         var
           hp : tnode;
@@ -1689,6 +1703,28 @@ implementation
                    end;
               end;
 {$endif cpurox}
+            { optimize
+
+                (a and b) or (c and not(b))
+
+                into
+
+                c xor ((c xor a) and b)
+            }
+            if (nodetype=orn) and
+             (left.resultdef.typ=orddef) and
+             (left.nodetype=andn) and
+             (right.nodetype=andn) and
+             { this test is not needed but it speeds up the test and allows to bail out early }
+             ((taddnode(left).left.nodetype=notn) or (taddnode(left).right.nodetype=notn) or
+              (taddnode(right).left.nodetype=notn) or (taddnode(right).right.nodetype=notn)
+             ) and
+             not(might_have_sideeffects(self)) then
+             begin
+               if MatchAndTransformNodesCommutative(taddnode(left).left,taddnode(left).right,taddnode(right).left,taddnode(right).right,
+                 @IsAndOrAndNot,@TransformAndOrAndNot,Result) then
+                 exit;
+             end;
           end;
       end;
 

+ 36 - 0
compiler/nutils.pas

@@ -186,11 +186,22 @@ interface
     type
       TMatchProc2 = function(n1,n2 : tnode) : Boolean is nested;
       TTransformProc2 = function(n1,n2 : tnode) : tnode is nested;
+      TMatchProc4 = function(n1,n2,n3,n4 : tnode) : Boolean is nested;
+      TTransformProc4 = function(n1,n2,n3,n4 : tnode) : tnode is nested;
 
     { calls matchproc with n1 and n2 as parameters, if it returns true, transformproc is called, does the same with the nodes swapped,
       the result of transformproc is assigned to res }
     function MatchAndTransformNodesCommutative(n1,n2 : tnode;matchproc : TMatchProc2;transformproc : TTransformProc2;var res : tnode) : Boolean;
 
+    { calls matchproc with n1, n2, n3 and n4 as parameters being considered as the leafs of commutative nodes so all 8 possible
+      combinations are tested, if it returns true, transformproc is called,
+      the result of transformproc is assigned to res
+
+      this allows to find pattern like (3*a)+(3*b) and transfrom them into 3*(a+b)
+    }
+    function MatchAndTransformNodesCommutative(n1,n2,n3,n4 : tnode;matchproc : TMatchProc4;transformproc : TTransformProc4;var res : tnode) : Boolean;
+
+
 implementation
 
     uses
@@ -1642,4 +1653,29 @@ implementation
           result:=false;
       end;
 
+
+    function MatchAndTransformNodesCommutative(n1,n2,n3,n4 : tnode;matchproc : TMatchProc4;transformproc : TTransformProc4;var res : tnode) : Boolean;
+      begin
+        res:=nil;
+        result:=true;
+        if matchproc(n1,n2,n3,n4) then
+          res:=transformproc(n1,n2,n3,n4)
+        else if matchproc(n1,n2,n4,n3) then
+          res:=transformproc(n1,n2,n4,n3)
+        else if matchproc(n2,n1,n3,n4) then
+          res:=transformproc(n2,n1,n3,n4)
+        else if matchproc(n2,n1,n4,n3) then
+          res:=transformproc(n2,n1,n4,n3)
+        else if matchproc(n3,n4,n1,n2) then
+          res:=transformproc(n3,n4,n1,n2)
+        else if matchproc(n4,n3,n1,n2) then
+          res:=transformproc(n4,n3,n1,n2)
+        else if matchproc(n3,n4,n2,n1) then
+          res:=transformproc(n3,n4,n2,n1)
+        else if matchproc(n4,n3,n2,n1) then
+          res:=transformproc(n4,n3,n2,n1)
+        else
+          result:=false;
+      end;
+
 end.

+ 34 - 0
tests/test/tandorandnot1.pp

@@ -0,0 +1,34 @@
+{ test (a and b) or (c and not(b)) into c xor ((c xor a) and b) optimization with random values }
+var
+  i,a,b,c,_a,_b,_c : word;
+begin
+  for i:=1 to 1000 do
+    begin
+      a:=random(65536);
+      _a:=a;
+      b:=random(65536);
+      _b:=b;
+      c:=random(65536);
+      _c:=c;
+      if (a and b) or (c and not(b))<>_c xor ((_c xor _a) and _b) then
+        begin
+          writeln('Error: ','a=',a,'b=',b,'c=',c);
+          halt(1);
+        end;
+      if (a and b) or (not(b) and c)<>_c xor ((_c xor _a) and _b) then
+        begin
+          writeln('Error: ','a=',a,'b=',b,'c=',c);
+          halt(1);
+        end;
+      if (not(b) and c) or (a and b)<>_c xor ((_c xor _a) and _b) then
+        begin
+          writeln('Error: ','a=',a,'b=',b,'c=',c);
+          halt(1);
+        end;
+      if (not(b) and c) or (b and a)<>_c xor ((_c xor _a) and _b) then
+        begin
+          writeln('Error: ','a=',a,'b=',b,'c=',c);
+          halt(1);
+        end;
+    end;
+end.