123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- {
- $Id$
- Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
- Development Team
- This unit contains the interface routines between the code generator
- and the optimizer.
- 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 aopt;
- Interface
- Uses Aasmbase,aasmtai,aasmcpu, cobjects, aoptobj, aoptcpud, aoptcpub {aoptcs, aoptpeep} ;
- Type
- PAsmOptimizer = ^TAsmOptimizer;
- TAsmOptimizer = Object(TAoptObj)
- { _AsmL is the PAasmOutpout list that has to be optimized }
- Constructor Init(_AsmL: PAasmOutput);
- { call the necessary optimizer procedures }
- Procedure Optimize;
- Destructor Done;
- private
- Function FindLoHiLabels: Pai;
- Procedure BuildLabelTableAndFixRegAlloc;
- End;
- procedure Optimize(AsmL:Paasmoutput);
- Implementation
- uses cpuinfo, globtype, globals;
- Constructor TAsmOptimizer.Init(_AsmL: PAasmOutput);
- Begin
- AsmL := _AsmL;
- {setup labeltable, always necessary}
- New(LabelInfo);
- LabelInfo^.LowLabel := High(AWord);
- LabelInfo^.HighLabel := 0;
- LabelInfo^.LabelDif := 0;
- End;
- Function TAsmOptimizer.FindLoHiLabels: Pai;
- { Walks through the paasmlist to find the lowest and highest label number. }
- { Returns the last Pai object of the current block }
- Var LabelFound: Boolean;
- P: Pai;
- Begin
- LabelFound := False;
- P := BlockStart;
- With LabelInfo^ Do
- Begin
- While Assigned(P) And
- ((P^.typ <> Ait_Marker) Or
- (Pai_Marker(P)^.Kind <> AsmBlockStart)) Do
- Begin
- If (Pai(p)^.typ = ait_label) Then
- If (Pai_Label(p)^.l^.is_used) Then
- Begin
- LabelFound := True;
- If (Pai_Label(p)^.l^.labelnr < LowLabel) Then
- LowLabel := Pai_Label(p)^.l^.labelnr;
- If (Pai_Label(p)^.l^.labelnr > HighLabel) Then
- HighLabel := Pai_Label(p)^.l^.labelnr
- End;
- GetNextInstruction(p, p)
- End;
- FindLoHiLabels := p;
- If LabelFound
- Then LabelDif := HighLabel-LowLabel+1
- Else LabelDif := 0
- End
- End;
- Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
- { Builds a table with the locations of the labels in the paasmoutput. }
- { Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
- Var p, hp1, hp2: Pai;
- UsedRegs: TRegSet;
- Begin
- UsedRegs := [];
- With LabelInfo^ Do
- If (LabelDif <> 0) Then
- Begin
- GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
- FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
- p := BlockStart;
- While (P <> BlockEnd) Do
- Begin
- Case p^.typ Of
- ait_Label:
- If Pai_Label(p)^.l^.is_used Then
- LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
- ait_regAlloc:
- begin
- if PairegAlloc(p)^.Allocation then
- Begin
- If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
- UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
- Else
- Begin
- hp1 := p;
- hp2 := nil;
- While GetLastInstruction(hp1, hp1) And
- Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
- hp2 := hp1;
- If hp2 <> nil Then
- Begin
- hp1 := New(PaiRegAlloc, DeAlloc(PaiRegAlloc(p)^.Reg));
- InsertLLItem(Pai(hp2^.previous), hp2, hp1);
- End;
- End;
- End
- else
- Begin
- UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg];
- hp1 := p;
- hp2 := nil;
- While Not(FindRegAlloc(PaiRegAlloc(p)^.Reg, Pai(hp1^.Next))) And
- GetNextInstruction(hp1, hp1) And
- RegInInstruction(PaiRegAlloc(p)^.Reg, hp1) Do
- hp2 := hp1;
- If hp2 <> nil Then
- Begin
- hp1 := Pai(p^.previous);
- AsmL^.Remove(p);
- InsertLLItem(hp2, Pai(hp2^.Next), p);
- p := hp1;
- End
- End
- End
- End
- End;
- P := Pai(p^.Next);
- While Assigned(p) And
- (p^.typ in (SkipInstr - [ait_regalloc])) Do
- P := Pai(P^.Next)
- End
- End;
- Procedure TAsmOptimizer.Optimize;
- Var HP: Pai;
- DFA: PAOptDFACpu;
- Begin
- BlockStart := Pai(AsmL^.First);
- While Assigned(BlockStart) Do
- Begin
- { Initialize BlockEnd and the LabelInfo (low and high label) }
- BlockEnd := FindLoHiLabels;
- { initialize the LabelInfo (labeltable) and fix the regalloc info }
- BuildLabelTableAndFixRegAlloc;
- { peephole optimizations, twice because you can't do them all in one }
- { pass }
- { PeepHoleOptPass1;
- PeepHoleOptPass1;}
- If (cs_slowoptimize in aktglobalswitches) Then
- Begin
- New(DFA,Init(AsmL,BlockStart,BlockEnd,LabelInfo));
- { data flow analyzer }
- DFA^.DoDFA;
- { common subexpression elimination }
- { CSE;}
- End;
- { more peephole optimizations }
- { PeepHoleOptPass2;}
- {dispose labeltabel}
- If Assigned(LabelInfo^.LabelTable) Then
- Begin
- Dispose(LabelInfo^.LabelTable);
- LabelInfo := Nil
- End;
- { continue where we left off, BlockEnd is either the start of an }
- { assembler block or nil}
- BlockStart := BlockEnd;
- While Assigned(BlockStart) And
- (BlockStart^.typ = ait_Marker) And
- (Pai_Marker(BlockStart)^.Kind = AsmBlockStart) Do
- Begin
- { we stopped at an assembler block, so skip it }
- While GetNextInstruction(BlockStart, BlockStart) And
- ((BlockStart^.Typ <> Ait_Marker) Or
- (Pai_Marker(Blockstart)^.Kind <> AsmBlockEnd)) Do;
- { blockstart now contains a pai_marker(asmblockend) }
- If Not(GetNextInstruction(BlockStart, HP) And
- ((HP^.typ <> ait_Marker) Or
- (Pai_Marker(HP)^.Kind <> AsmBlockStart)
- )
- ) Then
- {skip the next assembler block }
- BlockStart := HP;
- { otherwise there is no assembler block anymore after the current }
- { one, so optimize the next block of "normal" instructions }
- End
- End;
- End;
- Destructor TAsmOptimizer.Done;
- Begin
- Dispose(LabelInfo)
- End;
- procedure Optimize(AsmL:Paasmoutput);
- var
- p : PAsmOptimizer;
- begin
- new(p,Init(AsmL));
- p^.Optimize;
- dispose(p,Done);
- end;
- End.
- {Virtual methods, most have to be overridden by processor dependent methods}
- {
- $Log$
- Revision 1.5 2002-07-01 18:46:21 peter
- * internal linker
- * reorganized aasm layer
- Revision 1.4 2002/05/18 13:34:05 peter
- * readded missing revisions
- Revision 1.3 2002/05/16 19:46:34 carl
- + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
- + try to fix temp allocation (still in ifdef)
- + generic constructor calls
- + start of tassembler / tmodulebase class cleanup
- }
|