mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 03:49:05 +02:00
* fixed generic optimizer
* enabled generic optimizer for sparc
This commit is contained in:
parent
86f78c7300
commit
e04b172854
@ -1,6 +1,6 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2002 by Jonas Maebe, member of the Free Pascal
|
||||
Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
|
||||
Development Team
|
||||
|
||||
This unit contains the interface routines between the code generator
|
||||
@ -24,224 +24,238 @@
|
||||
}
|
||||
Unit aopt;
|
||||
|
||||
Interface
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
Uses Aasmbase,aasmtai,aasmcpu, cobjects, aoptobj, aoptcpud, aoptcpub {aoptcs, aoptpeep} ;
|
||||
Interface
|
||||
|
||||
Type
|
||||
PAsmOptimizer = ^TAsmOptimizer;
|
||||
TAsmOptimizer = Object(TAoptObj)
|
||||
Uses
|
||||
aasmbase,aasmtai,aasmcpu,
|
||||
aoptobj;
|
||||
|
||||
{ _AsmL is the PAasmOutpout list that has to be optimized }
|
||||
Constructor Init(_AsmL: PAasmOutput);
|
||||
Type
|
||||
TAsmOptimizer = class(TAoptObj)
|
||||
|
||||
{ call the necessary optimizer procedures }
|
||||
Procedure Optimize;
|
||||
Destructor Done;
|
||||
{ _AsmL is the PAasmOutpout list that has to be optimized }
|
||||
Constructor create(_AsmL: taasmoutput);
|
||||
|
||||
private
|
||||
{ call the necessary optimizer procedures }
|
||||
Procedure Optimize;
|
||||
Destructor destroy;override;
|
||||
|
||||
Function FindLoHiLabels: Pai;
|
||||
Procedure BuildLabelTableAndFixRegAlloc;
|
||||
private
|
||||
Function FindLoHiLabels: tai;
|
||||
Procedure BuildLabelTableAndFixRegAlloc;
|
||||
End;
|
||||
|
||||
End;
|
||||
var
|
||||
casmoptimizer : class of tasmoptimizer;
|
||||
|
||||
procedure Optimize(AsmL:Paasmoutput);
|
||||
procedure Optimize(AsmL:taasmoutput);
|
||||
|
||||
Implementation
|
||||
|
||||
Implementation
|
||||
uses
|
||||
cpuinfo, globtype, globals,
|
||||
aoptda,aoptcpu,aoptcpud;
|
||||
|
||||
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
|
||||
Constructor TAsmOptimizer.create(_AsmL: taasmoutput);
|
||||
Begin
|
||||
GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
|
||||
FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
|
||||
p := BlockStart;
|
||||
While (P <> BlockEnd) Do
|
||||
inherited create(_asml,nil,nil,nil);
|
||||
{setup labeltable, always necessary}
|
||||
New(LabelInfo);
|
||||
LabelInfo^.LowLabel := High(AWord);
|
||||
LabelInfo^.HighLabel := 0;
|
||||
LabelInfo^.LabelDif := 0;
|
||||
LabelInfo^.LabelTable:=nil;
|
||||
End;
|
||||
|
||||
Function TAsmOptimizer.FindLoHiLabels: tai;
|
||||
{ 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: tai;
|
||||
Begin
|
||||
LabelFound := False;
|
||||
P := BlockStart;
|
||||
With LabelInfo^ 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
|
||||
While Assigned(P) And
|
||||
((P.typ <> Ait_Marker) Or
|
||||
(tai_Marker(P).Kind <> AsmBlockStart)) Do
|
||||
Begin
|
||||
If (p.typ = ait_label) Then
|
||||
If (tai_Label(p).l.is_used) Then
|
||||
Begin
|
||||
If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
|
||||
UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
|
||||
Else
|
||||
LabelFound := True;
|
||||
If (tai_Label(p).l.labelnr < LowLabel) Then
|
||||
LowLabel := tai_Label(p).l.labelnr;
|
||||
If (tai_Label(p).l.labelnr > HighLabel) Then
|
||||
HighLabel := tai_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 taasmoutput. }
|
||||
{ Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
|
||||
Var p, hp1, hp2: tai;
|
||||
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 tai_label(p).l.is_used Then
|
||||
LabelTable^[tai_label(p).l.labelnr-LowLabel].PaiObj := p;
|
||||
ait_regAlloc:
|
||||
begin
|
||||
{!!!!!!!!!
|
||||
if tai_regalloc(p).ratype=ra_alloc then
|
||||
Begin
|
||||
If Not(tai_regalloc(p).Reg in UsedRegs) Then
|
||||
UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
|
||||
Else
|
||||
Begin
|
||||
hp1 := p;
|
||||
hp2 := nil;
|
||||
While GetLastInstruction(hp1, hp1) And
|
||||
Not(RegInInstruction(tai_regalloc(p).Reg, hp1)) Do
|
||||
hp2:=hp1;
|
||||
If hp2<>nil Then
|
||||
Begin
|
||||
hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
|
||||
InsertLLItem(tai(hp2.previous), hp2, hp1);
|
||||
End;
|
||||
End;
|
||||
End
|
||||
else
|
||||
Begin
|
||||
UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
|
||||
hp1 := p;
|
||||
hp2 := nil;
|
||||
While GetLastInstruction(hp1, hp1) And
|
||||
Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
|
||||
While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
|
||||
GetNextInstruction(hp1, hp1) And
|
||||
RegInInstruction(tai_regalloc(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;
|
||||
hp1 := tai(p.previous);
|
||||
AsmL.Remove(p);
|
||||
InsertLLItem(hp2, tai(hp2.Next), p);
|
||||
p := hp1;
|
||||
End
|
||||
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;
|
||||
P := tai(p.Next);
|
||||
While Assigned(p) And
|
||||
(p.typ in (SkipInstr - [ait_regalloc])) Do
|
||||
P := tai(P.Next)
|
||||
End
|
||||
End;
|
||||
End;
|
||||
|
||||
Destructor TAsmOptimizer.Done;
|
||||
Begin
|
||||
Dispose(LabelInfo)
|
||||
End;
|
||||
|
||||
|
||||
procedure Optimize(AsmL:Paasmoutput);
|
||||
var
|
||||
p : PAsmOptimizer;
|
||||
|
||||
Procedure TAsmOptimizer.Optimize;
|
||||
Var
|
||||
HP: tai;
|
||||
pass: longint;
|
||||
Begin
|
||||
pass:=0;
|
||||
BlockStart := tai(AsmL.First);
|
||||
While Assigned(BlockStart) Do
|
||||
Begin
|
||||
if pass = 0 then
|
||||
PrePeepHoleOpts;
|
||||
{ Peephole optimizations }
|
||||
PeepHoleOptPass1;
|
||||
{ Only perform them twice in the first pass }
|
||||
if pass = 0 then
|
||||
PeepHoleOptPass1;
|
||||
If (cs_slowoptimize in aktglobalswitches) Then
|
||||
Begin
|
||||
// DFA:=TAOptDFACpu.Create(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
|
||||
(tai_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
|
||||
(tai_Marker(Blockstart).Kind <> AsmBlockEnd)) Do;
|
||||
{ blockstart now contains a tai_marker(asmblockend) }
|
||||
If Not(GetNextInstruction(BlockStart, HP) And
|
||||
((HP.typ <> ait_Marker) Or
|
||||
(tai_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.Destroy;
|
||||
Begin
|
||||
Dispose(LabelInfo)
|
||||
End;
|
||||
|
||||
|
||||
procedure Optimize(AsmL:taasmoutput);
|
||||
var
|
||||
p : TAsmOptimizer;
|
||||
begin
|
||||
p:=casmoptimizer.Create(AsmL);
|
||||
p.Optimize;
|
||||
p.free
|
||||
end;
|
||||
|
||||
|
||||
begin
|
||||
new(p,Init(AsmL));
|
||||
p^.Optimize;
|
||||
dispose(p,Done);
|
||||
end;
|
||||
|
||||
|
||||
End.
|
||||
casmoptimizer:=TAsmOptimizer;
|
||||
end.
|
||||
|
||||
{Virtual methods, most have to be overridden by processor dependent methods}
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.6 2004-06-20 08:55:28 florian
|
||||
* logs truncated
|
||||
Revision 1.7 2004-10-30 15:21:37 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.6 2004/06/20 08:55:28 florian
|
||||
* logs truncated
|
||||
}
|
||||
|
@ -23,246 +23,246 @@
|
||||
}
|
||||
unit aoptbase;
|
||||
|
||||
Interface
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
uses aasmbase,aasmcpu,aasmtai,
|
||||
cpubase;
|
||||
interface
|
||||
|
||||
{ the number of tai objects processed by an optimizer object since the last }
|
||||
{ time a register was modified }
|
||||
Type TInstrSinceLastMod = Array[LoGPReg..HiGPReg] of byte;
|
||||
uses
|
||||
aasmbase,aasmcpu,aasmtai,
|
||||
cpubase,
|
||||
cgbase;
|
||||
|
||||
{ the TAopBase object implements the basic methods that most other }
|
||||
{ assembler optimizer objects require }
|
||||
Type
|
||||
TAoptBase = Object
|
||||
{ processor independent methods }
|
||||
Type
|
||||
{ the number of tai objects processed by an optimizer object since the last
|
||||
time a register was modified }
|
||||
{ size at each dimension depends on the registers of this type }
|
||||
TInstrSinceLastMod = Array[tregistertype] of pbyte;
|
||||
|
||||
constructor init;
|
||||
destructor done;
|
||||
{ returns true if register Reg is used by instruction p1 }
|
||||
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
||||
{ returns true if register Reg occurs in operand op }
|
||||
Function RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||
{ returns true if register Reg is used in the reference Ref }
|
||||
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||
{ the TAopBase object implements the basic methods that most other }
|
||||
{ assembler optimizer objects require }
|
||||
Type
|
||||
TAoptBase = class
|
||||
{ processor independent methods }
|
||||
|
||||
{ returns true if the references are completely equal }
|
||||
{Function RefsEqual(Const R1, R2: TReference): Boolean;}
|
||||
constructor create;
|
||||
destructor destroy;override;
|
||||
{ returns true if register Reg is used by instruction p1 }
|
||||
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
||||
{ returns true if register Reg occurs in operand op }
|
||||
Function RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||
{ returns true if register Reg is used in the reference Ref }
|
||||
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||
|
||||
{ gets the next tai object after current that contains info relevant }
|
||||
{ to the optimizer in p1. If there is none, it returns false and }
|
||||
{ sets p1 to nil }
|
||||
Function GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
||||
{ gets the previous tai object after current that contains info }
|
||||
{ relevant to the optimizer in last. If there is none, it retuns }
|
||||
{ false and sets last to nil }
|
||||
Function GetLastInstruction(Current: tai; Var Last: tai): Boolean;
|
||||
{ returns true if the references are completely equal }
|
||||
{Function RefsEqual(Const R1, R2: TReference): Boolean;}
|
||||
|
||||
{ gets the next tai object after current that contains info relevant }
|
||||
{ to the optimizer in p1. If there is none, it returns false and }
|
||||
{ sets p1 to nil }
|
||||
Function GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
||||
{ gets the previous tai object after current that contains info }
|
||||
{ relevant to the optimizer in last. If there is none, it retuns }
|
||||
{ false and sets last to nil }
|
||||
Function GetLastInstruction(Current: tai; Var Last: tai): Boolean;
|
||||
|
||||
|
||||
{ processor dependent methods }
|
||||
{ processor dependent methods }
|
||||
|
||||
{ returns the maximum width component of Reg. Only has to be }
|
||||
{ overridden for the 80x86 (afaik) }
|
||||
Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
|
||||
{ returns true if Reg1 and Reg2 are of the samae width. Only has to }
|
||||
{ overridden for the 80x86 (afaik) }
|
||||
Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
|
||||
{ returns whether P is a load instruction (load contents from a }
|
||||
{ memory location or (register) variable into a register) }
|
||||
Function IsLoadMemReg(p: tai): Boolean; Virtual;
|
||||
{ returns whether P is a load constant instruction (load a constant }
|
||||
{ into a register) }
|
||||
Function IsLoadConstReg(p: tai): Boolean; Virtual;
|
||||
{ returns whether P is a store instruction (store contents from a }
|
||||
{ register to a memory location or to a (register) variable) }
|
||||
Function IsStoreRegMem(p: tai): Boolean; Virtual;
|
||||
{ returns the maximum width component of Reg. Only has to be }
|
||||
{ overridden for the 80x86 (afaik) }
|
||||
Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
|
||||
{ returns true if Reg1 and Reg2 are of the samae width. Only has to }
|
||||
{ overridden for the 80x86 (afaik) }
|
||||
Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
|
||||
{ returns whether P is a load instruction (load contents from a }
|
||||
{ memory location or (register) variable into a register) }
|
||||
Function IsLoadMemReg(p: tai): Boolean; Virtual;
|
||||
{ returns whether P is a load constant instruction (load a constant }
|
||||
{ into a register) }
|
||||
Function IsLoadConstReg(p: tai): Boolean; Virtual;
|
||||
{ returns whether P is a store instruction (store contents from a }
|
||||
{ register to a memory location or to a (register) variable) }
|
||||
Function IsStoreRegMem(p: tai): Boolean; Virtual;
|
||||
|
||||
{ create a paicpu Object that loads the contents of reg1 into reg2 }
|
||||
Function a_load_reg_reg(reg1, reg2: TRegister): taicpu; Virtual;
|
||||
{ create a paicpu Object that loads the contents of reg1 into reg2 }
|
||||
Function a_load_reg_reg(reg1, reg2: TRegister): taicpu; Virtual;
|
||||
|
||||
end;
|
||||
|
||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
||||
end;
|
||||
|
||||
|
||||
Implementation
|
||||
implementation
|
||||
|
||||
uses globals, aoptcpub, cpuinfo;
|
||||
uses
|
||||
globtype,globals, aoptcpub, cpuinfo;
|
||||
|
||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
||||
Begin
|
||||
RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup)
|
||||
And (R1.Base = R2.Base)
|
||||
{$ifdef RefsHaveindex}
|
||||
And (R1.Index = R2.Index)
|
||||
{$endif RefsHaveindex}
|
||||
{$ifdef RefsHaveScale}
|
||||
And (R1.ScaleFactor = R2.ScaleFactor)
|
||||
{$endif RefsHaveScale}
|
||||
And (R1.Symbol = R2.Symbol)
|
||||
{$ifdef RefsHaveSegment}
|
||||
And (R1.Segment = R2.Segment)
|
||||
{$endif RefsHaveSegment}
|
||||
;
|
||||
End;
|
||||
constructor taoptbase.create;
|
||||
begin
|
||||
inherited create;
|
||||
end;
|
||||
|
||||
|
||||
constructor taoptbase.init;
|
||||
begin
|
||||
end;
|
||||
|
||||
destructor taoptbase.done;
|
||||
begin
|
||||
end;
|
||||
|
||||
Function TAOptBase.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
||||
Var Count: AWord;
|
||||
TmpResult: Boolean;
|
||||
Begin
|
||||
TmpResult := False;
|
||||
Count := 0;
|
||||
If (p1.typ = ait_instruction) Then
|
||||
Repeat
|
||||
TmpResult := RegInOp(Reg, PInstr(p1)^.oper[Count]);
|
||||
Inc(Count)
|
||||
Until (Count = MaxOps) or TmpResult;
|
||||
RegInInstruction := TmpResult
|
||||
End;
|
||||
destructor taoptbase.destroy;
|
||||
begin
|
||||
inherited destroy;
|
||||
end;
|
||||
|
||||
|
||||
Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||
Begin
|
||||
Case op.typ Of
|
||||
Top_Reg: RegInOp := Reg = op.reg;
|
||||
Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
|
||||
Else RegInOp := False
|
||||
End
|
||||
End;
|
||||
Function TAOptBase.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
||||
Var Count: AWord;
|
||||
TmpResult: Boolean;
|
||||
Begin
|
||||
TmpResult := False;
|
||||
Count := 0;
|
||||
If (p1.typ = ait_instruction) Then
|
||||
Repeat
|
||||
TmpResult := RegInOp(Reg, PInstr(p1)^.oper[Count]^);
|
||||
Inc(Count)
|
||||
Until (Count = MaxOps) or TmpResult;
|
||||
RegInInstruction := TmpResult
|
||||
End;
|
||||
|
||||
|
||||
Function TAOptBase.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||
Begin
|
||||
Reg := RegMaxSize(Reg);
|
||||
RegInRef := (Ref.Base = Reg)
|
||||
{$ifdef RefsHaveIndexReg}
|
||||
Or (Ref.Index = Reg)
|
||||
{$endif RefsHaveIndexReg}
|
||||
End;
|
||||
|
||||
Function TAOptBase.GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
||||
Begin
|
||||
Repeat
|
||||
Current := tai(Current.Next);
|
||||
While Assigned(Current) And
|
||||
((Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used))) Do
|
||||
Current := tai(Current.Next);
|
||||
If Assigned(Current) And
|
||||
(Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = NoPropInfoStart) Then
|
||||
Begin
|
||||
While Assigned(Current) And
|
||||
((Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoEnd)) Do
|
||||
Current := Tai(Current.Next);
|
||||
End;
|
||||
Until Not(Assigned(Current)) Or
|
||||
(Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoEnd);
|
||||
Next := Current;
|
||||
If Assigned(Current) And
|
||||
Not((Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used)))
|
||||
Then GetNextInstruction := True
|
||||
Else
|
||||
Begin
|
||||
Next := Nil;
|
||||
GetNextInstruction := False;
|
||||
End;
|
||||
End;
|
||||
|
||||
Function TAOptBase.GetLastInstruction(Current: tai; Var Last: tai): Boolean;
|
||||
Begin
|
||||
Repeat
|
||||
Current := Tai(Current.previous);
|
||||
While Assigned(Current) And
|
||||
(((Current.typ = ait_Marker) And
|
||||
Not(Tai_Marker(Current).Kind in [AsmBlockEnd,NoPropInfoEnd])) or
|
||||
(Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used))) Do
|
||||
Current := Tai(Current.previous);
|
||||
If Assigned(Current) And
|
||||
(Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = NoPropInfoEnd) Then
|
||||
Begin
|
||||
While Assigned(Current) And
|
||||
((Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoStart)) Do
|
||||
Current := Tai(Current.previous);
|
||||
End;
|
||||
Until Not(Assigned(Current)) Or
|
||||
(Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoStart);
|
||||
If Not(Assigned(Current)) or
|
||||
(Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used)) or
|
||||
((Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = AsmBlockEnd))
|
||||
Then
|
||||
Begin
|
||||
Last := Nil;
|
||||
GetLastInstruction := False
|
||||
Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||
Begin
|
||||
Case op.typ Of
|
||||
Top_Reg: RegInOp := Reg = op.reg;
|
||||
Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
|
||||
Else RegInOp := False
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
Last := Current;
|
||||
GetLastInstruction := True;
|
||||
End;
|
||||
End;
|
||||
End;
|
||||
|
||||
|
||||
{ ******************* Processor dependent stuff *************************** }
|
||||
Function TAOptBase.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||
Begin
|
||||
Reg := RegMaxSize(Reg);
|
||||
RegInRef := (Ref.Base = Reg)
|
||||
{$ifdef RefsHaveIndexReg}
|
||||
Or (Ref.Index = Reg)
|
||||
{$endif RefsHaveIndexReg}
|
||||
End;
|
||||
|
||||
Function TAOptBase.RegMaxSize(Reg: TRegister): TRegister;
|
||||
Begin
|
||||
RegMaxSize := Reg
|
||||
End;
|
||||
Function TAOptBase.GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
||||
Begin
|
||||
Repeat
|
||||
Current := tai(Current.Next);
|
||||
While Assigned(Current) And
|
||||
((Current.typ In SkipInstr) or
|
||||
{$ifdef SPARC}
|
||||
((Current.typ=ait_instruction) and
|
||||
(taicpu(Current).opcode=A_NOP)
|
||||
) or
|
||||
{$endif SPARC}
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used))) Do
|
||||
Current := tai(Current.Next);
|
||||
If Assigned(Current) And
|
||||
(Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = NoPropInfoStart) Then
|
||||
Begin
|
||||
While Assigned(Current) And
|
||||
((Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoEnd)) Do
|
||||
Current := Tai(Current.Next);
|
||||
End;
|
||||
Until Not(Assigned(Current)) Or
|
||||
(Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoEnd);
|
||||
Next := Current;
|
||||
If Assigned(Current) And
|
||||
Not((Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used)))
|
||||
Then GetNextInstruction := True
|
||||
Else
|
||||
Begin
|
||||
Next := Nil;
|
||||
GetNextInstruction := False;
|
||||
End;
|
||||
End;
|
||||
|
||||
Function TAOptBase.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
|
||||
Begin
|
||||
RegsSameSize := True
|
||||
End;
|
||||
Function TAOptBase.GetLastInstruction(Current: tai; Var Last: tai): Boolean;
|
||||
Begin
|
||||
Repeat
|
||||
Current := Tai(Current.previous);
|
||||
While Assigned(Current) And
|
||||
(((Current.typ = ait_Marker) And
|
||||
Not(Tai_Marker(Current).Kind in [AsmBlockEnd,NoPropInfoEnd])) or
|
||||
(Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used))) Do
|
||||
Current := Tai(Current.previous);
|
||||
If Assigned(Current) And
|
||||
(Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = NoPropInfoEnd) Then
|
||||
Begin
|
||||
While Assigned(Current) And
|
||||
((Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoStart)) Do
|
||||
Current := Tai(Current.previous);
|
||||
End;
|
||||
Until Not(Assigned(Current)) Or
|
||||
(Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> NoPropInfoStart);
|
||||
If Not(Assigned(Current)) or
|
||||
(Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
Not(Tai_Label(Current).l.is_used)) or
|
||||
((Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = AsmBlockEnd))
|
||||
Then
|
||||
Begin
|
||||
Last := Nil;
|
||||
GetLastInstruction := False
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
Last := Current;
|
||||
GetLastInstruction := True;
|
||||
End;
|
||||
End;
|
||||
|
||||
Function TAOptBase.IsLoadMemReg(p: tai): Boolean;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
|
||||
Function TAOptBase.IsLoadConstReg(p: tai): Boolean;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
{ ******************* Processor dependent stuff *************************** }
|
||||
|
||||
Function TAOptBase.IsStoreRegMem(p: tai): Boolean;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
Function TAOptBase.RegMaxSize(Reg: TRegister): TRegister;
|
||||
Begin
|
||||
RegMaxSize := Reg
|
||||
End;
|
||||
|
||||
Function TAoptBase.a_load_reg_reg(reg1, reg2: TRegister): taicpu;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
Function TAOptBase.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
|
||||
Begin
|
||||
RegsSameSize := True
|
||||
End;
|
||||
|
||||
End.
|
||||
Function TAOptBase.IsLoadMemReg(p: tai): Boolean;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
|
||||
Function TAOptBase.IsLoadConstReg(p: tai): Boolean;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
|
||||
Function TAOptBase.IsStoreRegMem(p: tai): Boolean;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
|
||||
Function TAoptBase.a_load_reg_reg(reg1, reg2: TRegister): taicpu;
|
||||
Begin
|
||||
Abstract
|
||||
End;
|
||||
|
||||
end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.7 2004-06-20 08:55:28 florian
|
||||
Revision 1.8 2004-10-30 15:21:37 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.7 2004/06/20 08:55:28 florian
|
||||
* logs truncated
|
||||
|
||||
}
|
||||
|
@ -24,164 +24,177 @@
|
||||
}
|
||||
Unit aoptda;
|
||||
|
||||
Interface
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
uses aasm, cpubase, aoptcpub, aoptbase, aoptcpu;
|
||||
Interface
|
||||
|
||||
Type
|
||||
TAOptDFA = Object(TAoptCpu)
|
||||
{ uses the same constructor as TAoptCpu = constructor from TAoptObj }
|
||||
uses
|
||||
cpubase,cgbase,
|
||||
aasmbase,aasmtai,aasmcpu,
|
||||
aoptcpub, aoptbase;
|
||||
|
||||
{ gathers the information regarding the contents of every register }
|
||||
{ at the end of every instruction }
|
||||
Procedure DoDFA;
|
||||
Type
|
||||
TAOptDFA = class
|
||||
{ uses the same constructor as TAoptCpu = constructor from TAoptObj }
|
||||
|
||||
{ handles the processor dependent dataflow analizing }
|
||||
Procedure CpuDFA(p: PInstr); Virtual;
|
||||
{ gathers the information regarding the contents of every register }
|
||||
{ at the end of every instruction }
|
||||
Procedure DoDFA;
|
||||
|
||||
{ How many instructions are between the current instruction and the }
|
||||
{ last one that modified the register }
|
||||
InstrSinceLastMod: TInstrSinceLastMod;
|
||||
{ handles the processor dependent dataflow analizing }
|
||||
Procedure CpuDFA(p: PInstr); Virtual;
|
||||
|
||||
{ convert a TInsChange value into the corresponding register }
|
||||
Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
|
||||
{ returns whether the instruction P reads from register Reg }
|
||||
Function RegReadByInstr(Reg: TRegister; p: Pai): Boolean; Virtual;
|
||||
End;
|
||||
{ How many instructions are between the current instruction and the }
|
||||
{ last one that modified the register }
|
||||
InstrSinceLastMod: TInstrSinceLastMod;
|
||||
|
||||
Implementation
|
||||
{ convert a TInsChange value into the corresponding register }
|
||||
//!!!!!!!!!! Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
|
||||
{ returns whether the instruction P reads from register Reg }
|
||||
Function RegReadByInstr(Reg: TRegister; p: tai): Boolean; Virtual;
|
||||
End;
|
||||
|
||||
uses globals, aoptobj;
|
||||
Implementation
|
||||
|
||||
Procedure TAOptDFA.DoDFA;
|
||||
{ Analyzes the Data Flow of an assembler list. Analyses the reg contents }
|
||||
{ for the instructions between blockstart and blockend. Returns the last pai }
|
||||
{ which has been processed }
|
||||
Var
|
||||
CurProp: PPaiProp;
|
||||
UsedRegs: TUsedRegs;
|
||||
p, hp, NewBlockStart : Pai;
|
||||
TmpReg: TRegister;
|
||||
Begin
|
||||
p := BlockStart;
|
||||
UsedRegs.init;
|
||||
UsedRegs.Update(p);
|
||||
NewBlockStart := SkipHead(p);
|
||||
{ done implicitely by the constructor
|
||||
FillChar(InstrSinceLastMod, SizeOf(InstrSinceLastMod), 0); }
|
||||
While (P <> BlockEnd) Do
|
||||
uses
|
||||
globals, aoptobj;
|
||||
|
||||
Procedure TAOptDFA.DoDFA;
|
||||
{ Analyzes the Data Flow of an assembler list. Analyses the reg contents }
|
||||
{ for the instructions between blockstart and blockend. Returns the last pai }
|
||||
{ which has been processed }
|
||||
Var
|
||||
CurProp: TPaiProp;
|
||||
UsedRegs: TUsedRegs;
|
||||
p, hp, NewBlockStart : tai;
|
||||
TmpReg: TRegister;
|
||||
Begin
|
||||
CurProp := New(PPaiProp, init);
|
||||
If (p <> NewBlockStart) Then
|
||||
{!!!!!!!!!!
|
||||
p := BlockStart;
|
||||
UsedRegs.Create;
|
||||
UsedRegs.Update(p);
|
||||
NewBlockStart := SkipHead(p);
|
||||
{ done implicitely by the constructor
|
||||
FillChar(InstrSinceLastMod, SizeOf(InstrSinceLastMod), 0); }
|
||||
While (P <> BlockEnd) Do
|
||||
Begin
|
||||
GetLastInstruction(p, hp);
|
||||
CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
|
||||
{ !!!!!!!!!!!! }
|
||||
{$ifdef x86}
|
||||
CurProp^.CondRegs.Flags :=
|
||||
PPaiProp(hp^.OptInfo)^.CondRegs.Flags;
|
||||
{$endif}
|
||||
End;
|
||||
CurProp^.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
|
||||
UsedRegs.Update(Pai(p^.Next));
|
||||
PPaiProp(p^.OptInfo) := CurProp;
|
||||
For TmpReg := LoGPReg To HiGPReg Do
|
||||
Inc(InstrSinceLastMod[TmpReg]);
|
||||
Case p^.typ Of
|
||||
ait_label:
|
||||
If (Pai_label(p)^.l^.is_used) Then
|
||||
CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
||||
{$ifdef GDB}
|
||||
ait_stabs, ait_stabn, ait_stab_function_name:;
|
||||
{$endif GDB}
|
||||
ait_instruction:
|
||||
if not(PInstr(p)^.is_jmp) then
|
||||
begin
|
||||
If IsLoadMemReg(p) Then
|
||||
Begin
|
||||
CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
|
||||
TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
|
||||
If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
|
||||
(CurProp^.GetRegContentType(TmpReg) = Con_Ref) Then
|
||||
CurProp:=TPaiProp.Create;
|
||||
If (p <> NewBlockStart) Then
|
||||
Begin
|
||||
GetLastInstruction(p, hp);
|
||||
CurProp.Regs := TPaiProp(hp.OptInfo).Regs;
|
||||
{ !!!!!!!!!!!! }
|
||||
{$ifdef x86}
|
||||
CurProp.CondRegs.Flags :=
|
||||
TPaiProp(hp.OptInfo).CondRegs.Flags;
|
||||
{$endif}
|
||||
End;
|
||||
CurProp.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
|
||||
UsedRegs.Update(tai(p.Next));
|
||||
TPaiProp(p.OptInfo) := CurProp;
|
||||
For TmpReg := LoGPReg To HiGPReg Do
|
||||
Inc(InstrSinceLastMod[TmpReg]);
|
||||
Case p^.typ Of
|
||||
ait_label:
|
||||
If (Pai_label(p)^.l^.is_used) Then
|
||||
CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
||||
{$ifdef GDB}
|
||||
ait_stabs, ait_stabn, ait_stab_function_name:;
|
||||
{$endif GDB}
|
||||
ait_instruction:
|
||||
if not(PInstr(p)^.is_jmp) then
|
||||
begin
|
||||
If IsLoadMemReg(p) Then
|
||||
Begin
|
||||
{ a load based on the value this register already }
|
||||
{ contained }
|
||||
CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
|
||||
TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
|
||||
If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
|
||||
(CurProp^.GetRegContentType(TmpReg) = Con_Ref) Then
|
||||
Begin
|
||||
{ a load based on the value this register already }
|
||||
{ contained }
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
CurProp^.IncWState(TmpReg);
|
||||
{also store how many instructions are part of the }
|
||||
{ sequence in the first instruction's PPaiProp, so }
|
||||
{ it can be easily accessed from within }
|
||||
{ CheckSequence }
|
||||
Inc(NrOfMods, InstrSinceLastMod[TmpReg]);
|
||||
PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
|
||||
InstrSinceLastMod[TmpReg] := 0
|
||||
End
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
{ load of a register with a completely new value }
|
||||
CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
|
||||
If Not(RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^)) Then
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
Typ := Con_Ref;
|
||||
StartMod := p;
|
||||
NrOfMods := 1;
|
||||
End
|
||||
End;
|
||||
{$ifdef StateDebug}
|
||||
hp := new(pai_asm_comment,init(strpnew(std_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
|
||||
InsertLLItem(AsmL, p, p^.next, hp);
|
||||
{$endif StateDebug}
|
||||
|
||||
End
|
||||
Else if IsLoadConstReg(p) Then
|
||||
Begin
|
||||
TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
CurProp^.IncWState(TmpReg);
|
||||
{also store how many instructions are part of the }
|
||||
{ sequence in the first instruction's PPaiProp, so }
|
||||
{ it can be easily accessed from within }
|
||||
{ CheckSequence }
|
||||
Inc(NrOfMods, InstrSinceLastMod[TmpReg]);
|
||||
PPaiProp(Pai(StartMod)^.OptInfo)^.Regs[TmpReg].NrOfMods := NrOfMods;
|
||||
InstrSinceLastMod[TmpReg] := 0
|
||||
CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
|
||||
typ := Con_Const;
|
||||
StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
|
||||
End
|
||||
End
|
||||
Else
|
||||
Begin
|
||||
{ load of a register with a completely new value }
|
||||
CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
|
||||
If Not(RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^)) Then
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
Typ := Con_Ref;
|
||||
StartMod := p;
|
||||
NrOfMods := 1;
|
||||
End
|
||||
End;
|
||||
{$ifdef StateDebug}
|
||||
hp := new(pai_asm_comment,init(strpnew(std_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].WState))));
|
||||
InsertLLItem(AsmL, p, p^.next, hp);
|
||||
{$endif StateDebug}
|
||||
|
||||
End
|
||||
Else if IsLoadConstReg(p) Then
|
||||
Begin
|
||||
TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
|
||||
With CurProp^.Regs[TmpReg] Do
|
||||
Begin
|
||||
CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
|
||||
typ := Con_Const;
|
||||
StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
|
||||
End
|
||||
End
|
||||
Else CpuDFA(Pinstr(p));
|
||||
End;
|
||||
Else CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
||||
End;
|
||||
{ Inc(InstrCnt);}
|
||||
GetNextInstruction(p, p);
|
||||
Else CpuDFA(Pinstr(p));
|
||||
End;
|
||||
Else CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
||||
End;
|
||||
{ Inc(InstrCnt);}
|
||||
GetNextInstruction(p, p);
|
||||
End;
|
||||
}
|
||||
End;
|
||||
End;
|
||||
|
||||
Procedure TAoptDFA.CpuDFA(p: PInstr);
|
||||
Begin
|
||||
Abstract;
|
||||
End;
|
||||
Procedure TAoptDFA.CpuDFA(p: PInstr);
|
||||
Begin
|
||||
Abstract;
|
||||
End;
|
||||
|
||||
Function TAOptDFA.TCh2Reg(Ch: TInsChange): TRegister;
|
||||
Begin
|
||||
TCh2Reg:=R_NO;
|
||||
Abstract;
|
||||
End;
|
||||
{!!!!!!!
|
||||
Function TAOptDFA.TCh2Reg(Ch: TInsChange): TRegister;
|
||||
Begin
|
||||
TCh2Reg:=R_NO;
|
||||
Abstract;
|
||||
End;
|
||||
}
|
||||
|
||||
Function TAOptDFA.RegReadByInstr(Reg: TRegister; p: Pai): Boolean;
|
||||
Begin
|
||||
RegReadByInstr:=false;
|
||||
Abstract;
|
||||
End;
|
||||
Function TAOptDFA.RegReadByInstr(Reg: TRegister; p: tai): Boolean;
|
||||
Begin
|
||||
RegReadByInstr:=false;
|
||||
Abstract;
|
||||
End;
|
||||
|
||||
|
||||
End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.8 2004-06-20 08:55:28 florian
|
||||
Revision 1.9 2004-10-30 15:21:37 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.8 2004/06/20 08:55:28 florian
|
||||
* logs truncated
|
||||
|
||||
Revision 1.7 2004/01/31 17:45:16 peter
|
||||
* Change several $ifdef i386 to x86
|
||||
* Change several OS_32 to OS_INT/OS_ADDR
|
||||
|
||||
}
|
||||
|
1754
compiler/aoptobj.pas
1754
compiler/aoptobj.pas
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,7 @@
|
||||
{$ifndef USEOPT}
|
||||
{$define NOOPT}
|
||||
{$endif}
|
||||
|
||||
|
||||
{ 1.0.x generates broken code for sysutils }
|
||||
{$ifndef FORCE_SYSUTILS}
|
||||
{$undef USE_SYSUTILS}
|
||||
@ -37,7 +37,7 @@
|
||||
{$undef USE_SYSUTILS}
|
||||
{$endif}
|
||||
{$endif}
|
||||
|
||||
|
||||
{$define FPCPROCVAR}
|
||||
{$define USEEXCEPT}
|
||||
|
||||
@ -58,18 +58,15 @@
|
||||
{$define cpu64bit}
|
||||
{$define cpuextended}
|
||||
{$define cpufloat128}
|
||||
{$define noopt}
|
||||
{$define cputargethasfixedstack}
|
||||
{$endif x86_64}
|
||||
|
||||
{$ifdef alpha}
|
||||
{$define cpu64bit}
|
||||
{$define noopt}
|
||||
{$endif alpha}
|
||||
|
||||
{$ifdef sparc}
|
||||
{$define cpuflags}
|
||||
{$define noopt}
|
||||
{$define cputargethasfixedstack}
|
||||
{$define cpurequiresproperalignment}
|
||||
{$endif sparc}
|
||||
@ -84,19 +81,21 @@
|
||||
{$define cpuflags}
|
||||
{$define cpuneedsdiv32helper}
|
||||
{$define cputargethasfixedstack}
|
||||
{$define noopt}
|
||||
{$define cpurequiresproperalignment}
|
||||
{$endif arm}
|
||||
|
||||
{$ifdef m68k}
|
||||
{$define cpuflags}
|
||||
{$define cpufpemu}
|
||||
{$define noopt}
|
||||
{$endif m68k}
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.44 2004-10-14 18:29:22 peter
|
||||
Revision 1.45 2004-10-30 15:21:37 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.44 2004/10/14 18:29:22 peter
|
||||
* disable USE_SYSUTILS when compiled with 1.9.4 or 1.0.x
|
||||
|
||||
Revision 1.43 2004/10/10 14:57:29 jonas
|
||||
|
@ -24,7 +24,6 @@ unit psub;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
@ -105,7 +104,7 @@ implementation
|
||||
{$ifdef i386}
|
||||
,aopt386
|
||||
{$else i386}
|
||||
,aoptcpu
|
||||
,aopt
|
||||
{$endif i386}
|
||||
{$endif}
|
||||
;
|
||||
@ -1404,7 +1403,11 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.210 2004-10-24 20:01:08 peter
|
||||
Revision 1.211 2004-10-30 15:21:37 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.210 2004/10/24 20:01:08 peter
|
||||
* remove saveregister calling convention
|
||||
|
||||
Revision 1.209 2004/10/15 09:14:17 mazen
|
||||
|
@ -1235,7 +1235,7 @@ unit rgobj;
|
||||
i,j,k : word;
|
||||
n,a,c : Tsuperregister;
|
||||
colourednodes : Tsuperregisterset;
|
||||
adj_colours:set of 0..255;
|
||||
adj_colours:set of 0..255;
|
||||
found : boolean;
|
||||
|
||||
begin
|
||||
@ -1994,7 +1994,11 @@ unit rgobj;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.144 2004-10-24 17:04:01 peter
|
||||
Revision 1.145 2004-10-30 15:21:37 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.144 2004/10/24 17:04:01 peter
|
||||
* during translation only process regalloc for the current regtype
|
||||
|
||||
Revision 1.143 2004/10/15 09:14:17 mazen
|
||||
|
@ -208,6 +208,7 @@ implementation
|
||||
constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
|
||||
begin
|
||||
inherited create(op);
|
||||
is_jmp:=op in [A_BA,A_Bxx];
|
||||
condition:=cond;
|
||||
ops:=1;
|
||||
loadsymbol(0,_op1,0);
|
||||
@ -217,6 +218,7 @@ implementation
|
||||
constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
|
||||
begin
|
||||
inherited create(op);
|
||||
is_jmp:=op in [A_BA,A_Bxx];
|
||||
ops:=1;
|
||||
loadsymbol(0,_op1,0);
|
||||
end;
|
||||
@ -311,7 +313,11 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.50 2004-06-20 08:55:32 florian
|
||||
Revision 1.51 2004-10-30 15:21:38 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.50 2004/06/20 08:55:32 florian
|
||||
* logs truncated
|
||||
|
||||
Revision 1.49 2004/06/20 08:47:33 florian
|
||||
|
51
compiler/sparc/aoptcpu.pas
Normal file
51
compiler/sparc/aoptcpu.pas
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2004 by Jonas Maebe
|
||||
|
||||
This unit calls the optimization procedures to optimize the assembler
|
||||
code for sparc
|
||||
|
||||
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 aoptcpu;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
Interface
|
||||
|
||||
uses
|
||||
cpubase, aoptobj, aoptcpub, aopt;
|
||||
|
||||
Type
|
||||
TCpuAsmOptimizer = class(TAsmOptimizer)
|
||||
End;
|
||||
|
||||
Implementation
|
||||
|
||||
begin
|
||||
casmoptimizer:=TCpuAsmOptimizer;
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2004-10-30 15:21:38 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.10 2004/06/20 08:55:31 florian
|
||||
* logs truncated
|
||||
}
|
132
compiler/sparc/aoptcpub.pas
Normal file
132
compiler/sparc/aoptcpub.pas
Normal file
@ -0,0 +1,132 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
|
||||
Development Team
|
||||
|
||||
This unit contains several types and constants necessary for the
|
||||
optimizer to work on the sparc architecture
|
||||
|
||||
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 aoptcpub; { Assembler OPTimizer CPU specific Base }
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
{ enable the following define if memory references can have both a base and }
|
||||
{ index register in 1 operand }
|
||||
|
||||
{$define RefsHaveIndexReg}
|
||||
|
||||
{ enable the following define if memory references can have a scaled index }
|
||||
|
||||
{ define RefsHaveScale}
|
||||
|
||||
{ enable the following define if memory references can have a segment }
|
||||
{ override }
|
||||
|
||||
{ define RefsHaveSegment}
|
||||
|
||||
Interface
|
||||
|
||||
Uses
|
||||
cpubase,aasmcpu,AOptBase;
|
||||
|
||||
Type
|
||||
|
||||
{ type of a normal instruction }
|
||||
TInstr = Taicpu;
|
||||
PInstr = ^TInstr;
|
||||
|
||||
{ ************************************************************************* }
|
||||
{ **************************** TCondRegs ********************************** }
|
||||
{ ************************************************************************* }
|
||||
{ Info about the conditional registers }
|
||||
TCondRegs = Object
|
||||
Constructor Init;
|
||||
Destructor Done;
|
||||
End;
|
||||
|
||||
{ ************************************************************************* }
|
||||
{ **************************** TAoptBaseCpu ******************************* }
|
||||
{ ************************************************************************* }
|
||||
|
||||
TAoptBaseCpu = class(TAoptBase)
|
||||
End;
|
||||
|
||||
|
||||
{ ************************************************************************* }
|
||||
{ ******************************* Constants ******************************* }
|
||||
{ ************************************************************************* }
|
||||
Const
|
||||
|
||||
{ the maximum number of things (registers, memory, ...) a single instruction }
|
||||
{ changes }
|
||||
|
||||
MaxCh = 3;
|
||||
|
||||
{ the maximum number of operands an instruction has }
|
||||
|
||||
MaxOps = 3;
|
||||
|
||||
{Oper index of operand that contains the source (reference) with a load }
|
||||
{instruction }
|
||||
|
||||
LoadSrc = 0;
|
||||
|
||||
{Oper index of operand that contains the destination (register) with a load }
|
||||
{instruction }
|
||||
|
||||
LoadDst = 1;
|
||||
|
||||
{Oper index of operand that contains the source (register) with a store }
|
||||
{instruction }
|
||||
|
||||
StoreSrc = 0;
|
||||
|
||||
{Oper index of operand that contains the destination (reference) with a load }
|
||||
{instruction }
|
||||
|
||||
StoreDst = 1;
|
||||
|
||||
aopt_uncondjmp = A_BA;
|
||||
aopt_condjmp = A_Bxx;
|
||||
|
||||
Implementation
|
||||
|
||||
{ ************************************************************************* }
|
||||
{ **************************** TCondRegs ********************************** }
|
||||
{ ************************************************************************* }
|
||||
Constructor TCondRegs.init;
|
||||
Begin
|
||||
End;
|
||||
|
||||
Destructor TCondRegs.Done; {$ifdef inl} inline; {$endif inl}
|
||||
Begin
|
||||
End;
|
||||
|
||||
End.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2004-10-30 15:21:38 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.6 2004/06/20 08:55:31 florian
|
||||
* logs truncated
|
||||
|
||||
}
|
43
compiler/sparc/aoptcpud.pas
Normal file
43
compiler/sparc/aoptcpud.pas
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
$Id$
|
||||
Copyright (c) 1998-2004 by Jonas Maebe, member of the Free Pascal
|
||||
Development Team
|
||||
|
||||
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 aoptcpud;
|
||||
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
aoptda;
|
||||
|
||||
type
|
||||
TAOptDFACpu = class(TAOptDFA)
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2004-10-30 15:21:38 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
}
|
@ -393,6 +393,7 @@ uses
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
|
||||
function RefsEqual(Const r1,r2: TReference) : Boolean;
|
||||
function is_calljmp(o:tasmop):boolean;
|
||||
|
||||
procedure inverse_flags(var f: TResFlags);
|
||||
@ -427,6 +428,17 @@ implementation
|
||||
Helpers
|
||||
*****************************************************************************}
|
||||
|
||||
function RefsEqual(Const r1,r2: TReference) : Boolean;
|
||||
begin
|
||||
RefsEqual := (r1.Offset=r2.Offset) and
|
||||
(r1.Base=r2.Base) and
|
||||
(r1.Index=r2.Index) and
|
||||
(r1.symbol=r2.symbol) and
|
||||
(r1.relsymbol=r2.relsymbol) and
|
||||
(r1.refaddr=r2.refaddr);
|
||||
end;
|
||||
|
||||
|
||||
function is_calljmp(o:tasmop):boolean;
|
||||
const
|
||||
CallJmpOp=[A_JMPL..A_CBccc];
|
||||
@ -509,7 +521,11 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.73 2004-10-25 17:04:51 peter
|
||||
Revision 1.74 2004-10-30 15:21:38 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.73 2004/10/25 17:04:51 peter
|
||||
* add saved_standard_registers
|
||||
|
||||
Revision 1.72 2004/09/21 17:25:13 peter
|
||||
|
@ -22,7 +22,7 @@
|
||||
}
|
||||
unit cputarg;
|
||||
|
||||
{$INCLUDE fpcdefs.inc}
|
||||
{$i fpcdefs.inc}
|
||||
|
||||
interface
|
||||
|
||||
@ -32,6 +32,10 @@ implementation
|
||||
uses
|
||||
systems { prevent a syntax error when nothing is included }
|
||||
|
||||
{$ifndef NOOPT}
|
||||
,aoptcpu
|
||||
{$endif NOOPT}
|
||||
|
||||
{**************************************
|
||||
Targets
|
||||
**************************************}
|
||||
@ -48,12 +52,16 @@ implementation
|
||||
**************************************}
|
||||
|
||||
,CpuGas
|
||||
|
||||
;
|
||||
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.5 2004-06-20 08:55:32 florian
|
||||
* logs truncated
|
||||
Revision 1.6 2004-10-30 15:21:38 florian
|
||||
* fixed generic optimizer
|
||||
* enabled generic optimizer for sparc
|
||||
|
||||
Revision 1.5 2004/06/20 08:55:32 florian
|
||||
* logs truncated
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user