* case statement inlining added

* fixed inlining of write()
  * switched statementnode left and right parts so the statements are
    processed in the correct order when getcopy is used. This is
    required for tempnodes
This commit is contained in:
peter 2002-11-27 02:37:12 +00:00
parent 0da515f669
commit 34e8266af4
6 changed files with 211 additions and 130 deletions

View File

@ -186,17 +186,17 @@ implementation
function internalstatements(var laststatement:tstatementnode):tblocknode;
begin
{ create dummy initial statement }
laststatement := cstatementnode.create(nil,cnothingnode.create);
laststatement := cstatementnode.create(cnothingnode.create,nil);
internalstatements := cblocknode.create(laststatement);
end;
procedure addstatement(var laststatement:tstatementnode;n:tnode);
begin
if assigned(laststatement.left) then
if assigned(laststatement.right) then
internalerror(200204201);
laststatement.left:=cstatementnode.create(nil,n);
laststatement:=tstatementnode(laststatement.left);
laststatement.right:=cstatementnode.create(n,nil);
laststatement:=tstatementnode(laststatement.right);
end;
@ -260,22 +260,22 @@ implementation
result:=nil;
resulttype:=voidtype;
{ right is the statement itself calln assignn or a complex one }
resulttypepass(right);
{ left is the statement itself calln assignn or a complex one }
resulttypepass(left);
if (not (cs_extsyntax in aktmoduleswitches)) and
assigned(right.resulttype.def) and
not((right.nodetype=calln) and
assigned(left.resulttype.def) and
not((left.nodetype=calln) and
{ don't complain when funcretrefnode is set, because then the
value is already used. And also not for constructors }
(assigned(tcallnode(right).funcretrefnode) or
(tcallnode(right).procdefinition.proctypeoption=potype_constructor))) and
not(is_void(right.resulttype.def)) then
(assigned(tcallnode(left).funcretrefnode) or
(tcallnode(left).procdefinition.proctypeoption=potype_constructor))) and
not(is_void(left.resulttype.def)) then
CGMessage(cg_e_illegal_expression);
if codegenerror then
exit;
{ left is the next in the list }
resulttypepass(left);
{ right is the next statement in the list }
resulttypepass(right);
if codegenerror then
exit;
end;
@ -285,28 +285,20 @@ implementation
result:=nil;
{ no temps over several statements }
rg.cleartempgen;
{ right is the statement itself calln assignn or a complex one }
firstpass(right);
if codegenerror then
exit;
location.loc:=right.location.loc;
registers32:=right.registers32;
registersfpu:=right.registersfpu;
{$ifdef SUPPORT_MMX}
registersmmx:=right.registersmmx;
{$endif SUPPORT_MMX}
{ left is the next in the list }
{ left is the statement itself calln assignn or a complex one }
firstpass(left);
if codegenerror then
exit;
if right.registers32>registers32 then
registers32:=right.registers32;
if right.registersfpu>registersfpu then
registersfpu:=right.registersfpu;
location.loc:=left.location.loc;
registers32:=left.registers32;
registersfpu:=left.registersfpu;
{$ifdef SUPPORT_MMX}
if right.registersmmx>registersmmx then
registersmmx:=right.registersmmx;
{$endif}
registersmmx:=left.registersmmx;
{$endif SUPPORT_MMX}
{ right is the next in the list }
firstpass(right);
if codegenerror then
exit;
end;
{$ifdef extdebug}
@ -319,11 +311,11 @@ implementation
writeln(',');
{ write the statement }
writenodeindention:=writenodeindention+' ';
writenode(right);
writenode(left);
writeln(')');
delete(writenodeindention,1,4);
{ go on with the next statement }
writenode(left);
writenode(right);
end;
{$endif}
@ -347,26 +339,26 @@ implementation
hp:=tstatementnode(left);
while assigned(hp) do
begin
if assigned(hp.right) then
if assigned(hp.left) then
begin
codegenerror:=false;
resulttypepass(hp.right);
resulttypepass(hp.left);
if (not (cs_extsyntax in aktmoduleswitches)) and
assigned(hp.right.resulttype.def) and
not((hp.right.nodetype=calln) and
assigned(hp.left.resulttype.def) and
not((hp.left.nodetype=calln) and
{ don't complain when funcretrefnode is set, because then the
value is already used. And also not for constructors }
(assigned(tcallnode(hp.right).funcretrefnode) or
(tcallnode(hp.right).procdefinition.proctypeoption=potype_constructor))) and
not(is_void(hp.right.resulttype.def)) then
CGMessagePos(hp.right.fileinfo,cg_e_illegal_expression);
(assigned(tcallnode(hp.left).funcretrefnode) or
(tcallnode(hp.left).procdefinition.proctypeoption=potype_constructor))) and
not(is_void(hp.left.resulttype.def)) then
CGMessagePos(hp.left.fileinfo,cg_e_illegal_expression);
{ the resulttype of the block is the last type that is
returned. Normally this is a voidtype. But when the
compiler inserts a block of multiple statements then the
last entry can return a value }
resulttype:=hp.right.resulttype;
resulttype:=hp.left.resulttype;
end;
hp:=tstatementnode(hp.left);
hp:=tstatementnode(hp.right);
end;
end;
@ -390,51 +382,51 @@ implementation
if {ret_in_acc(aktprocdef.rettype.def) and }
(is_ordinal(aktprocdef.rettype.def) or
is_smallset(aktprocdef.rettype.def)) and
assigned(hp.left) and
assigned(tstatementnode(hp.left).right) and
(tstatementnode(hp.left).right.nodetype=exitn) and
(hp.right.nodetype=assignn) and
assigned(hp.right) and
assigned(tstatementnode(hp.right).left) and
(tstatementnode(hp.right).left.nodetype=exitn) and
(hp.left.nodetype=assignn) and
{ !!!! this tbinarynode should be tassignmentnode }
(tbinarynode(hp.right).left.nodetype=funcretn) then
(tbinarynode(hp.left).left.nodetype=funcretn) then
begin
if assigned(texitnode(tstatementnode(hp.left).right).left) then
if assigned(texitnode(tstatementnode(hp.right).left).left) then
CGMessage(cg_n_inefficient_code)
else
begin
texitnode(tstatementnode(hp.left).right).left:=tassignmentnode(hp.right).right;
tassignmentnode(hp.right).right:=nil;
hp.right.free;
hp.right:=nil;
texitnode(tstatementnode(hp.right).left).left:=tassignmentnode(hp.left).right;
tassignmentnode(hp.left).right:=nil;
hp.left.free;
hp.left:=nil;
end;
end
{ warning if unreachable code occurs and elimate this }
else if (hp.right.nodetype in
else if (hp.left.nodetype in
[exitn,breakn,continuen,goton]) and
{ statement node (JM) }
assigned(hp.left) and
assigned(hp.right) and
{ kind of statement! (JM) }
assigned(tstatementnode(hp.left).right) and
(tstatementnode(hp.left).right.nodetype<>labeln) then
assigned(tstatementnode(hp.right).left) and
(tstatementnode(hp.right).left.nodetype<>labeln) then
begin
{ use correct line number }
aktfilepos:=hp.left.fileinfo;
hp.left.free;
hp.left:=nil;
aktfilepos:=hp.right.fileinfo;
hp.right.free;
hp.right:=nil;
CGMessage(cg_w_unreachable_code);
{ old lines }
aktfilepos:=hp.right.fileinfo;
aktfilepos:=hp.left.fileinfo;
end;
end;
if assigned(hp.right) then
if assigned(hp.left) then
begin
rg.cleartempgen;
codegenerror:=false;
firstpass(hp.right);
firstpass(hp.left);
hp.registers32:=hp.right.registers32;
hp.registersfpu:=hp.right.registersfpu;
hp.registers32:=hp.left.registers32;
hp.registersfpu:=hp.left.registersfpu;
{$ifdef SUPPORT_MMX}
hp.registersmmx:=hp.right.registersmmx;
hp.registersmmx:=hp.left.registersmmx;
{$endif SUPPORT_MMX}
end
else
@ -450,7 +442,7 @@ implementation
{$endif}
location.loc:=hp.location.loc;
inc(count);
hp:=tstatementnode(hp.left);
hp:=tstatementnode(hp.right);
end;
end;
@ -464,9 +456,9 @@ implementation
hp:=Tstatementnode(left);
while assigned(hp) do
begin
if hp.right.track_state_pass(exec_known) then
if hp.left.track_state_pass(exec_known) then
track_state_pass:=true;
hp:=Tstatementnode(hp.left);
hp:=Tstatementnode(hp.right);
end;
end;
{$endif state_tracking}
@ -592,6 +584,11 @@ implementation
fillchar(n.tempinfo^,sizeof(n.tempinfo^),0);
n.tempinfo^.restype := tempinfo^.restype;
{ when the tempinfo has already a hookoncopy then it is not
reset by a tempdeletenode }
if assigned(tempinfo^.hookoncopy) then
internalerror(200211262);
{ signal the temprefs that the temp they point to has been copied, }
{ so that if the refs get copied as well, they can hook themselves }
{ to the copy of the temp }
@ -723,6 +720,8 @@ implementation
begin
{ hook the tempdeletenode to the copied temp }
n.tempinfo := tempinfo^.hookoncopy;
{ the temp shall not be used, reset hookoncopy }
tempinfo^.hookoncopy:=nil;
end
else
{ if the temp we refer to hasn't been copied, we have a }
@ -767,7 +766,14 @@ begin
end.
{
$Log$
Revision 1.37 2002-11-25 17:43:17 peter
Revision 1.38 2002-11-27 02:37:12 peter
* case statement inlining added
* fixed inlining of write()
* switched statementnode left and right parts so the statements are
processed in the correct order when getcopy is used. This is
required for tempnodes
Revision 1.37 2002/11/25 17:43:17 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once

View File

@ -90,14 +90,14 @@ interface
hp:=self;
while assigned(hp) do
begin
if assigned(tstatementnode(hp).right) then
if assigned(tstatementnode(hp).left) then
begin
rg.cleartempgen;
secondpass(tstatementnode(hp).right);
secondpass(tstatementnode(hp).left);
{ Compiler inserted blocks can return values }
location_copy(location,tstatementnode(hp).right.location);
location_copy(location,tstatementnode(hp).left.location);
end;
hp:=tstatementnode(hp).left;
hp:=tstatementnode(hp).right;
end;
end;
@ -288,7 +288,14 @@ begin
end.
{
$Log$
Revision 1.26 2002-11-17 16:31:56 carl
Revision 1.27 2002-11-27 02:37:13 peter
* case statement inlining added
* fixed inlining of write()
* switched statementnode left and right parts so the statements are
processed in the correct order when getcopy is used. This is
required for tempnodes
Revision 1.26 2002/11/17 16:31:56 carl
* memory optimization (3-4%) : cleanup of tai fields,
cleanup of tdef and tsym fields.
* make it work for m68k

View File

@ -90,7 +90,7 @@ implementation
symconst,symdef,defutil,
paramgr,
pass_2,
ncon,
nbas,ncon,nflw,
tgobj,ncgutil,regvars,rgobj,cpuinfo;
@ -837,6 +837,29 @@ implementation
end;
procedure ReLabel(var p:tasmsymbol);
begin
if p.defbind = AB_LOCAL then
begin
if not assigned(p.altsymbol) then
objectlibrary.GenerateAltSymbol(p);
p:=p.altsymbol;
p.increfs;
end;
end;
procedure relabelcaserecord(p : pcaserecord);
begin
Relabel(p^.statement);
Relabel(p^._at);
if assigned(p^.greater) then
relabelcaserecord(p^.greater);
if assigned(p^.less) then
relabelcaserecord(p^.less);
end;
procedure tcgcasenode.pass_2;
var
lv,hv,
@ -847,8 +870,16 @@ implementation
isjump : boolean;
max_dist,
dist : cardinal;
hp : tnode;
hp : tstatementnode;
begin
{ Relabel for inlining? }
if inlining_procedure and
assigned(nodes) then
begin
objectlibrary.CreateUsedAsmSymbolList;
relabelcaserecord(nodes);
end;
objectlibrary.getlabel(endlabel);
objectlibrary.getlabel(elselabel);
with_sign:=is_signed(left.resulttype.def);
@ -983,16 +1014,23 @@ implementation
rg.ungetregister(exprasmlist,hregister);
{ now generate the instructions }
hp:=right;
hp:=tstatementnode(right);
while assigned(hp) do
begin
rg.cleartempgen;
secondpass(tbinarynode(hp).right);
{ relabel when inlining }
if inlining_procedure then
begin
if hp.left.nodetype<>labeln then
internalerror(200211261);
Relabel(tlabelnode(hp.left).labelnr);
end;
secondpass(hp.left);
{ don't come back to case line }
aktfilepos:=exprasmList.getlasttaifilepos^;
load_all_regvars(exprasmlist);
cg.a_jmp_always(exprasmlist,endlabel);
hp:=tbinarynode(hp).left;
hp:=tstatementnode(hp.right);
end;
cg.a_label(exprasmlist,elselabel);
{ ...and the else block }
@ -1003,6 +1041,15 @@ implementation
load_all_regvars(exprasmlist);
end;
cg.a_label(exprasmlist,endlabel);
{ Remove relabels for inlining }
if inlining_procedure and
assigned(nodes) then
begin
{ restore used symbols }
objectlibrary.UsedAsmSymbolListResetAltSym;
objectlibrary.DestroyUsedAsmSymbolList;
end;
end;
@ -1015,7 +1062,14 @@ begin
end.
{
$Log$
Revision 1.23 2002-11-25 17:43:18 peter
Revision 1.24 2002-11-27 02:37:13 peter
* case statement inlining added
* fixed inlining of write()
* switched statementnode left and right parts so the statements are
processed in the correct order when getcopy is used. This is
required for tempnodes
Revision 1.23 2002/11/25 17:43:18 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once

View File

@ -424,7 +424,7 @@ implementation
addstatement(newstatement,
cassignmentnode.create(ctemprefnode.create(filetemp),
caddrnode.create(filepara.left)));
resulttypepass(newstatement.right);
resulttypepass(newstatement.left);
{ create a new fileparameter as follows: file_type(temp^) }
{ (so that we pass the value and not the address of the temp }
{ to the read/write routine) }
@ -899,8 +899,8 @@ implementation
{ create the blocknode which will hold the generated statements + }
{ an initial dummy statement }
newstatement := cstatementnode.create(nil,cnothingnode.create);
newblock := cblocknode.create(newstatement);
newblock:=internalstatements(newstatement);
{ do we need a temp for code? Yes, if no code specified, or if }
{ code is not a 32bit parameter (we already checked whether the }
@ -909,8 +909,7 @@ implementation
(torddef(codepara.resulttype.def).typ in [u8bit,u16bit,s8bit,s16bit]) then
begin
tempcode := ctempcreatenode.create(s32bittype,4,true);
newstatement.left := cstatementnode.create(nil,tempcode);
newstatement := tstatementnode(newstatement.left);
addstatement(newstatement,tempcode);
{ set the resulttype of the temp (needed to be able to get }
{ the resulttype of the tempref used in the new code para) }
resulttypepass(tnode(tempcode));
@ -970,7 +969,8 @@ implementation
{ the shortstring-longint val routine by default }
if (sourcepara.resulttype.def.deftype = stringdef) then
procname := procname + tstringdef(sourcepara.resulttype.def).stringtypname
else procname := procname + 'shortstr';
else
procname := procname + 'shortstr';
{ set up the correct parameters for the call: the code para... }
newparas := codepara;
@ -985,9 +985,8 @@ implementation
{ create the call and assign the result to dest }
{ (val helpers are functions) }
{ the assignment will take care of rangechecking }
newstatement.left := cstatementnode.create(nil,cassignmentnode.create(
addstatement(newstatement,cassignmentnode.create(
destpara.left,ccallnode.createintern(procname,newparas)));
newstatement := tstatementnode(newstatement.left);
{ dispose of the enclosing paranode of the destination }
destpara.left := nil;
@ -997,19 +996,13 @@ implementation
{ check if we used a temp for code and whether we have to store }
{ it to the real code parameter }
if assigned(orgcode) then
begin
newstatement.left := cstatementnode.create(nil,cassignmentnode.create(
orgcode,ctemprefnode.create(tempcode)));
newstatement := tstatementnode(newstatement.left);
end;
addstatement(newstatement,cassignmentnode.create(
orgcode,
ctemprefnode.create(tempcode)));
{ release the temp if we allocated one }
if assigned(tempcode) then
begin
newstatement.left := cstatementnode.create(nil,
ctempdeletenode.create(tempcode));
newstatement := tstatementnode(newstatement.left);
end;
addstatement(newstatement,ctempdeletenode.create(tempcode));
{ free the errornode }
result.free;
@ -2408,7 +2401,14 @@ begin
end.
{
$Log$
Revision 1.98 2002-11-25 17:43:19 peter
Revision 1.99 2002-11-27 02:37:13 peter
* case statement inlining added
* fixed inlining of write()
* switched statementnode left and right parts so the statements are
processed in the correct order when getcopy is used. This is
required for tempnodes
Revision 1.98 2002/11/25 17:43:19 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once

View File

@ -118,7 +118,7 @@ implementation
verbose,
symconst,symdef,symsym,defutil,defcmp,
htypechk,pass_1,
ncnv,ncon,cpubase,nld,rgobj,cgbase;
nbas,ncnv,ncon,cpubase,nld,rgobj,cgbase;
function gencasenode(l,r : tnode;nodes : pcaserecord) : tnode;
@ -265,17 +265,17 @@ implementation
elements.with the in operator.
}
if (
(left.resulttype.def.deftype = orddef) and not
(left.resulttype.def.deftype = orddef) and not
(torddef(left.resulttype.def).typ in [s8bit,u8bit,uchar,bool8bit])
)
)
or
(
(left.resulttype.def.deftype = enumdef)
(left.resulttype.def.deftype = enumdef)
and (tenumdef(left.resulttype.def).size <> 1)
)
then
Message(type_h_in_range_check);
{ type conversion/check }
if assigned(tsetdef(right.resulttype.def).elementtype.def) then
begin
@ -587,7 +587,7 @@ implementation
function tcasenode.pass_1 : tnode;
var
old_t_times : longint;
hp : tbinarynode;
hp : tstatementnode;
begin
result:=nil;
{ evalutes the case expression }
@ -613,23 +613,23 @@ implementation
rg.t_times:=1;
end;
{ first case }
hp:=tbinarynode(right);
hp:=tstatementnode(right);
while assigned(hp) do
begin
rg.cleartempgen;
firstpass(hp.right);
firstpass(hp.left);
{ searchs max registers }
if hp.right.registers32>registers32 then
registers32:=hp.right.registers32;
if hp.right.registersfpu>registersfpu then
registersfpu:=hp.right.registersfpu;
if hp.left.registers32>registers32 then
registers32:=hp.left.registers32;
if hp.left.registersfpu>registersfpu then
registersfpu:=hp.left.registersfpu;
{$ifdef SUPPORT_MMX}
if hp.right.registersmmx>registersmmx then
registersmmx:=hp.right.registersmmx;
if hp.left.registersmmx>registersmmx then
registersmmx:=hp.left.registersmmx;
{$endif SUPPORT_MMX}
hp:=tbinarynode(hp.left);
hp:=tstatementnode(hp.right);
end;
{ may be handle else tree }
@ -709,7 +709,14 @@ begin
end.
{
$Log$
Revision 1.36 2002-11-26 21:52:38 carl
Revision 1.37 2002-11-27 02:37:14 peter
* case statement inlining added
* fixed inlining of write()
* switched statementnode left and right parts so the statements are
processed in the correct order when getcopy is used. This is
required for tempnodes
Revision 1.36 2002/11/26 21:52:38 carl
+ hint for in operator with non byte sized operand
Revision 1.35 2002/11/25 17:43:21 peter

View File

@ -105,13 +105,13 @@ implementation
begin
if first=nil then
begin
last:=cstatementnode.create(nil,statement);
last:=cstatementnode.create(statement,nil);
first:=last;
end
else
begin
last.left:=cstatementnode.create(nil,statement);
last:=tstatementnode(last.left);
last.right:=cstatementnode.create(statement,nil);
last:=tstatementnode(last.right);
end;
if not try_to_consume(_SEMICOLON) then
break;
@ -274,7 +274,7 @@ implementation
p:=clabelnode.createcase(aktcaselabel,statement);
{ concats instruction }
instruc:=cstatementnode.create(instruc,p);
instruc:=cstatementnode.create(p,instruc);
if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
consume(_SEMICOLON);
@ -315,13 +315,13 @@ implementation
begin
if first=nil then
begin
last:=cstatementnode.create(nil,statement);
last:=cstatementnode.create(statement,nil);
first:=last;
end
else
begin
tstatementnode(last).left:=cstatementnode.create(nil,statement);
last:=tstatementnode(last).left;
tstatementnode(last).right:=cstatementnode.create(statement,nil);
last:=tstatementnode(last).right;
end;
if not try_to_consume(_SEMICOLON) then
break;
@ -541,13 +541,13 @@ implementation
begin
if first=nil then
begin
last:=cstatementnode.create(nil,statement);
last:=cstatementnode.create(statement,nil);
first:=last;
end
else
begin
tstatementnode(last).left:=cstatementnode.create(nil,statement);
last:=tstatementnode(last).left;
tstatementnode(last).right:=cstatementnode.create(statement,nil);
last:=tstatementnode(last).right;
end;
if not try_to_consume(_SEMICOLON) then
break;
@ -961,13 +961,13 @@ implementation
begin
if first=nil then
begin
last:=cstatementnode.create(nil,statement);
last:=cstatementnode.create(statement,nil);
first:=last;
end
else
begin
tstatementnode(last).left:=cstatementnode.create(nil,statement);
last:=tstatementnode(last).left;
tstatementnode(last).right:=cstatementnode.create(statement,nil);
last:=tstatementnode(last).right;
end;
if (token in [_END,_FINALIZATION]) then
break
@ -1147,7 +1147,14 @@ implementation
end.
{
$Log$
Revision 1.80 2002-11-25 17:43:22 peter
Revision 1.81 2002-11-27 02:37:14 peter
* case statement inlining added
* fixed inlining of write()
* switched statementnode left and right parts so the statements are
processed in the correct order when getcopy is used. This is
required for tempnodes
Revision 1.80 2002/11/25 17:43:22 peter
* splitted defbase in defutil,symutil,defcmp
* merged isconvertable and is_equal into compare_defs(_ext)
* made operator search faster by walking the list only once