mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 00:09:23 +02:00
* Adjustment to "(v>=x) and (v<=y)" so it also optimises its inverse: "(v<x) or (v>y)"
This commit is contained in:
parent
d0f08ef259
commit
e1297e0859
@ -407,10 +407,12 @@ implementation
|
|||||||
function is_range_test(nodel, noder: taddnode; out value: tnode; var cl,cr: Tconstexprint): boolean;
|
function is_range_test(nodel, noder: taddnode; out value: tnode; var cl,cr: Tconstexprint): boolean;
|
||||||
const
|
const
|
||||||
is_upper_test: array[ltn..gten] of boolean = (true,true,false,false);
|
is_upper_test: array[ltn..gten] of boolean = (true,true,false,false);
|
||||||
inclusive_adjust: array[boolean,ltn..gten] of integer = ((-1,0,1,0),
|
inclusive_adjust: array[boolean,boolean,ltn..gten] of integer = (((-1,0,1,0),
|
||||||
(1,0,-1,0));
|
(1,0,-1,0)),
|
||||||
|
((0,-1,0,1),
|
||||||
|
(0,1,0,-1)));
|
||||||
var
|
var
|
||||||
swapl, swapr: Boolean;
|
swapl, swapr, inverted_range: Boolean;
|
||||||
valuer: tnode;
|
valuer: tnode;
|
||||||
t: Tconstexprint;
|
t: Tconstexprint;
|
||||||
begin
|
begin
|
||||||
@ -449,12 +451,21 @@ implementation
|
|||||||
if not value.isequal(valuer) then
|
if not value.isequal(valuer) then
|
||||||
exit;
|
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 }
|
{ 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
|
if (is_upper_test[nodel.nodetype] xor swapl)=(is_upper_test[noder.nodetype] xor swapr) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
cl:=cl+inclusive_adjust[swapl,nodel.nodetype];
|
cl:=cl+inclusive_adjust[inverted_range,swapl,nodel.nodetype];
|
||||||
cr:=cr+inclusive_adjust[swapr,noder.nodetype];
|
cr:=cr+inclusive_adjust[inverted_range,swapr,noder.nodetype];
|
||||||
|
|
||||||
if is_upper_test[nodel.nodetype] xor swapl then
|
if is_upper_test[nodel.nodetype] xor swapl then
|
||||||
begin
|
begin
|
||||||
@ -1569,7 +1580,7 @@ implementation
|
|||||||
{ transform unsigned comparisons of (v>=x) and (v<=y)
|
{ transform unsigned comparisons of (v>=x) and (v<=y)
|
||||||
into (v-x)<=(y-x)
|
into (v-x)<=(y-x)
|
||||||
}
|
}
|
||||||
if (nodetype=andn) and
|
if (nodetype in [andn,orn]) and
|
||||||
(left.nodetype in [ltn,lten,gtn,gten]) and
|
(left.nodetype in [ltn,lten,gtn,gten]) and
|
||||||
(right.nodetype in [ltn,lten,gtn,gten]) and
|
(right.nodetype in [ltn,lten,gtn,gten]) and
|
||||||
(not might_have_sideeffects(left)) and
|
(not might_have_sideeffects(left)) and
|
||||||
@ -1581,9 +1592,19 @@ implementation
|
|||||||
hdef:=get_unsigned_inttype(vl.resultdef);
|
hdef:=get_unsigned_inttype(vl.resultdef);
|
||||||
vl:=ctypeconvnode.create_internal(vl.getcopy,hdef);
|
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),
|
ctypeconvnode.create_internal(caddnode.create_internal(subn,vl,cordconstnode.create(cl,hdef,false)),hdef),
|
||||||
cordconstnode.create(cr-cl,hdef,false));
|
cordconstnode.create(cr-cl,hdef,false));
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user