mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-29 20:20:16 +02:00
* backup commit of more dfa stuff
git-svn-id: trunk@7287 -
This commit is contained in:
parent
a3b72c1be8
commit
867e00dee3
@ -203,6 +203,7 @@ interface
|
|||||||
nf_pass1_done,
|
nf_pass1_done,
|
||||||
nf_write, { Node is written to }
|
nf_write, { Node is written to }
|
||||||
nf_isproperty,
|
nf_isproperty,
|
||||||
|
nf_processing,
|
||||||
|
|
||||||
{ taddrnode }
|
{ taddrnode }
|
||||||
nf_typedaddr,
|
nf_typedaddr,
|
||||||
@ -250,6 +251,7 @@ interface
|
|||||||
|
|
||||||
{ tblocknode }
|
{ tblocknode }
|
||||||
nf_block_with_exit
|
nf_block_with_exit
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
tnodeflags = set of tnodeflag;
|
tnodeflags = set of tnodeflag;
|
||||||
@ -359,6 +361,9 @@ interface
|
|||||||
procedure printnodetree(var t:text);virtual;
|
procedure printnodetree(var t:text);virtual;
|
||||||
procedure concattolist(l : tlinkedlist);virtual;
|
procedure concattolist(l : tlinkedlist);virtual;
|
||||||
function ischild(p : tnode) : boolean;virtual;
|
function ischild(p : tnode) : boolean;virtual;
|
||||||
|
|
||||||
|
{ ensures that the optimizer info record is allocated }
|
||||||
|
function allocoptinfo : poptinfo;inline;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
tnodeclass = class of tnode;
|
tnodeclass = class of tnode;
|
||||||
@ -775,6 +780,8 @@ implementation
|
|||||||
if firstpasscount>maxfirstpasscount then
|
if firstpasscount>maxfirstpasscount then
|
||||||
maxfirstpasscount:=firstpasscount;
|
maxfirstpasscount:=firstpasscount;
|
||||||
{$endif EXTDEBUG}
|
{$endif EXTDEBUG}
|
||||||
|
if assigned(optinfo) then
|
||||||
|
dispose(optinfo);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -905,6 +912,14 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ ensures that the optimizer info record is allocated }
|
||||||
|
function tnode.allocoptinfo : poptinfo;inline;
|
||||||
|
begin
|
||||||
|
if not(assigned(optinfo)) then
|
||||||
|
new(optinfo);
|
||||||
|
result:=optinfo;
|
||||||
|
end;
|
||||||
|
|
||||||
{****************************************************************************
|
{****************************************************************************
|
||||||
TUNARYNODE
|
TUNARYNODE
|
||||||
****************************************************************************}
|
****************************************************************************}
|
||||||
|
@ -29,17 +29,127 @@ unit optbase;
|
|||||||
globtype;
|
globtype;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
{ this should maybe replaced by a spare set,
|
||||||
|
using a dyn. array makes assignments cheap }
|
||||||
tdfaset = array of byte;
|
tdfaset = array of byte;
|
||||||
|
|
||||||
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 }
|
||||||
index : aword;
|
index : aword;
|
||||||
defined_nodes : tdfaset;
|
def : tdfaset;
|
||||||
used_nodes : tdfaset;
|
use : tdfaset;
|
||||||
|
life : tdfaset;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
poptinfo = ^toptinfo;
|
poptinfo = ^toptinfo;
|
||||||
|
|
||||||
|
{ basic set operations for dfa sets }
|
||||||
|
procedure TDFASetInclude(var s : tdfaset;e : integer);
|
||||||
|
procedure TDFASetExclude(var s : tdfaset;e : integer);
|
||||||
|
function TDFASetIn(const s : tdfaset;e : integer) : boolean;
|
||||||
|
procedure TDFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
procedure TDFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
procedure TDFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
cutils;
|
||||||
|
|
||||||
|
procedure TDFASetInclude(var s : tdfaset;e : integer);
|
||||||
|
var
|
||||||
|
e8 : Integer;
|
||||||
|
begin
|
||||||
|
e8:=e div 8;
|
||||||
|
if e8>high(s) then
|
||||||
|
SetLength(s,e8+1);
|
||||||
|
s[e8]:=s[e8] or (1 shl (e mod 8));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDFASetExclude(var s : tdfaset;e : integer);
|
||||||
|
var
|
||||||
|
e8 : Integer;
|
||||||
|
begin
|
||||||
|
e8:=e div 8;
|
||||||
|
if e8>high(s) then
|
||||||
|
SetLength(s,e8+1);
|
||||||
|
s[e8]:=s[e8] and not(1 shl (e mod 8));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TDFASetIn(const s : tdfaset;e : integer) : boolean;
|
||||||
|
var
|
||||||
|
e8 : Integer;
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
e8:=e div 8;
|
||||||
|
if e8>high(s) then
|
||||||
|
exit;
|
||||||
|
result:=(s[e8] and (1 shl (e mod 8)))<>0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDFASetUnion(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
SetLength(d,max(Length(s1),Length(s2)));
|
||||||
|
for i:=0 to high(s1) do
|
||||||
|
d[i]:=s1[i];
|
||||||
|
for i:=0 to high(s2) do
|
||||||
|
d[i]:=d[i] or s2[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDFASetIntersect(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
SetLength(d,min(Length(s1),Length(s2)));
|
||||||
|
for i:=0 to min(high(s1),high(s2)) do
|
||||||
|
d[i]:=s1[i] and s2[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TDFASetDiff(var d : tdfaset;const s1,s2 : tdfaset);
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
SetLength(d,min(Length(s1),Length(s2)));
|
||||||
|
for i:=0 to min(high(s1),high(s2)) do
|
||||||
|
d[i]:=s1[i] and not(s2[i]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function DFASetNotEqual(const s1,s2 : tdfaset) : boolean;
|
||||||
|
var
|
||||||
|
i : integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
{ one set could be larger than the other }
|
||||||
|
if length(s1)>length(s2) then
|
||||||
|
begin
|
||||||
|
for i:=0 to high(s2) do
|
||||||
|
if s1[i]<>s2[i] then
|
||||||
|
exit;
|
||||||
|
{ check remaining part being zero }
|
||||||
|
for i:=length(s2) to high(s1) do
|
||||||
|
if s1[i]<>0 then
|
||||||
|
exit;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
for i:=0 to high(s1) do
|
||||||
|
if s1[i]<>s2[i] then
|
||||||
|
exit;
|
||||||
|
{ check remaining part being zero }
|
||||||
|
for i:=length(s1) to high(s2) do
|
||||||
|
if s2[i]<>0 then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -28,6 +28,10 @@ unit optdfa;
|
|||||||
uses
|
uses
|
||||||
node;
|
node;
|
||||||
|
|
||||||
|
{ reset all dfa info, this is required before creating dfa info
|
||||||
|
if the tree has been changed without updating dfa }
|
||||||
|
procedure resetdfainfo(node : tnode);
|
||||||
|
|
||||||
procedure createoptinfo(node : tnode);
|
procedure createoptinfo(node : tnode);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -54,8 +58,6 @@ unit optdfa;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
x:=f; read: [f]
|
x:=f; read: [f]
|
||||||
|
|
||||||
@ -83,16 +85,130 @@ unit optdfa;
|
|||||||
|
|
||||||
type
|
type
|
||||||
tdfainfo = record
|
tdfainfo = record
|
||||||
definitionlist : tfplist;
|
use : TDFASet;
|
||||||
lifelist : tfplist;
|
def : TDFASet;
|
||||||
|
map : TIndexedNodeSet
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure AddDefUse(s : TDFASet;m : ;n : tnode);
|
||||||
|
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;
|
||||||
|
else
|
||||||
|
internalerror(2007050601);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure CreateLifeInfo(node : tnode);
|
||||||
|
|
||||||
|
var
|
||||||
|
changed : boolean;
|
||||||
|
|
||||||
|
procedure CreateInfo(node : tnode);
|
||||||
|
|
||||||
|
procedure updatelifeinfo(n : tnode;l : TDFASet);
|
||||||
|
begin
|
||||||
|
changed:=changed or DFASetNotEqual(l,n.life);
|
||||||
|
node.life:=l;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure calclife(n : tnode);
|
||||||
|
var
|
||||||
|
l : TDFANode;
|
||||||
|
begin
|
||||||
|
if assigned(successor) then
|
||||||
|
begin
|
||||||
|
DFASetDiff(l,successor.optinfo^.life,n.optinfo^.def);
|
||||||
|
DFASetIncludeSet(l,n.optinfo^.use);
|
||||||
|
updatelifeinfo(n,l);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
var
|
||||||
|
dfainfo : tdfainfo;
|
||||||
|
begin
|
||||||
|
if nf_processing in node.flags then
|
||||||
|
exit;
|
||||||
|
include(node,nf_processing);
|
||||||
|
|
||||||
|
if assigned(node.successor) then
|
||||||
|
CreateInfo(node.successor);
|
||||||
|
|
||||||
|
{ life:=succesorlive-definition+use }
|
||||||
|
|
||||||
|
case node.nodetype of
|
||||||
|
whilen:
|
||||||
|
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);
|
||||||
|
end;
|
||||||
|
statementn:
|
||||||
|
begin
|
||||||
|
{ actually an expression doing something? }
|
||||||
|
case tstatementnode(node).statement.nodetype of
|
||||||
|
assignn:
|
||||||
|
begin
|
||||||
|
tstatementnode(node).allocoptinfo;
|
||||||
|
if not(assigned(tstatementnode(node).optinfo^.def)) or
|
||||||
|
not(assigned(tstatementnode(node).optinfo^.use)) then
|
||||||
|
begin
|
||||||
|
dfainfo.use:=tstatementnode(node).optinfo^.use;
|
||||||
|
dfainfo.def:=tstatementnode(node).optinfo^.def;
|
||||||
|
Foreach
|
||||||
|
end;
|
||||||
|
calclife(node);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
internalerror(2007050502);
|
||||||
|
end;
|
||||||
|
|
||||||
|
exclude(node,nf_processing);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
changed:=false;
|
||||||
|
CreateInfo(node);
|
||||||
|
until not(changed);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ reset all dfa info, this is required before creating dfa info
|
||||||
|
if the tree has been changed without updating dfa }
|
||||||
|
procedure resetdfainfo(node : tnode);
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure createdfainfo(node : tnode);
|
procedure createdfainfo(node : tnode);
|
||||||
begin
|
begin
|
||||||
{ first, add controll flow information }
|
{ add controll flow information }
|
||||||
SetNodeSucessors(node);
|
SetNodeSucessors(node);
|
||||||
{ now, collect life information }
|
|
||||||
|
|
||||||
|
{ now, collect life information }
|
||||||
|
CreateLifeInfo(node);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,19 @@ unit optutils;
|
|||||||
uses
|
uses
|
||||||
node;
|
node;
|
||||||
|
|
||||||
|
type
|
||||||
|
{ this implementation should be really improved,
|
||||||
|
its purpose is to find equal nodes }
|
||||||
|
TIndexedNodeSet = class(TFPList)
|
||||||
|
function Add(node : tnode) : boolean;
|
||||||
|
function Includes(node : tnode) : tnode;
|
||||||
|
function Remove(node : tnode) : boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TNodeMap = class(TNodeSet)
|
||||||
|
function (node : tnode) : boolean;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure SetNodeSucessors(p : tnode);
|
procedure SetNodeSucessors(p : tnode);
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -35,6 +48,66 @@ unit optutils;
|
|||||||
uses
|
uses
|
||||||
nbas,nflw;
|
nbas,nflw;
|
||||||
|
|
||||||
|
function TIndexedNodeSet.Add(node : tnode) : boolean;
|
||||||
|
var
|
||||||
|
i : Integer;
|
||||||
|
p : tnode;
|
||||||
|
begin
|
||||||
|
node.allocoptinfo;
|
||||||
|
p:=Includes(node);
|
||||||
|
if assigned(p) then
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
node.optinfo^.index:=p.optinfo^.index;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
i:=Add(node);
|
||||||
|
node.optinfo^.index:=i;
|
||||||
|
result:=true;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TIndexedNodeSet.Includes(node : tnode) : tnode;
|
||||||
|
var
|
||||||
|
i : longint;
|
||||||
|
begin
|
||||||
|
for i:=0 to FCount-1 do
|
||||||
|
if tnode(FList^[i]).isequal(node) then
|
||||||
|
begin
|
||||||
|
result:=tnode(FList^[i]);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TIndexedNodeSet.Remove(node : tnode) : boolean;
|
||||||
|
var
|
||||||
|
p : tnode;
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
p:=Includes(node);
|
||||||
|
if assigned(p) then
|
||||||
|
begin
|
||||||
|
if Remove(p)<>-1 then
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure PrintIndexedNodeSet(f : text;s : TIndexedNodeSet);
|
||||||
|
begin
|
||||||
|
for i:=0 to high(s) do
|
||||||
|
begin
|
||||||
|
writeln(f,'=============================== Node ',i,' ===============================');
|
||||||
|
printnode(f,s[i]);
|
||||||
|
writeln(f);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure SetNodeSucessors(p : tnode);
|
procedure SetNodeSucessors(p : tnode);
|
||||||
var
|
var
|
||||||
Continuestack : TFPList;
|
Continuestack : TFPList;
|
||||||
|
Loading…
Reference in New Issue
Block a user