* simplify real expressions involving unary minus

+ test
This commit is contained in:
florian 2021-09-19 23:07:59 +02:00
parent 12796d176d
commit 8cb92fd49a
2 changed files with 149 additions and 69 deletions

View File

@ -992,83 +992,128 @@ implementation
exit;
end;
{ optimize operations with real constants, but only if fast math is switched on as
the operations could change e.g. the sign of 0 so they cannot be optimized always
}
if (cs_opt_fastmath in current_settings.optimizerswitches) and
is_real(resultdef) then
if is_real(resultdef) then
begin
if lt=realconstn then
if (nodetype=addn) then
begin
if (trealconstnode(left).value_real=0) and (nodetype in [addn,muln,subn,slashn]) then
{ -left+right => right-left,
this operation is always valid }
if (left.nodetype=unaryminusn) then
begin
result:=caddnode.create(subn,right.getcopy,tunaryminusnode(left).left.getcopy);
exit;
end;
{ left+(-right) => left-right,
this operation is always valid }
if (right.nodetype=unaryminusn) then
begin
result:=caddnode.create(subn,left.getcopy,tunaryminusnode(right).left.getcopy);
exit;
end;
end;
{ left-(-right) => left+right,
this operation is always valid }
if (nodetype=subn) and (right.nodetype=unaryminusn) then
begin
result:=caddnode.create(addn,left.getcopy,tunaryminusnode(right).left.getcopy);
exit;
end;
{ (-left)*(-right) => left*right,
this operation is always valid }
if (nodetype=muln) and (left.nodetype=unaryminusn) and (right.nodetype=unaryminusn) then
begin
result:=caddnode.create(muln,tunaryminusnode(left).left.getcopy,tunaryminusnode(right).left.getcopy);
exit;
end;
{ (-left)/(-right) => left/right,
this operation is always valid }
if (nodetype=slashn) and (left.nodetype=unaryminusn) and (right.nodetype=unaryminusn) then
begin
result:=caddnode.create(slashn,tunaryminusnode(left).left.getcopy,tunaryminusnode(right).left.getcopy);
exit;
end;
{ optimize operations with real constants, but only if fast math is switched on as
the operations could change e.g. the sign of 0 so they cannot be optimized always
}
if is_real(resultdef) then
begin
if lt=realconstn then
begin
if (trealconstnode(left).value_real=0) and (nodetype in [addn,muln,subn,slashn]) then
begin
case nodetype of
addn:
begin
result:=right.getcopy;
exit;
end;
slashn,
muln:
if not(might_have_sideeffects(right,[mhs_exceptions])) then
begin
result:=left.getcopy;
exit;
end;
subn:
begin
result:=ctypeconvnode.create_internal(cunaryminusnode.create(right.getcopy),right.resultdef);
exit;
end;
else
Internalerror(2020060801);
end;
end
else if (trealconstnode(left).value_real=1) and (nodetype=muln) then
begin
result:=right.getcopy;
exit;
end;
end
else if rt=realconstn then
begin
if (trealconstnode(right).value_real=0) and (nodetype in [addn,muln,subn]) then
begin
case nodetype of
subn,
addn:
begin
result:=left.getcopy;
exit;
end;
muln:
if not(might_have_sideeffects(left,[mhs_exceptions])) then
begin
result:=right.getcopy;
exit;
end;
else
Internalerror(2020060802);
end;
end
else if (trealconstnode(right).value_real=1) and (nodetype in [muln,slashn]) then
begin
result:=left.getcopy;
exit;
end;
end
{ optimize a/a and a-a }
else if (cs_opt_level2 in current_settings.optimizerswitches) and (nodetype in [slashn,subn]) and
left.isequal(right) and not(might_have_sideeffects(left,[mhs_exceptions])) then
begin
case nodetype of
addn:
begin
result:=right.getcopy;
exit;
end;
slashn,
muln:
if not(might_have_sideeffects(right,[mhs_exceptions])) then
begin
result:=left.getcopy;
exit;
end;
subn:
begin
result:=ctypeconvnode.create_internal(cunaryminusnode.create(right.getcopy),right.resultdef);
exit;
end;
result:=crealconstnode.create(0,left.resultdef);
slashn:
result:=crealconstnode.create(1,left.resultdef);
else
Internalerror(2020060801);
Internalerror(2020060901);
end;
end
else if (trealconstnode(left).value_real=1) and (nodetype=muln) then
begin
result:=right.getcopy;
exit;
end;
end
else if rt=realconstn then
begin
if (trealconstnode(right).value_real=0) and (nodetype in [addn,muln,subn]) then
begin
case nodetype of
subn,
addn:
begin
result:=left.getcopy;
exit;
end;
muln:
if not(might_have_sideeffects(left,[mhs_exceptions])) then
begin
result:=right.getcopy;
exit;
end;
else
Internalerror(2020060802);
end;
end
else if (trealconstnode(right).value_real=1) and (nodetype in [muln,slashn]) then
begin
result:=left.getcopy;
exit;
end;
end
{ optimize a/a and a-a }
else if (cs_opt_level2 in current_settings.optimizerswitches) and (nodetype in [slashn,subn]) and
left.isequal(right) and not(might_have_sideeffects(left,[mhs_exceptions])) then
begin
case nodetype of
subn:
result:=crealconstnode.create(0,left.resultdef);
slashn:
result:=crealconstnode.create(1,left.resultdef);
else
Internalerror(2020060901);
end;
end;
end;

35
tests/tbs/tb0685.pp Normal file
View File

@ -0,0 +1,35 @@
{ %OPT=-O- }
var
d1,d2,d3 : double;
begin
d1:=0.0;
d2:=-0.0;
d3:=-d1+d2;
writeln(d3);
if (d3<>0.0) or not(TDoubleRec(d3).Sign) then
halt(1);
d3:=d2+-d1;
writeln(d3);
if (d3<>0.0) or not(TDoubleRec(d3).Sign) then
halt(2);
d3:=d2--d1;
writeln(d3);
if (d3<>0.0) or (TDoubleRec(d3).Sign) then
halt(3);
d1:=1.0;
d2:=1.0;
d3:=-d2*-d1;
writeln(d3);
if (d3<>1.0) or (TDoubleRec(d3).Sign) then
halt(4);
d3:=-d2/-d1;
writeln(d3);
if (d3<>1.0) or (TDoubleRec(d3).Sign) then
halt(5);
writeln('ok');
end.