mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 01:08:07 +02:00
+ 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:
parent
ebb199b9d4
commit
ea11517d27
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user