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

+ test

git-svn-id: trunk@48841 -
This commit is contained in:
florian 2021-02-28 18:20:46 +00:00
parent 272a0e3e26
commit e0a1bc6675
4 changed files with 107 additions and 0 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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.