123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502 |
- {
- Helper routines for the optimizer
- Copyright (c) 2007 by Florian Klaempfl
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit optutils;
- {$i fpcdefs.inc}
- interface
- uses
- cclasses,
- node,
- globtype;
- 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;
- procedure SetNodeSucessors(p,last : tnode);
- procedure PrintDFAInfo(var f : text;p : tnode);
- procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
- { determines the optinfo.defsum field for the given node
- this field contains a sum of all expressions defined by
- all child expressions reachable through p
- }
- procedure CalcDefSum(p : tnode);
- { calculates/estimates the field execution weight of optinfo }
- procedure CalcExecutionWeights(p : tnode;Initial : longint = 100);
- { determines the optinfo.defsum field for the given node
- this field contains a sum of all expressions defined by
- all child expressions reachable through p
- }
- procedure CalcUseSum(p : tnode);
- { returns true, if n is a valid node and has life info }
- function has_life_info(n : tnode) : boolean;
- implementation
- uses
- cutils,
- verbose,
- optbase,
- ncal,nbas,nflw,nutils,nset,ncon;
- 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:=inherited Add(node);
- node.optinfo^.index:=i;
- result:=true;
- end
- end;
- function TIndexedNodeSet.Includes(node : tnode) : tnode;
- var
- i : longint;
- begin
- for i:=0 to Count-1 do
- if tnode(List[i]).isequal(node) then
- begin
- result:=tnode(List[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 inherited Remove(p)<>-1 then
- result:=true;
- end;
- end;
- procedure PrintIndexedNodeSet(var f : text;s : TIndexedNodeSet);
- var
- i : integer;
- begin
- for i:=0 to s.count-1 do
- begin
- writeln(f,'=============================== Node ',i,' ===============================');
- printnode(f,tnode(s[i]));
- writeln(f);
- 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);
- if assigned(n.successor) then
- write(text(arg^),' Successor: ',nodetype2str[n.successor.nodetype],'(',n.successor.fileinfo.line,',',n.successor.fileinfo.column,')')
- else
- write(text(arg^),' Successor: nil');
- write(text(arg^),' DefSum: ');
- PrintDFASet(text(arg^),n.optinfo^.defsum);
- writeln(text(arg^));
- end;
- result:=fen_false;
- end;
- procedure PrintDFAInfo(var f : text;p : tnode);
- begin
- foreachnodestatic(pm_postprocess,p,@PrintNodeDFA,@f);
- end;
- type
- PBreakContinueStackNode = ^TBreakContinueStackNode;
- TBreakContinueStackNode = record
- { successor node for a break statement in the current loop }
- brk,
- { successor node for a continue statement in the current loop }
- cont : tnode;
- next : PBreakContinueStackNode;
- end;
- { implements a stack to track successor nodes for break and continue
- statements }
- TBreakContinueStack = object
- top: PBreakContinueStackNode;
- constructor Init;
- destructor Done;
- procedure Push(brk,cont : tnode);
- procedure Pop;
- end;
- const
- NullBreakContinueStackNode : TBreakContinueStackNode = (brk: nil; cont: nil; next: nil);
- constructor TBreakContinueStack.Init;
- begin
- top:=@NullBreakContinueStackNode;
- end;
- destructor TBreakContinueStack.Done;
- begin
- while top<>@NullBreakContinueStackNode do
- Pop;
- end;
- procedure TBreakContinueStack.Push(brk,cont : tnode);
- var
- n : PBreakContinueStackNode;
- begin
- new(n);
- n^.brk:=brk;
- n^.cont:=cont;
- n^.next:=top;
- top:=n;
- end;
- procedure TBreakContinueStack.Pop;
- var
- n : PBreakContinueStackNode;
- begin
- n:=top;
- top:=n^.next;
- Dispose(n);
- end;
- procedure SetNodeSucessors(p,last : tnode);
- var
- BreakContinueStack : TBreakContinueStack;
- Exitsuccessor: TNode;
- { sets the successor nodes of a node tree block
- returns the first node of the tree if it's a controll flow node }
- function DoSet(p : tnode;succ : tnode) : tnode;
- var
- hp1,hp2, oldexitsuccessor: tnode;
- i : longint;
- begin
- result:=nil;
- if p=nil then
- exit;
- case p.nodetype of
- statementn:
- begin
- hp1:=p;
- result:=p;
- while assigned(hp1) do
- begin
- { does another statement follow? }
- if assigned(tstatementnode(hp1).next) then
- begin
- hp2:=DoSet(tstatementnode(hp1).statement,tstatementnode(hp1).next);
- if assigned(hp2) then
- tstatementnode(hp1).successor:=hp2
- else
- tstatementnode(hp1).successor:=tstatementnode(hp1).next;
- end
- else
- begin
- hp2:=DoSet(tstatementnode(hp1).statement,succ);
- if assigned(hp2) then
- tstatementnode(hp1).successor:=hp2
- else
- tstatementnode(hp1).successor:=succ;
- end;
- hp1:=tstatementnode(hp1).next;
- end;
- end;
- blockn:
- begin
- result:=p;
- oldexitsuccessor:=Exitsuccessor;
- if nf_block_with_exit in p.flags then
- Exitsuccessor:=succ;
- DoSet(tblocknode(p).statements,succ);
- if assigned(tblocknode(p).statements) then
- p.successor:=tblocknode(p).statements
- else
- p.successor:=succ;
- Exitsuccessor:=oldexitsuccessor;
- end;
- forn:
- begin
- BreakContinueStack.Push(succ,p);
- result:=p;
- { the successor of the last node of the for body is the dummy loop iteration node
- it allows the dfa to inject needed life information into the loop }
- tfornode(p).loopiteration:=cnothingnode.create;
- DoSet(tfornode(p).t2,tfornode(p).loopiteration);
- p.successor:=succ;
- BreakContinueStack.Pop;
- end;
- breakn:
- begin
- result:=p;
- p.successor:=BreakContinueStack.top^.brk;
- end;
- continuen:
- begin
- result:=p;
- p.successor:=BreakContinueStack.top^.cont;
- end;
- whilerepeatn:
- begin
- BreakContinueStack.Push(succ,p);
- result:=p;
- { the successor of the last node of the while/repeat body is the while node itself }
- DoSet(twhilerepeatnode(p).right,p);
- p.successor:=succ;
- { special case: we do not do a dyn. dfa, but we should handle endless loops }
- if is_constboolnode(twhilerepeatnode(p).left) then
- begin
- if ((lnf_testatbegin in twhilerepeatnode(p).loopflags) and
- getbooleanvalue(twhilerepeatnode(p).left)) or (not(lnf_testatbegin in twhilerepeatnode(p).loopflags) and
- not(getbooleanvalue(twhilerepeatnode(p).left))) then
- p.successor:=nil;
- end;
- BreakContinueStack.Pop;
- end;
- ifn:
- begin
- result:=p;
- DoSet(tifnode(p).right,succ);
- DoSet(tifnode(p).t1,succ);
- p.successor:=succ;
- end;
- labeln:
- begin
- result:=p;
- p.successor:=succ;
- end;
- assignn:
- begin
- result:=p;
- p.successor:=succ;
- end;
- goton:
- begin
- result:=p;
- if not(assigned(tgotonode(p).labelnode)) then
- internalerror(2007050701);
- p.successor:=tgotonode(p).labelnode;
- end;
- exitn:
- begin
- result:=p;
- p.successor:=Exitsuccessor;
- end;
- casen:
- begin
- result:=p;
- DoSet(tcasenode(p).elseblock,succ);
- for i:=0 to tcasenode(p).blocks.count-1 do
- DoSet(pcaseblock(tcasenode(p).blocks[i])^.statement,succ);
- p.successor:=succ;
- end;
- calln:
- begin
- { not sure if this is enough (FK) }
- result:=p;
- if cnf_call_never_returns in tcallnode(p).callnodeflags then
- p.successor:=nil
- else
- p.successor:=succ;
- end;
- inlinen:
- begin
- { not sure if this is enough (FK) }
- result:=p;
- p.successor:=succ;
- end;
- loadn,
- tempcreaten,
- tempdeleten,
- nothingn:
- begin
- result:=p;
- p.successor:=succ;
- end;
- raisen:
- begin
- result:=p;
- { raise never returns }
- p.successor:=nil;
- end;
- tryexceptn,
- tryfinallyn,
- onn:
- internalerror(2007050501);
- else
- ;
- end;
- end;
- begin
- BreakContinueStack.Init;
- Exitsuccessor:=nil;
- DoSet(p,last);
- BreakContinueStack.Done;
- end;
- function adddef(var n: tnode; arg: pointer): foreachnoderesult;
- var
- defsum : PDFASet absolute arg;
- begin
- if assigned(n.optinfo) then
- begin
- DFASetIncludeSet(defsum^,n.optinfo^.def);
- { for nodes itself do not necessarily expose the definition of the counter as
- the counter might be undefined after the for loop, so include here the counter
- explicitly }
- if (n.nodetype=forn) and assigned(tfornode(n).left.optinfo) then
- DFASetInclude(defsum^,tfornode(n).left.optinfo^.index);
- end;
- Result:=fen_false;
- end;
- procedure CalcDefSum(p : tnode);
- var
- defsum : PDFASet;
- begin
- p.allocoptinfo;
- defsum:[email protected]^.defsum;
- if not assigned(defsum^) then
- foreachnodestatic(pm_postprocess,p,@adddef,defsum);
- end;
- function SetExecutionWeight(var n: tnode; arg: pointer): foreachnoderesult;
- var
- Weight, CaseWeight : longint;
- i : Integer;
- begin
- Result:=fen_false;
- n.allocoptinfo;
- Weight:=max(plongint(arg)^,1);
- case n.nodetype of
- casen:
- begin
- CalcExecutionWeights(tcasenode(n).left,Weight);
- CaseWeight:=max(Weight div tcasenode(n).labelcnt,1);
- for i:=0 to tcasenode(n).blocks.count-1 do
- CalcExecutionWeights(pcaseblock(tcasenode(n).blocks[i])^.statement,CaseWeight);
- CalcExecutionWeights(tcasenode(n).elseblock,CaseWeight);
- Result:=fen_norecurse_false;
- end;
- whilerepeatn:
- begin
- CalcExecutionWeights(twhilerepeatnode(n).right,Weight*8);
- CalcExecutionWeights(twhilerepeatnode(n).left,Weight*8);
- Result:=fen_norecurse_false;
- end;
- ifn:
- begin
- CalcExecutionWeights(tifnode(n).left,Weight);
- CalcExecutionWeights(tifnode(n).right,Weight div 2);
- CalcExecutionWeights(tifnode(n).t1,Weight div 2);
- Result:=fen_norecurse_false;
- end;
- else
- ;
- end;
- n.optinfo^.executionweight:=Weight;
- end;
- procedure CalcExecutionWeights(p : tnode;Initial : longint = 100);
- begin
- if assigned(p) then
- foreachnodestatic(pm_postprocess,p,@SetExecutionWeight,Pointer(@Initial));
- end;
- function adduse(var n: tnode; arg: pointer): foreachnoderesult;
- var
- usesum : PDFASet absolute arg;
- begin
- if assigned(n.optinfo) then
- DFASetIncludeSet(usesum^,n.optinfo^.use);
- Result:=fen_false;
- end;
- procedure CalcUseSum(p : tnode);
- var
- usesum : PDFASet;
- begin
- p.allocoptinfo;
- usesum:[email protected]^.usesum;
- if not assigned(usesum^) then
- foreachnodestatic(pm_postprocess,p,@adduse,usesum);
- end;
- function has_life_info(n : tnode) : boolean;
- begin
- result:=assigned(n) and assigned(n.optinfo) and
- assigned(n.optinfo^.life);
- end;
- end.
|