From ea11517d27fa00f40b626e47213f0caa8832d155 Mon Sep 17 00:00:00 2001 From: florian Date: Sat, 21 Nov 2020 21:58:28 +0000 Subject: [PATCH] + 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 - --- compiler/ncnv.pas | 59 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index 863292aa55..1c941bb7ef 100644 --- a/compiler/ncnv.pas +++ b/compiler/ncnv.pas @@ -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