* Adjustment to "(v>=x) and (v<=y)" so it also optimises its inverse: "(v<x) or (v>y)"

This commit is contained in:
J. Gareth "Curious Kit" Moreton 2024-03-12 06:14:38 +00:00 committed by FPK
parent d0f08ef259
commit e1297e0859

View File

@ -407,10 +407,12 @@ implementation
function is_range_test(nodel, noder: taddnode; out value: tnode; var cl,cr: Tconstexprint): boolean;
const
is_upper_test: array[ltn..gten] of boolean = (true,true,false,false);
inclusive_adjust: array[boolean,ltn..gten] of integer = ((-1,0,1,0),
(1,0,-1,0));
inclusive_adjust: array[boolean,boolean,ltn..gten] of integer = (((-1,0,1,0),
(1,0,-1,0)),
((0,-1,0,1),
(0,1,0,-1)));
var
swapl, swapr: Boolean;
swapl, swapr, inverted_range: Boolean;
valuer: tnode;
t: Tconstexprint;
begin
@ -449,12 +451,21 @@ implementation
if not value.isequal(valuer) then
exit;
{ This is based on De Morgan's theorem, namely that
"A and B" = "not ((not A) or (not B))" }
inverted_range:=(nodetype=orn);
if inverted_range then
begin
swapl:=not swapl;
swapr:=not swapr;
end;
{ this could be simplified too, but probably never happens }
if (is_upper_test[nodel.nodetype] xor swapl)=(is_upper_test[noder.nodetype] xor swapr) then
exit;
cl:=cl+inclusive_adjust[swapl,nodel.nodetype];
cr:=cr+inclusive_adjust[swapr,noder.nodetype];
cl:=cl+inclusive_adjust[inverted_range,swapl,nodel.nodetype];
cr:=cr+inclusive_adjust[inverted_range,swapr,noder.nodetype];
if is_upper_test[nodel.nodetype] xor swapl then
begin
@ -1569,7 +1580,7 @@ implementation
{ transform unsigned comparisons of (v>=x) and (v<=y)
into (v-x)<=(y-x)
}
if (nodetype=andn) and
if (nodetype in [andn,orn]) and
(left.nodetype in [ltn,lten,gtn,gten]) and
(right.nodetype in [ltn,lten,gtn,gten]) and
(not might_have_sideeffects(left)) and
@ -1581,9 +1592,19 @@ implementation
hdef:=get_unsigned_inttype(vl.resultdef);
vl:=ctypeconvnode.create_internal(vl.getcopy,hdef);
result:=caddnode.create_internal(lten,
{ If the condition is of the inverted form (v<x) or (v>y),
we have to invert the conditional result as well, since
the above nodes return True for if v is within the range
(we're merging "not ((v-x)<=(y-x))" into "(v-x)>(y-x)") }
if (nodetype=orn) then
nt:=gtn
else
nt:=lten;
result:=caddnode.create_internal(nt,
ctypeconvnode.create_internal(caddnode.create_internal(subn,vl,cordconstnode.create(cl,hdef,false)),hdef),
cordconstnode.create(cr-cl,hdef,false));
exit;
end;