mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-26 21:30:38 +02:00
+ first basically working (not all node types yet) dfa implementation determining life information
git-svn-id: trunk@7294 -
This commit is contained in:
parent
31a34e03c2
commit
45cda67f3f
@ -914,6 +914,24 @@ implementation
|
|||||||
eq:=te_convert_l1;
|
eq:=te_convert_l1;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{
|
||||||
|
enumdef :
|
||||||
|
begin
|
||||||
|
{ allow explicit typecasts from enums to pointer.
|
||||||
|
Support for delphi compatibility
|
||||||
|
}
|
||||||
|
if (eq=te_incompatible) and
|
||||||
|
(((cdo_explicit in cdoptions) and
|
||||||
|
(m_delphi in current_settings.modeswitches)
|
||||||
|
) or
|
||||||
|
(cdo_internal in cdoptions)
|
||||||
|
) then
|
||||||
|
begin
|
||||||
|
doconv:=tc_int_2_int;
|
||||||
|
eq:=te_convert_l1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
}
|
||||||
arraydef :
|
arraydef :
|
||||||
begin
|
begin
|
||||||
{ string constant (which can be part of array constructor)
|
{ string constant (which can be part of array constructor)
|
||||||
|
@ -153,7 +153,8 @@ interface
|
|||||||
toptimizerswitch = (cs_opt_none,
|
toptimizerswitch = (cs_opt_none,
|
||||||
cs_opt_level1,cs_opt_level2,cs_opt_level3,
|
cs_opt_level1,cs_opt_level2,cs_opt_level3,
|
||||||
cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
|
cs_opt_regvar,cs_opt_uncertain,cs_opt_size,cs_opt_stackframe,
|
||||||
cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse
|
cs_opt_peephole,cs_opt_asmcse,cs_opt_loopunroll,cs_opt_tailrecursion,cs_opt_nodecse,
|
||||||
|
cs_opt_nodedfa
|
||||||
);
|
);
|
||||||
toptimizerswitches = set of toptimizerswitch;
|
toptimizerswitches = set of toptimizerswitch;
|
||||||
|
|
||||||
@ -161,7 +162,7 @@ interface
|
|||||||
OptimizerSwitchStr : array[toptimizerswitch] of string[10] = ('',
|
OptimizerSwitchStr : array[toptimizerswitch] of string[10] = ('',
|
||||||
'LEVEL1','LEVEL2','LEVEL3',
|
'LEVEL1','LEVEL2','LEVEL3',
|
||||||
'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
|
'REGVAR','UNCERTAIN','SIZE','STACKFRAME',
|
||||||
'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE'
|
'PEEPHOLE','ASMCSE','LOOPUNROLL','TAILREC','CSE','DFA'
|
||||||
);
|
);
|
||||||
|
|
||||||
{ switches being applied to all CPUs at the given level }
|
{ switches being applied to all CPUs at the given level }
|
||||||
|
@ -32,6 +32,7 @@ unit optbase;
|
|||||||
{ this should maybe replaced by a spare set,
|
{ this should maybe replaced by a spare set,
|
||||||
using a dyn. array makes assignments cheap }
|
using a dyn. array makes assignments cheap }
|
||||||
tdfaset = array of byte;
|
tdfaset = array of byte;
|
||||||
|
PDFASet = ^TDFASet;
|
||||||
|
|
||||||
toptinfo = record
|
toptinfo = record
|
||||||
{ index of the current node inside the dfa sets, aword(-1) if no entry }
|
{ index of the current node inside the dfa sets, aword(-1) if no entry }
|
||||||
@ -44,31 +45,69 @@ unit optbase;
|
|||||||
poptinfo = ^toptinfo;
|
poptinfo = ^toptinfo;
|
||||||
|
|
||||||
{ basic set operations for dfa sets }
|
{ basic set operations for dfa sets }
|
||||||
procedure TDFASetInclude(var s : tdfaset;e : integer);
|
|
||||||
procedure TDFASetExclude(var s : tdfaset;e : integer);
|
{ add e to s }
|
||||||
function TDFASetIn(const s : tdfaset;e : integer) : boolean;
|
procedure DFASetInclude(var s : tdfaset;e : integer);
|
||||||
procedure TDFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
|
|
||||||
procedure TDFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
|
{ add s to d }
|
||||||
procedure TDFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
|
procedure DFASetIncludeSet(var d : tdfaset;const s : tdfaset);
|
||||||
|
|
||||||
|
{ remove e from s }
|
||||||
|
procedure DFASetExclude(var s : tdfaset;e : integer);
|
||||||
|
|
||||||
|
{ test if s contains e }
|
||||||
|
function DFASetIn(const s : tdfaset;e : integer) : boolean;
|
||||||
|
|
||||||
|
{ d:=s1+s2; }
|
||||||
|
procedure DFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
|
||||||
|
{ d:=s1*s2; }
|
||||||
|
procedure DFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
|
||||||
|
{ d:=s1-s2; }
|
||||||
|
procedure DFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
|
||||||
|
{ s1<>s2; }
|
||||||
function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
|
function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
|
||||||
|
|
||||||
|
{ output DFA set }
|
||||||
|
procedure PrintDFASet(var f : text;s : TDFASet);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
cutils;
|
cutils;
|
||||||
|
|
||||||
procedure TDFASetInclude(var s : tdfaset;e : integer);
|
procedure DFASetInclude(var s : tdfaset;e : integer);
|
||||||
var
|
var
|
||||||
|
i,
|
||||||
|
oldhigh,
|
||||||
e8 : Integer;
|
e8 : Integer;
|
||||||
begin
|
begin
|
||||||
e8:=e div 8;
|
e8:=e div 8;
|
||||||
if e8>high(s) then
|
if e8>high(s) then
|
||||||
SetLength(s,e8+1);
|
begin
|
||||||
|
oldhigh:=high(s);
|
||||||
|
SetLength(s,e8+1);
|
||||||
|
for i:=oldhigh+1 to high(s) do
|
||||||
|
s[i]:=0;
|
||||||
|
end;
|
||||||
s[e8]:=s[e8] or (1 shl (e mod 8));
|
s[e8]:=s[e8] or (1 shl (e mod 8));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TDFASetExclude(var s : tdfaset;e : integer);
|
procedure DFASetIncludeSet(var d : tdfaset;const s : tdfaset);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
if length(s)>length(d) then
|
||||||
|
SetLength(d,length(s));
|
||||||
|
for i:=0 to high(s) do
|
||||||
|
d[i]:=d[i] or s[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure DFASetExclude(var s : tdfaset;e : integer);
|
||||||
var
|
var
|
||||||
e8 : Integer;
|
e8 : Integer;
|
||||||
begin
|
begin
|
||||||
@ -79,7 +118,7 @@ unit optbase;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TDFASetIn(const s : tdfaset;e : integer) : boolean;
|
function DFASetIn(const s : tdfaset;e : integer) : boolean;
|
||||||
var
|
var
|
||||||
e8 : Integer;
|
e8 : Integer;
|
||||||
begin
|
begin
|
||||||
@ -91,7 +130,7 @@ unit optbase;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TDFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
|
procedure DFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
begin
|
begin
|
||||||
@ -103,7 +142,7 @@ unit optbase;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TDFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
|
procedure DFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
begin
|
begin
|
||||||
@ -113,13 +152,16 @@ unit optbase;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TDFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
|
procedure DFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
var
|
var
|
||||||
i : integer;
|
i : integer;
|
||||||
begin
|
begin
|
||||||
SetLength(d,min(Length(s1),Length(s2)));
|
SetLength(d,length(s1));
|
||||||
for i:=0 to min(high(s1),high(s2)) do
|
for i:=0 to high(d) do
|
||||||
d[i]:=s1[i] and not(s2[i]);
|
if i>high(s2) then
|
||||||
|
d[i]:=s1[i]
|
||||||
|
else
|
||||||
|
d[i]:=s1[i] and not(s2[i]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -152,4 +194,24 @@ unit optbase;
|
|||||||
result:=false;
|
result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure PrintDFASet(var f : text;s : TDFASet);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
first : boolean;
|
||||||
|
begin
|
||||||
|
first:=true;
|
||||||
|
for i:=0 to Length(s)*8 do
|
||||||
|
begin
|
||||||
|
if DFASetIn(s,i) then
|
||||||
|
begin
|
||||||
|
if not(first) then
|
||||||
|
write(f,',');
|
||||||
|
write(f,i);
|
||||||
|
first:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
****************************************************************************
|
****************************************************************************
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ $define DEBUG_DFA}
|
||||||
|
|
||||||
|
{ this unit implements routines to perform dfa }
|
||||||
unit optdfa;
|
unit optdfa;
|
||||||
|
|
||||||
{$i fpcdefs.inc}
|
{$i fpcdefs.inc}
|
||||||
@ -32,18 +36,21 @@ unit optdfa;
|
|||||||
if the tree has been changed without updating dfa }
|
if the tree has been changed without updating dfa }
|
||||||
procedure resetdfainfo(node : tnode);
|
procedure resetdfainfo(node : tnode);
|
||||||
|
|
||||||
procedure createoptinfo(node : tnode);
|
procedure createdfainfo(node : tnode);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
globtype,globals,
|
globtype,globals,
|
||||||
|
verbose,
|
||||||
cpuinfo,
|
cpuinfo,
|
||||||
|
symdef,
|
||||||
nutils,
|
nutils,
|
||||||
nbas,nflw,ncon,ninl,ncal,
|
nbas,nflw,ncon,ninl,ncal,
|
||||||
optutils;
|
optbase,optutils;
|
||||||
|
|
||||||
|
|
||||||
|
(*
|
||||||
function initnodes(var n:tnode; arg: pointer) : foreachnoderesult;
|
function initnodes(var n:tnode; arg: pointer) : foreachnoderesult;
|
||||||
begin
|
begin
|
||||||
{ node worth to add? }
|
{ node worth to add? }
|
||||||
@ -56,7 +63,7 @@ unit optdfa;
|
|||||||
else
|
else
|
||||||
result:=fen_norecurse_false;
|
result:=fen_norecurse_false;
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
{
|
{
|
||||||
x:=f; read: [f]
|
x:=f; read: [f]
|
||||||
@ -85,61 +92,104 @@ unit optdfa;
|
|||||||
|
|
||||||
type
|
type
|
||||||
tdfainfo = record
|
tdfainfo = record
|
||||||
use : TDFASet;
|
use : PDFASet;
|
||||||
def : TDFASet;
|
def : PDFASet;
|
||||||
map : TIndexedNodeSet
|
map : TIndexedNodeSet
|
||||||
end;
|
end;
|
||||||
|
pdfainfo = ^tdfainfo;
|
||||||
|
|
||||||
procedure AddDefUse(s : TDFASet;m : ;n : tnode);
|
function AddDefUse(var n: tnode; arg: pointer): foreachnoderesult;
|
||||||
begin
|
begin
|
||||||
while true do
|
case n.nodetype of
|
||||||
begin
|
loadn:
|
||||||
case n.nodetype of
|
begin
|
||||||
typeconvn:
|
pdfainfo(arg)^.map.Add(n);
|
||||||
n:=ttypeconvnode(n).left;
|
if nf_write in n.flags then
|
||||||
loadn:
|
DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
|
||||||
begin
|
|
||||||
m.Add(n);
|
|
||||||
TDFASetInclude(s,n.optinfo^.index);
|
|
||||||
end;
|
|
||||||
else
|
else
|
||||||
internalerror(2007050601);
|
DFASetInclude(pdfainfo(arg)^.use^,n.optinfo^.index);
|
||||||
|
{
|
||||||
|
write('Use Set: ');
|
||||||
|
PrintDFASet(output,pdfainfo(arg)^.use^);
|
||||||
|
write(' Def Set: ');
|
||||||
|
PrintDFASet(output,pdfainfo(arg)^.def^);
|
||||||
|
writeln;
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
result:=fen_false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure CreateLifeInfo(node : tnode);
|
procedure CreateLifeInfo(node : tnode;map : TIndexedNodeSet);
|
||||||
|
|
||||||
var
|
var
|
||||||
changed : boolean;
|
changed : boolean;
|
||||||
|
|
||||||
procedure CreateInfo(node : tnode);
|
procedure CreateInfo(node : tnode);
|
||||||
|
|
||||||
|
{ update life entry of a node with l, set changed if this changes
|
||||||
|
life info for the node
|
||||||
|
}
|
||||||
procedure updatelifeinfo(n : tnode;l : TDFASet);
|
procedure updatelifeinfo(n : tnode;l : TDFASet);
|
||||||
|
var
|
||||||
|
b : boolean;
|
||||||
begin
|
begin
|
||||||
changed:=changed or DFASetNotEqual(l,n.life);
|
b:=DFASetNotEqual(l,n.optinfo^.life);
|
||||||
node.life:=l;
|
{
|
||||||
|
if b then
|
||||||
|
begin
|
||||||
|
printnode(output,n);
|
||||||
|
printdfaset(output,l);
|
||||||
|
writeln;
|
||||||
|
printdfaset(output,n.optinfo^.life);
|
||||||
|
writeln;
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
changed:=changed or b;
|
||||||
|
node.optinfo^.life:=l;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure calclife(n : tnode);
|
procedure calclife(n : tnode);
|
||||||
var
|
var
|
||||||
l : TDFANode;
|
l : TDFASet;
|
||||||
begin
|
begin
|
||||||
if assigned(successor) then
|
n.allocoptinfo;
|
||||||
|
if assigned(n.successor) then
|
||||||
begin
|
begin
|
||||||
DFASetDiff(l,successor.optinfo^.life,n.optinfo^.def);
|
{
|
||||||
|
write('Successor Life: ');
|
||||||
|
printdfaset(output,n.successor.optinfo^.life);
|
||||||
|
writeln;
|
||||||
|
write('Def.');
|
||||||
|
printdfaset(output,n.optinfo^.def);
|
||||||
|
writeln;
|
||||||
|
}
|
||||||
|
{ ensure we can access optinfo }
|
||||||
|
DFASetDiff(l,n.successor.optinfo^.life,n.optinfo^.def);
|
||||||
|
{
|
||||||
|
printdfaset(output,l);
|
||||||
|
writeln;
|
||||||
|
}
|
||||||
DFASetIncludeSet(l,n.optinfo^.use);
|
DFASetIncludeSet(l,n.optinfo^.use);
|
||||||
updatelifeinfo(n,l);
|
DFASetIncludeSet(l,n.optinfo^.life);
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
l:=n.optinfo^.use;
|
||||||
|
updatelifeinfo(n,l);
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
dfainfo : tdfainfo;
|
dfainfo : tdfainfo;
|
||||||
|
l : TDFASet;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
if node=nil then
|
||||||
|
exit;
|
||||||
|
|
||||||
if nf_processing in node.flags then
|
if nf_processing in node.flags then
|
||||||
exit;
|
exit;
|
||||||
include(node,nf_processing);
|
include(node.flags,nf_processing);
|
||||||
|
|
||||||
if assigned(node.successor) then
|
if assigned(node.successor) then
|
||||||
CreateInfo(node.successor);
|
CreateInfo(node.successor);
|
||||||
@ -147,20 +197,36 @@ unit optdfa;
|
|||||||
{ life:=succesorlive-definition+use }
|
{ life:=succesorlive-definition+use }
|
||||||
|
|
||||||
case node.nodetype of
|
case node.nodetype of
|
||||||
whilen:
|
whilerepeatn:
|
||||||
begin
|
begin
|
||||||
{ first, do things as usual, get life information from the successor }
|
calclife(node);
|
||||||
|
if lnf_testatbegin in twhilerepeatnode(node).loopflags then
|
||||||
|
begin
|
||||||
|
{ first, do things as usual, get life information from the successor }
|
||||||
|
node.allocoptinfo;
|
||||||
|
if not(assigned(node.optinfo^.def)) and
|
||||||
|
not(assigned(node.optinfo^.use)) then
|
||||||
|
begin
|
||||||
|
dfainfo.use:=@node.optinfo^.use;
|
||||||
|
dfainfo.def:=@node.optinfo^.def;
|
||||||
|
dfainfo.map:=map;
|
||||||
|
foreachnodestatic(pm_postprocess,twhilerepeatnode(node).left,@AddDefUse,@dfainfo);
|
||||||
|
end;
|
||||||
|
calclife(node);
|
||||||
|
|
||||||
{ life:=succesorlive-definition+use }
|
{ now iterate through the loop }
|
||||||
|
CreateInfo(twhilerepeatnode(node).right);
|
||||||
|
|
||||||
{ now iterate through the loop }
|
{ update while node }
|
||||||
CreateInfo(twhilenode(node).left);
|
{ life:=life+use+right.life }
|
||||||
|
l:=node.optinfo^.life;
|
||||||
|
DFASetIncludeSet(l,node.optinfo^.use);
|
||||||
|
DFASetIncludeSet(l,twhilerepeatnode(node).right.optinfo^.life);
|
||||||
|
UpdateLifeInfo(node,l);
|
||||||
|
|
||||||
{ update while node }
|
{ ... and a second iteration for fast convergence }
|
||||||
{ life:=life+left.life }
|
CreateInfo(twhilerepeatnode(node).right);
|
||||||
|
end;
|
||||||
{ ... and a second iteration for fast convergence }
|
|
||||||
CreateInfo(twhilenode(node).left);
|
|
||||||
end;
|
end;
|
||||||
statementn:
|
statementn:
|
||||||
begin
|
begin
|
||||||
@ -168,30 +234,58 @@ unit optdfa;
|
|||||||
case tstatementnode(node).statement.nodetype of
|
case tstatementnode(node).statement.nodetype of
|
||||||
assignn:
|
assignn:
|
||||||
begin
|
begin
|
||||||
tstatementnode(node).allocoptinfo;
|
node.allocoptinfo;
|
||||||
if not(assigned(tstatementnode(node).optinfo^.def)) or
|
if not(assigned(node.optinfo^.def)) and
|
||||||
not(assigned(tstatementnode(node).optinfo^.use)) then
|
not(assigned(node.optinfo^.use)) then
|
||||||
begin
|
begin
|
||||||
dfainfo.use:=tstatementnode(node).optinfo^.use;
|
dfainfo.use:=@node.optinfo^.use;
|
||||||
dfainfo.def:=tstatementnode(node).optinfo^.def;
|
dfainfo.def:=@node.optinfo^.def;
|
||||||
Foreach
|
dfainfo.map:=map;
|
||||||
|
foreachnodestatic(pm_postprocess,tstatementnode(node).left,@AddDefUse,@dfainfo);
|
||||||
end;
|
end;
|
||||||
calclife(node);
|
calclife(node);
|
||||||
end;
|
end;
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ nested statement }
|
||||||
|
CreateInfo(tstatementnode(node).statement);
|
||||||
|
{ inherit info }
|
||||||
|
node.allocoptinfo;
|
||||||
|
node.optinfo^.life:=tstatementnode(node).statement.optinfo^.life;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
blockn:
|
||||||
|
begin
|
||||||
|
CreateInfo(tblocknode(node).statements);
|
||||||
|
node.allocoptinfo;
|
||||||
|
if assigned(tblocknode(node).statements) then
|
||||||
|
node.optinfo^.life:=tblocknode(node).statements.optinfo^.life;
|
||||||
|
end;
|
||||||
else
|
else
|
||||||
internalerror(2007050502);
|
internalerror(2007050502);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
exclude(node,nf_processing);
|
exclude(node.flags,nf_processing);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
runs : integer;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
runs:=0;
|
||||||
repeat
|
repeat
|
||||||
|
inc(runs);
|
||||||
changed:=false;
|
changed:=false;
|
||||||
CreateInfo(node);
|
CreateInfo(node);
|
||||||
|
{$ifdef DEBUG_DFA}
|
||||||
|
PrintIndexedNodeSet(output,map);
|
||||||
|
PrintDFAInfo(output,node);
|
||||||
|
{$endif DEBUG_DFA}
|
||||||
until not(changed);
|
until not(changed);
|
||||||
|
{$ifdef DEBUG_DFA}
|
||||||
|
writeln('DFA solver iterations: ',runs);
|
||||||
|
{$endif DEBUG_DFA}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -203,13 +297,17 @@ unit optdfa;
|
|||||||
|
|
||||||
|
|
||||||
procedure createdfainfo(node : tnode);
|
procedure createdfainfo(node : tnode);
|
||||||
|
var
|
||||||
|
map : TIndexedNodeSet;
|
||||||
begin
|
begin
|
||||||
|
map:=TIndexedNodeSet.Create;
|
||||||
{ add controll flow information }
|
{ add controll flow information }
|
||||||
SetNodeSucessors(node);
|
SetNodeSucessors(node);
|
||||||
|
|
||||||
{ now, collect life information }
|
{ now, collect life information }
|
||||||
CreateLifeInfo(node);
|
CreateLifeInfo(node,map);
|
||||||
|
|
||||||
|
map.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -26,6 +26,7 @@ unit optutils;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
|
cclasses,
|
||||||
node;
|
node;
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -37,16 +38,16 @@ unit optutils;
|
|||||||
function Remove(node : tnode) : boolean;
|
function Remove(node : tnode) : boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
TNodeMap = class(TNodeSet)
|
|
||||||
function (node : tnode) : boolean;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure SetNodeSucessors(p : tnode);
|
procedure SetNodeSucessors(p : tnode);
|
||||||
|
procedure PrintDFAInfo(var f : text;p : tnode);
|
||||||
|
procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
nbas,nflw;
|
verbose,
|
||||||
|
optbase,
|
||||||
|
nbas,nflw,nutils;
|
||||||
|
|
||||||
function TIndexedNodeSet.Add(node : tnode) : boolean;
|
function TIndexedNodeSet.Add(node : tnode) : boolean;
|
||||||
var
|
var
|
||||||
@ -62,7 +63,7 @@ unit optutils;
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
i:=Add(node);
|
i:=inherited Add(node);
|
||||||
node.optinfo^.index:=i;
|
node.optinfo^.index:=i;
|
||||||
result:=true;
|
result:=true;
|
||||||
end
|
end
|
||||||
@ -73,10 +74,10 @@ unit optutils;
|
|||||||
var
|
var
|
||||||
i : longint;
|
i : longint;
|
||||||
begin
|
begin
|
||||||
for i:=0 to FCount-1 do
|
for i:=0 to Count-1 do
|
||||||
if tnode(FList^[i]).isequal(node) then
|
if tnode(List^[i]).isequal(node) then
|
||||||
begin
|
begin
|
||||||
result:=tnode(FList^[i]);
|
result:=tnode(List^[i]);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
result:=nil;
|
result:=nil;
|
||||||
@ -91,23 +92,47 @@ unit optutils;
|
|||||||
p:=Includes(node);
|
p:=Includes(node);
|
||||||
if assigned(p) then
|
if assigned(p) then
|
||||||
begin
|
begin
|
||||||
if Remove(p)<>-1 then
|
if inherited Remove(p)<>-1 then
|
||||||
result:=true;
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure PrintIndexedNodeSet(f : text;s : TIndexedNodeSet);
|
procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
begin
|
begin
|
||||||
for i:=0 to high(s) do
|
for i:=0 to s.count-1 do
|
||||||
begin
|
begin
|
||||||
writeln(f,'=============================== Node ',i,' ===============================');
|
writeln(f,'=============================== Node ',i,' ===============================');
|
||||||
printnode(f,s[i]);
|
printnode(f,tnode(s[i]));
|
||||||
writeln(f);
|
writeln(f);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function PrintNodeDFA(var n: tnode; arg: pointer): foreachnoderesult;
|
||||||
|
begin
|
||||||
|
if assigned(n.optinfo) and ((n.optinfo^.life<>nil) or (n.optinfo^.use<>nil) or (n.optinfo^.def<>nil)) then
|
||||||
|
begin
|
||||||
|
write(text(arg^),nodetype2str[n.nodetype],'(',n.fileinfo.line,',',n.fileinfo.column,') Life: ');
|
||||||
|
PrintDFASet(text(arg^),n.optinfo^.life);
|
||||||
|
write(text(arg^),' Def: ');
|
||||||
|
PrintDFASet(text(arg^),n.optinfo^.def);
|
||||||
|
write(text(arg^),' Use: ');
|
||||||
|
PrintDFASet(text(arg^),n.optinfo^.use);
|
||||||
|
writeln(text(arg^));
|
||||||
|
end;
|
||||||
|
result:=fen_false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure PrintDFAInfo(var f : text;p : tnode);
|
||||||
|
begin
|
||||||
|
foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure SetNodeSucessors(p : tnode);
|
procedure SetNodeSucessors(p : tnode);
|
||||||
var
|
var
|
||||||
Continuestack : TFPList;
|
Continuestack : TFPList;
|
||||||
@ -119,6 +144,8 @@ unit optutils;
|
|||||||
hp1,hp2 : tnode;
|
hp1,hp2 : tnode;
|
||||||
begin
|
begin
|
||||||
result:=nil;
|
result:=nil;
|
||||||
|
if p=nil then
|
||||||
|
exit;
|
||||||
case p.nodetype of
|
case p.nodetype of
|
||||||
statementn:
|
statementn:
|
||||||
begin
|
begin
|
||||||
@ -126,36 +153,41 @@ unit optutils;
|
|||||||
result:=p;
|
result:=p;
|
||||||
while assigned(hp1) do
|
while assigned(hp1) do
|
||||||
begin
|
begin
|
||||||
if assigned(tstatementnode(hp1).right) then
|
{ does another statement follow? }
|
||||||
|
if assigned(tstatementnode(hp1).next) then
|
||||||
begin
|
begin
|
||||||
hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
|
hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
|
||||||
if assigned(hp2) then
|
if assigned(hp2) then
|
||||||
tstatementnode(hp1).successor:=hp2
|
tstatementnode(hp1).successor:=hp2
|
||||||
else
|
else
|
||||||
tstatementnode(hp1).successor:=tstatementnode(hp1).right;
|
tstatementnode(hp1).successor:=tstatementnode(hp1).next;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
hp2:=DoSet(tstatementnode(hp1).statement,successor);
|
hp2:=DoSet(tstatementnode(hp1).statement,succ);
|
||||||
if assigned(hp2) then
|
if assigned(hp2) then
|
||||||
tstatementnode(hp1).successor:=hp2
|
tstatementnode(hp1).successor:=hp2
|
||||||
else
|
else
|
||||||
tstatementnode(hp1).successor:=successor;
|
tstatementnode(hp1).successor:=succ;
|
||||||
end;
|
end;
|
||||||
|
hp1:=tstatementnode(hp1).next;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
blockn:
|
blockn:
|
||||||
begin
|
begin
|
||||||
result:=DoSet(tblocknode(p).statements,successor);
|
result:=p;
|
||||||
|
DoSet(tblocknode(p).statements,succ);
|
||||||
|
p.successor:=succ;
|
||||||
end;
|
end;
|
||||||
forn:
|
forn:
|
||||||
begin
|
begin
|
||||||
Breakstack.Add(successor);
|
Breakstack.Add(succ);
|
||||||
Continuestack.Add(p);
|
Continuestack.Add(p);
|
||||||
result:=p;
|
result:=p;
|
||||||
DoSet(tfornode(p).statements,successor);
|
{ the successor of the last node of the for body is the for node itself }
|
||||||
Breakstack.Delete(Count-1);
|
DoSet(tfornode(p).t2,p);
|
||||||
Continuestack.Delete(Count-1);
|
Breakstack.Delete(Breakstack.Count-1);
|
||||||
|
Continuestack.Delete(Continuestack.Count-1);
|
||||||
end;
|
end;
|
||||||
breakn:
|
breakn:
|
||||||
begin
|
begin
|
||||||
@ -167,6 +199,17 @@ unit optutils;
|
|||||||
result:=p;
|
result:=p;
|
||||||
p.successor:=tnode(Continuestack.Last);
|
p.successor:=tnode(Continuestack.Last);
|
||||||
end;
|
end;
|
||||||
|
whilerepeatn:
|
||||||
|
begin
|
||||||
|
Breakstack.Add(succ);
|
||||||
|
Continuestack.Add(p);
|
||||||
|
result:=p;
|
||||||
|
{ the successor of the last node of the for body is the while node itself }
|
||||||
|
DoSet(twhilerepeatnode(p).right,p);
|
||||||
|
p.successor:=succ;
|
||||||
|
Breakstack.Delete(Breakstack.Count-1);
|
||||||
|
Continuestack.Delete(Continuestack.Count-1);
|
||||||
|
end;
|
||||||
{ exit is actually a jump to some final. code
|
{ exit is actually a jump to some final. code
|
||||||
exitn:
|
exitn:
|
||||||
begin
|
begin
|
||||||
@ -175,7 +218,6 @@ unit optutils;
|
|||||||
end;
|
end;
|
||||||
}
|
}
|
||||||
ifn,
|
ifn,
|
||||||
whilerepeatn,
|
|
||||||
exitn,
|
exitn,
|
||||||
withn,
|
withn,
|
||||||
casen,
|
casen,
|
||||||
|
@ -103,7 +103,8 @@ implementation
|
|||||||
tgobj,cgbase,cgobj,dbgbase,
|
tgobj,cgbase,cgobj,dbgbase,
|
||||||
ncgutil,regvars,
|
ncgutil,regvars,
|
||||||
opttail,
|
opttail,
|
||||||
optcse
|
optcse,
|
||||||
|
optdfa
|
||||||
{$if defined(arm) or defined(powerpc) or defined(powerpc64)}
|
{$if defined(arm) or defined(powerpc) or defined(powerpc64)}
|
||||||
,aasmcpu
|
,aasmcpu
|
||||||
{$endif arm}
|
{$endif arm}
|
||||||
@ -755,6 +756,11 @@ implementation
|
|||||||
(pi_is_recursive in flags) then
|
(pi_is_recursive in flags) then
|
||||||
do_opttail(code,procdef);
|
do_opttail(code,procdef);
|
||||||
|
|
||||||
|
if cs_opt_nodedfa in current_settings.optimizerswitches then
|
||||||
|
begin
|
||||||
|
createdfainfo(code);
|
||||||
|
end;
|
||||||
|
|
||||||
if cs_opt_nodecse in current_settings.optimizerswitches then
|
if cs_opt_nodecse in current_settings.optimizerswitches then
|
||||||
do_optcse(code);
|
do_optcse(code);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user