mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 07:28:26 +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;
|
||||
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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user