mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-02 10:09:35 +01:00
+ 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:
parent
272a0e3e26
commit
e0a1bc6675
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
tests/test/tandorandnot1.pp
Normal file
34
tests/test/tandorandnot1.pp
Normal 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.
|
||||
Loading…
Reference in New Issue
Block a user