+ 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, globtype,systems,constexp,compinnr,
cutils,verbose,globals,widestr,ppu, cutils,verbose,globals,widestr,ppu,
symconst,symdef,symsym,symcpu,symtable, 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, cgbase,procinfo,
htypechk,blockutl,pass_1,cpuinfo; htypechk,blockutl,pass_1,cpuinfo;
@ -2872,6 +2872,9 @@ implementation
function checkremovebiginttypeconvs(n: tnode; out gotsint: boolean;validints : tordtypeset;const l,h : Tconstexprint): boolean; function checkremovebiginttypeconvs(n: tnode; out gotsint: boolean;validints : tordtypeset;const l,h : Tconstexprint): boolean;
var var
gotminus1,
gotsigned,
gotunsigned,
gotdivmod: boolean; gotdivmod: boolean;
{ checks whether a node has an accepted resultdef, or originally { checks whether a node has an accepted resultdef, or originally
@ -2880,6 +2883,13 @@ implementation
begin begin
if (n.resultdef.typ<>orddef) then if (n.resultdef.typ<>orddef) then
exit(false); 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 if (torddef(n.resultdef).ordtype in validints) then
begin begin
if is_signed(n.resultdef) then if is_signed(n.resultdef) then
@ -2904,7 +2914,12 @@ implementation
is_signed(ttypeconvnode(n).left.resultdef)) or is_signed(ttypeconvnode(n).left.resultdef)) or
((n.nodetype=ordconstn) and ((n.nodetype=ordconstn) and
(tordconstnode(n).value<0)) then (tordconstnode(n).value<0)) then
gotsint:=true; begin
gotsint:=true;
gotsigned:=true;
end
else
gotunsigned:=true;
exit(true); exit(true);
end; end;
result:=false; result:=false;
@ -2938,7 +2953,10 @@ implementation
gotdivmod:=true; gotdivmod:=true;
result:= result:=
(docheckremoveinttypeconvs(tbinarynode(n).left) and (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 { in case of div/mod, the result of that division/modulo can
usually be different in 32 and 64 bit } usually be different in 32 and 64 bit }
(not gotdivmod and (not gotdivmod and
@ -2953,14 +2971,22 @@ implementation
begin { checkremove64bittypeconvs } begin { checkremove64bittypeconvs }
gotdivmod:=false; gotdivmod:=false;
gotsint:=false; gotsint:=false;
gotminus1:=false;
gotsigned:=false;
gotunsigned:=false;
result:= result:=
docheckremoveinttypeconvs(n) and docheckremoveinttypeconvs(n) and
not(gotdivmod and gotsint); (not(gotdivmod) or (gotsigned xor gotunsigned));
end; end;
{ remove int type conversions and set the result to the given type } { remove int type conversions and set the result to the given type }
procedure doremoveinttypeconvs(var n: tnode; todef: tdef; forceunsigned: boolean; signedtype,unsignedtype : tdef); procedure doremoveinttypeconvs(var n: tnode; todef: tdef; forceunsigned: boolean; signedtype,unsignedtype : tdef);
var
newblock: tblocknode;
newstatements: tstatementnode;
originaldivtree: tnode;
tempnode: ttempcreatenode;
begin begin
case n.nodetype of case n.nodetype of
subn,addn,muln,divn,modn,xorn,andn,orn: subn,addn,muln,divn,modn,xorn,andn,orn:
@ -2969,9 +2995,34 @@ implementation
if not forceunsigned and if not forceunsigned and
is_signed(n.resultdef) then is_signed(n.resultdef) then
begin begin
originaldivtree:=nil;
if n.nodetype in [divn,modn] then
originaldivtree:=n.getcopy;
doremoveinttypeconvs(tbinarynode(n).left,signedtype,false,signedtype,unsignedtype); doremoveinttypeconvs(tbinarynode(n).left,signedtype,false,signedtype,unsignedtype);
doremoveinttypeconvs(tbinarynode(n).right,signedtype,false,signedtype,unsignedtype); doremoveinttypeconvs(tbinarynode(n).right,signedtype,false,signedtype,unsignedtype);
n.resultdef:=signedtype; 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 end
else else
begin begin