fpc/compiler/new/aopt.pas
Jonas Maebe 56524f33df + compilable!
+ dataflow analyzer finished
  + start of CSE units
  + aoptbase which contains a base object for all optimizer objects
  * some constants and type definitions moved around to avoid circular
    dependencies
  * moved some methods from base objects to specialized objects because
    they're not used anywhere else
1999-08-18 14:32:20 +00:00

249 lines
8.1 KiB
ObjectPascal

{
$Id$
Copyright (c) 1999 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 Aasm, cobjects, aoptobj, aoptcpud, aoptcpub {aoptcs, aoptpeep} ;
Type
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;
Implementation
uses cpuinfo, globtype, globals, tainst;
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;
End.
{Virtual methods, most have to be overridden by processor dependent methods}
{
$Log$
Revision 1.3 1999-08-18 14:32:20 jonas
+ compilable!
+ dataflow analyzer finished
+ start of CSE units
+ aoptbase which contains a base object for all optimizer objects
* some constants and type definitions moved around to avoid circular
dependencies
* moved some methods from base objects to specialized objects because
they're not used anywhere else
Revision 1.2 1999/08/09 14:07:22 jonas
commit.msg
Revision 1.1 1999/08/08 13:24:50 jonas
+ added copyright header/GNU license info
* made the assembler optimizer almost completely OOP
* some code style clean up and extra comments
* moved from the new/aopt to the /new and /new/i386 dirs
}