|
@@ -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;
|
|
|
|
- def : TDFASet;
|
|
|
|
|
|
+ use : PDFASet;
|
|
|
|
+ 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
|
|
|
|
- begin
|
|
|
|
- case n.nodetype of
|
|
|
|
- typeconvn:
|
|
|
|
- n:=ttypeconvnode(n).left;
|
|
|
|
- loadn:
|
|
|
|
- begin
|
|
|
|
- m.Add(n);
|
|
|
|
- TDFASetInclude(s,n.optinfo^.index);
|
|
|
|
- end;
|
|
|
|
|
|
+ case n.nodetype of
|
|
|
|
+ loadn:
|
|
|
|
+ begin
|
|
|
|
+ pdfainfo(arg)^.map.Add(n);
|
|
|
|
+ if nf_write in n.flags then
|
|
|
|
+ DFASetInclude(pdfainfo(arg)^.def^,n.optinfo^.index)
|
|
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);
|
|
|
|
- node.life:=l;
|
|
|
|
|
|
+ b:=DFASetNotEqual(l,n.optinfo^.life);
|
|
|
|
+ {
|
|
|
|
+ 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 }
|
|
|
|
-
|
|
|
|
- { life:=succesorlive-definition+use }
|
|
|
|
-
|
|
|
|
- { now iterate through the loop }
|
|
|
|
- CreateInfo(twhilenode(node).left);
|
|
|
|
-
|
|
|
|
- { update while node }
|
|
|
|
- { life:=life+left.life }
|
|
|
|
-
|
|
|
|
- { ... and a second iteration for fast convergence }
|
|
|
|
- CreateInfo(twhilenode(node).left);
|
|
|
|
|
|
+ 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:[email protected]^.use;
|
|
|
|
+ dfainfo.def:[email protected]^.def;
|
|
|
|
+ dfainfo.map:=map;
|
|
|
|
+ foreachnodestatic(pm_postprocess,twhilerepeatnode(node).left,@AddDefUse,@dfainfo);
|
|
|
|
+ end;
|
|
|
|
+ calclife(node);
|
|
|
|
+
|
|
|
|
+ { now iterate through the loop }
|
|
|
|
+ CreateInfo(twhilerepeatnode(node).right);
|
|
|
|
+
|
|
|
|
+ { update while node }
|
|
|
|
+ { life:=life+use+right.life }
|
|
|
|
+ l:=node.optinfo^.life;
|
|
|
|
+ DFASetIncludeSet(l,node.optinfo^.use);
|
|
|
|
+ DFASetIncludeSet(l,twhilerepeatnode(node).right.optinfo^.life);
|
|
|
|
+ UpdateLifeInfo(node,l);
|
|
|
|
+
|
|
|
|
+ { ... and a second iteration for fast convergence }
|
|
|
|
+ CreateInfo(twhilerepeatnode(node).right);
|
|
|
|
+ end;
|
|
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;
|
|
|
|
- if not(assigned(tstatementnode(node).optinfo^.def)) or
|
|
|
|
- not(assigned(tstatementnode(node).optinfo^.use)) then
|
|
|
|
|
|
+ node.allocoptinfo;
|
|
|
|
+ if not(assigned(node.optinfo^.def)) and
|
|
|
|
+ not(assigned(node.optinfo^.use)) then
|
|
begin
|
|
begin
|
|
- dfainfo.use:=tstatementnode(node).optinfo^.use;
|
|
|
|
- dfainfo.def:=tstatementnode(node).optinfo^.def;
|
|
|
|
- Foreach
|
|
|
|
|
|
+ dfainfo.use:[email protected]^.use;
|
|
|
|
+ dfainfo.def:[email protected]^.def;
|
|
|
|
+ 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);
|
|
|
|
- end;
|
|
|
|
|
|
+ CreateLifeInfo(node,map);
|
|
|
|
|
|
|
|
+ map.free;
|
|
|
|
+ end;
|
|
|
|
|
|
end.
|
|
end.
|