* generate better code for length(<dyn. type>)=0, resolves #36060

git-svn-id: trunk@43272 -
This commit is contained in:
florian 2019-10-20 13:03:45 +00:00
parent e251c8e2ab
commit e80eee5da5
2 changed files with 75 additions and 3 deletions

View File

@ -22,6 +22,7 @@
unit nadd;
{$i fpcdefs.inc}
{$modeswitch nestedprocvars}
{ define addstringopt}
@ -446,6 +447,35 @@ implementation
result:=true;
end;
function IsLengthZero(n1,n2 : tnode) : Boolean;
begin
result:=is_inlinefunction(n1,in_length_x) and is_constintvalue(n2,0) and not(is_shortstring(tinlinenode(n1).left.resultdef));
end;
function TransformLengthZero(n1,n2 : tnode) : tnode;
var
len : Tconstexprint;
begin
if is_dynamic_array(tinlinenode(n1).left.resultdef) then
len:=-1
else
len:=0;
result:=caddnode.create_internal(orn,
caddnode.create_internal(equaln,ctypeconvnode.create_internal(tinlinenode(n1).left.getcopy,voidpointertype),
cpointerconstnode.create(0,voidpointertype)),
caddnode.create_internal(equaln,
ctypeconvnode.create_internal(
cderefnode.create(
caddnode.create_internal(subn,ctypeconvnode.create_internal(tinlinenode(n1).left.getcopy,voidpointertype),
cordconstnode.create(0,sizesinttype,false))
),sizesinttype
),
cordconstnode.create(len,sizesinttype,false))
);
end;
var
t , vl: tnode;
lt,rt : tnodetype;
@ -1172,7 +1202,9 @@ implementation
else
;
end;
end;
end
else if (nodetype=equaln) and MatchAndTransformNodesCommutative(left,right,@IsLengthZero,@TransformLengthZero,Result) then
exit;
end;
{ using sqr(x) for reals instead of x*x might reduces register pressure and/or

View File

@ -22,13 +22,14 @@
unit nutils;
{$i fpcdefs.inc}
{$modeswitch nestedprocvars}
interface
uses
globtype,constexp,
symtype,symsym,symbase,symtable,
node;
node,compinnr;
const
NODE_COMPLEXITY_INF = 255;
@ -168,10 +169,24 @@ interface
if it is not an orn/andn with boolean operans, the result is undefined }
function doshortbooleval(p : tnode) : Boolean;
{ returns true if the node has the int value l }
function is_constintvalue(p : tnode;l : Tconstexprint) : Boolean;
{ returns true if the node is an inline node of type i }
function is_inlinefunction(p : tnode;i : tinlinenumber) : Boolean;
type
TMatchProc2 = function(n1,n2 : tnode) : Boolean is nested;
TTransformProc2 = function(n1,n2 : tnode) : tnode is nested;
{ calls matchproc with n1 and n2 as parameters, if it returns true, transformproc is called, does the same with the nodes swapped,
the result of transformproc is assigned to res }
function MatchAndTransformNodesCommutative(n1,n2 : tnode;matchproc : TMatchProc2;transformproc : TTransformProc2;var res : tnode) : Boolean;
implementation
uses
cutils,verbose,globals,compinnr,
cutils,verbose,globals,
symconst,symdef,
defcmp,defutil,
nbas,ncon,ncnv,nld,nflw,nset,ncal,nadd,nmem,ninl,
@ -1530,4 +1545,29 @@ implementation
Result:=(p.nodetype in [orn,andn]) and ((nf_short_bool in taddnode(p).flags) or not(cs_full_boolean_eval in p.localswitches));
end;
function is_constintvalue(p: tnode; l: Tconstexprint): Boolean;
begin
Result:=is_constintnode(p) and (tordconstnode(p).value=l);
end;
function is_inlinefunction(p: tnode; i: tinlinenumber): Boolean;
begin
Result:=(p.nodetype=inlinen) and (tinlinenode(p).inlinenumber=i);
end;
function MatchAndTransformNodesCommutative(n1,n2 : tnode;matchproc : TMatchProc2;transformproc : TTransformProc2;var res : tnode) : Boolean;
begin
res:=nil;
result:=true;
if matchproc(n1,n2) then
res:=transformproc(n1,n2)
else if matchproc(n2,n1) then
res:=transformproc(n2,n1)
else
result:=false;
end;
end.