+ optimization type converted (modulo) divisions as well by removing up/down converting but,

insert a test and separate code path for -1 if needed

git-svn-id: trunk@47521 -
This commit is contained in:
florian 2020-11-21 21:58:28 +00:00
parent ebb199b9d4
commit ea11517d27

View File

@ -322,7 +322,7 @@ implementation
globtype,systems,constexp,compinnr,
cutils,verbose,globals,widestr,ppu,
symconst,symdef,symsym,symcpu,symtable,
ncon,ncal,nset,nadd,nmem,nmat,nbas,nutils,ninl,
ncon,ncal,nset,nadd,nmem,nmat,nbas,nutils,ninl,nflw,
cgbase,procinfo,
htypechk,blockutl,pass_1,cpuinfo;
@ -2872,6 +2872,9 @@ implementation
function checkremovebiginttypeconvs(n: tnode; out gotsint: boolean;validints : tordtypeset;const l,h : Tconstexprint): boolean;
var
gotminus1,
gotsigned,
gotunsigned,
gotdivmod: boolean;
{ checks whether a node has an accepted resultdef, or originally
@ -2880,6 +2883,13 @@ implementation
begin
if (n.resultdef.typ<>orddef) then
exit(false);
gotsigned:=gotsigned or is_signed(n.resultdef);
gotunsigned:=gotunsigned or not(is_signed(n.resultdef));
{ actually, we should only check right (denominator) nodes here, but
setting it always is a safe approximation }
if ((n.nodetype=ordconstn) and
(tordconstnode(n).value=-1)) then
gotminus1:=true;
if (torddef(n.resultdef).ordtype in validints) then
begin
if is_signed(n.resultdef) then
@ -2904,7 +2914,12 @@ implementation
is_signed(ttypeconvnode(n).left.resultdef)) or
((n.nodetype=ordconstn) and
(tordconstnode(n).value<0)) then
gotsint:=true;
begin
gotsint:=true;
gotsigned:=true;
end
else
gotunsigned:=true;
exit(true);
end;
result:=false;
@ -2938,7 +2953,10 @@ implementation
gotdivmod:=true;
result:=
(docheckremoveinttypeconvs(tbinarynode(n).left) and
docheckremoveinttypeconvs(tbinarynode(n).right)) or
docheckremoveinttypeconvs(tbinarynode(n).right) and
(not(n.nodetype in [modn,divn]) or (not(gotminus1)))
) or
{ in case of div/mod, the result of that division/modulo can
usually be different in 32 and 64 bit }
(not gotdivmod and
@ -2953,14 +2971,22 @@ implementation
begin { checkremove64bittypeconvs }
gotdivmod:=false;
gotsint:=false;
gotminus1:=false;
gotsigned:=false;
gotunsigned:=false;
result:=
docheckremoveinttypeconvs(n) and
not(gotdivmod and gotsint);
(not(gotdivmod) or (gotsigned xor gotunsigned));
end;
{ remove int type conversions and set the result to the given type }
procedure doremoveinttypeconvs(var n: tnode; todef: tdef; forceunsigned: boolean; signedtype,unsignedtype : tdef);
var
newblock: tblocknode;
newstatements: tstatementnode;
originaldivtree: tnode;
tempnode: ttempcreatenode;
begin
case n.nodetype of
subn,addn,muln,divn,modn,xorn,andn,orn:
@ -2969,9 +2995,34 @@ implementation
if not forceunsigned and
is_signed(n.resultdef) then
begin
originaldivtree:=nil;
if n.nodetype in [divn,modn] then
originaldivtree:=n.getcopy;
doremoveinttypeconvs(tbinarynode(n).left,signedtype,false,signedtype,unsignedtype);
doremoveinttypeconvs(tbinarynode(n).right,signedtype,false,signedtype,unsignedtype);
n.resultdef:=signedtype;
if n.nodetype in [divn,modn] then
begin
newblock:=internalstatements(newstatements);
tempnode:=ctempcreatenode.create(n.resultdef,n.resultdef.size,tt_persistent,true);
addstatement(newstatements,tempnode);
addstatement(newstatements,cifnode.create_internal(
caddnode.create_internal(equaln,tbinarynode(n).right.getcopy,cordconstnode.create(-1,n.resultdef,false)),
cassignmentnode.create_internal(
ctemprefnode.create(tempnode),
cmoddivnode.create(n.nodetype,tbinarynode(originaldivtree).left.getcopy,cordconstnode.create(-1,tbinarynode(originaldivtree).right.resultdef,false))
),
cassignmentnode.create_internal(
ctemprefnode.create(tempnode),n
)
)
);
addstatement(newstatements,ctempdeletenode.create_normal_temp(tempnode));
addstatement(newstatements,ctemprefnode.create(tempnode));
n:=newblock;
do_typecheckpass(n);
originaldivtree.free;
end;
end
else
begin