mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 13:29:15 +02:00
* fixed generic optimizer
* enabled generic optimizer for sparc
This commit is contained in:
parent
86f78c7300
commit
e04b172854
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
$Id$
|
$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
|
Development Team
|
||||||
|
|
||||||
This unit contains the interface routines between the code generator
|
This unit contains the interface routines between the code generator
|
||||||
@ -24,224 +24,238 @@
|
|||||||
}
|
}
|
||||||
Unit aopt;
|
Unit aopt;
|
||||||
|
|
||||||
Interface
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
Uses Aasmbase,aasmtai,aasmcpu, cobjects, aoptobj, aoptcpud, aoptcpub {aoptcs, aoptpeep} ;
|
Interface
|
||||||
|
|
||||||
Type
|
Uses
|
||||||
PAsmOptimizer = ^TAsmOptimizer;
|
aasmbase,aasmtai,aasmcpu,
|
||||||
TAsmOptimizer = Object(TAoptObj)
|
aoptobj;
|
||||||
|
|
||||||
{ _AsmL is the PAasmOutpout list that has to be optimized }
|
Type
|
||||||
Constructor Init(_AsmL: PAasmOutput);
|
TAsmOptimizer = class(TAoptObj)
|
||||||
|
|
||||||
{ call the necessary optimizer procedures }
|
{ _AsmL is the PAasmOutpout list that has to be optimized }
|
||||||
Procedure Optimize;
|
Constructor create(_AsmL: taasmoutput);
|
||||||
Destructor Done;
|
|
||||||
|
|
||||||
private
|
{ call the necessary optimizer procedures }
|
||||||
|
Procedure Optimize;
|
||||||
|
Destructor destroy;override;
|
||||||
|
|
||||||
Function FindLoHiLabels: Pai;
|
private
|
||||||
Procedure BuildLabelTableAndFixRegAlloc;
|
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.create(_AsmL: taasmoutput);
|
||||||
|
|
||||||
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
|
Begin
|
||||||
GetMem(LabelTable, LabelDif*SizeOf(TLabelTableItem));
|
inherited create(_asml,nil,nil,nil);
|
||||||
FillChar(LabelTable^, LabelDif*SizeOf(TLabelTableItem), 0);
|
{setup labeltable, always necessary}
|
||||||
p := BlockStart;
|
New(LabelInfo);
|
||||||
While (P <> BlockEnd) Do
|
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
|
Begin
|
||||||
Case p^.typ Of
|
While Assigned(P) And
|
||||||
ait_Label:
|
((P.typ <> Ait_Marker) Or
|
||||||
If Pai_Label(p)^.l^.is_used Then
|
(tai_Marker(P).Kind <> AsmBlockStart)) Do
|
||||||
LabelTable^[Pai_Label(p)^.l^.labelnr-LowLabel].PaiObj := p;
|
Begin
|
||||||
ait_regAlloc:
|
If (p.typ = ait_label) Then
|
||||||
begin
|
If (tai_Label(p).l.is_used) Then
|
||||||
if PairegAlloc(p)^.Allocation then
|
|
||||||
Begin
|
Begin
|
||||||
If Not(PaiRegAlloc(p)^.Reg in UsedRegs) Then
|
LabelFound := True;
|
||||||
UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg]
|
If (tai_Label(p).l.labelnr < LowLabel) Then
|
||||||
Else
|
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
|
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;
|
hp1 := p;
|
||||||
hp2 := nil;
|
hp2 := nil;
|
||||||
While GetLastInstruction(hp1, hp1) And
|
While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
|
||||||
Not(RegInInstruction(PaiRegAlloc(p)^.Reg, hp1)) Do
|
GetNextInstruction(hp1, hp1) And
|
||||||
|
RegInInstruction(tai_regalloc(p).Reg, hp1) Do
|
||||||
hp2 := hp1;
|
hp2 := hp1;
|
||||||
If hp2 <> nil Then
|
If hp2 <> nil Then
|
||||||
Begin
|
Begin
|
||||||
hp1 := New(PaiRegAlloc, DeAlloc(PaiRegAlloc(p)^.Reg));
|
hp1 := tai(p.previous);
|
||||||
InsertLLItem(Pai(hp2^.previous), hp2, hp1);
|
AsmL.Remove(p);
|
||||||
End;
|
InsertLLItem(hp2, tai(hp2.Next), p);
|
||||||
End;
|
p := hp1;
|
||||||
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
|
End
|
||||||
End
|
End;
|
||||||
End;
|
P := tai(p.Next);
|
||||||
P := Pai(p^.Next);
|
While Assigned(p) And
|
||||||
While Assigned(p) And
|
(p.typ in (SkipInstr - [ait_regalloc])) Do
|
||||||
(p^.typ in (SkipInstr - [ait_regalloc])) Do
|
P := tai(P.Next)
|
||||||
P := Pai(P^.Next)
|
End
|
||||||
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;
|
||||||
End;
|
|
||||||
|
|
||||||
Destructor TAsmOptimizer.Done;
|
|
||||||
Begin
|
|
||||||
Dispose(LabelInfo)
|
|
||||||
End;
|
|
||||||
|
|
||||||
|
|
||||||
procedure Optimize(AsmL:Paasmoutput);
|
|
||||||
var
|
Procedure TAsmOptimizer.Optimize;
|
||||||
p : PAsmOptimizer;
|
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
|
begin
|
||||||
new(p,Init(AsmL));
|
casmoptimizer:=TAsmOptimizer;
|
||||||
p^.Optimize;
|
end.
|
||||||
dispose(p,Done);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
End.
|
|
||||||
|
|
||||||
{Virtual methods, most have to be overridden by processor dependent methods}
|
{Virtual methods, most have to be overridden by processor dependent methods}
|
||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.6 2004-06-20 08:55:28 florian
|
Revision 1.7 2004-10-30 15:21:37 florian
|
||||||
* logs truncated
|
* 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;
|
unit aoptbase;
|
||||||
|
|
||||||
Interface
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
uses aasmbase,aasmcpu,aasmtai,
|
interface
|
||||||
cpubase;
|
|
||||||
|
|
||||||
{ the number of tai objects processed by an optimizer object since the last }
|
uses
|
||||||
{ time a register was modified }
|
aasmbase,aasmcpu,aasmtai,
|
||||||
Type TInstrSinceLastMod = Array[LoGPReg..HiGPReg] of byte;
|
cpubase,
|
||||||
|
cgbase;
|
||||||
|
|
||||||
{ the TAopBase object implements the basic methods that most other }
|
Type
|
||||||
{ assembler optimizer objects require }
|
{ the number of tai objects processed by an optimizer object since the last
|
||||||
Type
|
time a register was modified }
|
||||||
TAoptBase = Object
|
{ size at each dimension depends on the registers of this type }
|
||||||
{ processor independent methods }
|
TInstrSinceLastMod = Array[tregistertype] of pbyte;
|
||||||
|
|
||||||
constructor init;
|
{ the TAopBase object implements the basic methods that most other }
|
||||||
destructor done;
|
{ assembler optimizer objects require }
|
||||||
{ returns true if register Reg is used by instruction p1 }
|
Type
|
||||||
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
TAoptBase = class
|
||||||
{ returns true if register Reg occurs in operand op }
|
{ processor independent methods }
|
||||||
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;
|
|
||||||
|
|
||||||
{ returns true if the references are completely equal }
|
constructor create;
|
||||||
{Function RefsEqual(Const R1, R2: TReference): Boolean;}
|
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 }
|
{ returns true if the references are completely equal }
|
||||||
{ to the optimizer in p1. If there is none, it returns false and }
|
{Function RefsEqual(Const R1, R2: TReference): Boolean;}
|
||||||
{ sets p1 to nil }
|
|
||||||
Function GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
{ gets the next tai object after current that contains info relevant }
|
||||||
{ gets the previous tai object after current that contains info }
|
{ to the optimizer in p1. If there is none, it returns false and }
|
||||||
{ relevant to the optimizer in last. If there is none, it retuns }
|
{ sets p1 to nil }
|
||||||
{ false and sets last to nil }
|
Function GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
||||||
Function GetLastInstruction(Current: tai; Var Last: 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 }
|
{ returns the maximum width component of Reg. Only has to be }
|
||||||
{ overridden for the 80x86 (afaik) }
|
{ overridden for the 80x86 (afaik) }
|
||||||
Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
|
Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
|
||||||
{ returns true if Reg1 and Reg2 are of the samae width. Only has to }
|
{ returns true if Reg1 and Reg2 are of the samae width. Only has to }
|
||||||
{ overridden for the 80x86 (afaik) }
|
{ overridden for the 80x86 (afaik) }
|
||||||
Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
|
Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
|
||||||
{ returns whether P is a load instruction (load contents from a }
|
{ returns whether P is a load instruction (load contents from a }
|
||||||
{ memory location or (register) variable into a register) }
|
{ memory location or (register) variable into a register) }
|
||||||
Function IsLoadMemReg(p: tai): Boolean; Virtual;
|
Function IsLoadMemReg(p: tai): Boolean; Virtual;
|
||||||
{ returns whether P is a load constant instruction (load a constant }
|
{ returns whether P is a load constant instruction (load a constant }
|
||||||
{ into a register) }
|
{ into a register) }
|
||||||
Function IsLoadConstReg(p: tai): Boolean; Virtual;
|
Function IsLoadConstReg(p: tai): Boolean; Virtual;
|
||||||
{ returns whether P is a store instruction (store contents from a }
|
{ returns whether P is a store instruction (store contents from a }
|
||||||
{ register to a memory location or to a (register) variable) }
|
{ register to a memory location or to a (register) variable) }
|
||||||
Function IsStoreRegMem(p: tai): Boolean; Virtual;
|
Function IsStoreRegMem(p: tai): Boolean; Virtual;
|
||||||
|
|
||||||
{ create a paicpu Object that loads the contents of reg1 into reg2 }
|
{ create a paicpu Object that loads the contents of reg1 into reg2 }
|
||||||
Function a_load_reg_reg(reg1, reg2: TRegister): taicpu; Virtual;
|
Function a_load_reg_reg(reg1, reg2: TRegister): taicpu; Virtual;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
implementation
|
||||||
|
|
||||||
uses globals, aoptcpub, cpuinfo;
|
uses
|
||||||
|
globtype,globals, aoptcpub, cpuinfo;
|
||||||
|
|
||||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
constructor taoptbase.create;
|
||||||
Begin
|
begin
|
||||||
RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup)
|
inherited create;
|
||||||
And (R1.Base = R2.Base)
|
end;
|
||||||
{$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.init;
|
destructor taoptbase.destroy;
|
||||||
begin
|
begin
|
||||||
end;
|
inherited destroy;
|
||||||
|
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;
|
|
||||||
|
|
||||||
|
|
||||||
Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean;
|
Function TAOptBase.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
||||||
Begin
|
Var Count: AWord;
|
||||||
Case op.typ Of
|
TmpResult: Boolean;
|
||||||
Top_Reg: RegInOp := Reg = op.reg;
|
Begin
|
||||||
Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
|
TmpResult := False;
|
||||||
Else RegInOp := False
|
Count := 0;
|
||||||
End
|
If (p1.typ = ait_instruction) Then
|
||||||
End;
|
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;
|
Function TAOptBase.RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||||
Begin
|
Begin
|
||||||
Reg := RegMaxSize(Reg);
|
Case op.typ Of
|
||||||
RegInRef := (Ref.Base = Reg)
|
Top_Reg: RegInOp := Reg = op.reg;
|
||||||
{$ifdef RefsHaveIndexReg}
|
Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
|
||||||
Or (Ref.Index = Reg)
|
Else RegInOp := False
|
||||||
{$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
|
|
||||||
End
|
End
|
||||||
Else
|
End;
|
||||||
Begin
|
|
||||||
Last := Current;
|
|
||||||
GetLastInstruction := True;
|
|
||||||
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;
|
Function TAOptBase.GetNextInstruction(Current: tai; Var Next: tai): Boolean;
|
||||||
Begin
|
Begin
|
||||||
RegMaxSize := Reg
|
Repeat
|
||||||
End;
|
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;
|
Function TAOptBase.GetLastInstruction(Current: tai; Var Last: tai): Boolean;
|
||||||
Begin
|
Begin
|
||||||
RegsSameSize := True
|
Repeat
|
||||||
End;
|
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;
|
{ ******************* Processor dependent stuff *************************** }
|
||||||
Begin
|
|
||||||
Abstract
|
|
||||||
End;
|
|
||||||
|
|
||||||
Function TAOptBase.IsStoreRegMem(p: tai): Boolean;
|
Function TAOptBase.RegMaxSize(Reg: TRegister): TRegister;
|
||||||
Begin
|
Begin
|
||||||
Abstract
|
RegMaxSize := Reg
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function TAoptBase.a_load_reg_reg(reg1, reg2: TRegister): taicpu;
|
Function TAOptBase.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
|
||||||
Begin
|
Begin
|
||||||
Abstract
|
RegsSameSize := True
|
||||||
End;
|
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$
|
$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
|
* logs truncated
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,164 +24,177 @@
|
|||||||
}
|
}
|
||||||
Unit aoptda;
|
Unit aoptda;
|
||||||
|
|
||||||
Interface
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
uses aasm, cpubase, aoptcpub, aoptbase, aoptcpu;
|
Interface
|
||||||
|
|
||||||
Type
|
uses
|
||||||
TAOptDFA = Object(TAoptCpu)
|
cpubase,cgbase,
|
||||||
{ uses the same constructor as TAoptCpu = constructor from TAoptObj }
|
aasmbase,aasmtai,aasmcpu,
|
||||||
|
aoptcpub, aoptbase;
|
||||||
|
|
||||||
{ gathers the information regarding the contents of every register }
|
Type
|
||||||
{ at the end of every instruction }
|
TAOptDFA = class
|
||||||
Procedure DoDFA;
|
{ uses the same constructor as TAoptCpu = constructor from TAoptObj }
|
||||||
|
|
||||||
{ handles the processor dependent dataflow analizing }
|
{ gathers the information regarding the contents of every register }
|
||||||
Procedure CpuDFA(p: PInstr); Virtual;
|
{ at the end of every instruction }
|
||||||
|
Procedure DoDFA;
|
||||||
|
|
||||||
{ How many instructions are between the current instruction and the }
|
{ handles the processor dependent dataflow analizing }
|
||||||
{ last one that modified the register }
|
Procedure CpuDFA(p: PInstr); Virtual;
|
||||||
InstrSinceLastMod: TInstrSinceLastMod;
|
|
||||||
|
|
||||||
{ convert a TInsChange value into the corresponding register }
|
{ How many instructions are between the current instruction and the }
|
||||||
Function TCh2Reg(Ch: TInsChange): TRegister; Virtual;
|
{ last one that modified the register }
|
||||||
{ returns whether the instruction P reads from register Reg }
|
InstrSinceLastMod: TInstrSinceLastMod;
|
||||||
Function RegReadByInstr(Reg: TRegister; p: Pai): Boolean; Virtual;
|
|
||||||
End;
|
|
||||||
|
|
||||||
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;
|
uses
|
||||||
{ Analyzes the Data Flow of an assembler list. Analyses the reg contents }
|
globals, aoptobj;
|
||||||
{ for the instructions between blockstart and blockend. Returns the last pai }
|
|
||||||
{ which has been processed }
|
Procedure TAOptDFA.DoDFA;
|
||||||
Var
|
{ Analyzes the Data Flow of an assembler list. Analyses the reg contents }
|
||||||
CurProp: PPaiProp;
|
{ for the instructions between blockstart and blockend. Returns the last pai }
|
||||||
UsedRegs: TUsedRegs;
|
{ which has been processed }
|
||||||
p, hp, NewBlockStart : Pai;
|
Var
|
||||||
TmpReg: TRegister;
|
CurProp: TPaiProp;
|
||||||
Begin
|
UsedRegs: TUsedRegs;
|
||||||
p := BlockStart;
|
p, hp, NewBlockStart : tai;
|
||||||
UsedRegs.init;
|
TmpReg: TRegister;
|
||||||
UsedRegs.Update(p);
|
|
||||||
NewBlockStart := SkipHead(p);
|
|
||||||
{ done implicitely by the constructor
|
|
||||||
FillChar(InstrSinceLastMod, SizeOf(InstrSinceLastMod), 0); }
|
|
||||||
While (P <> BlockEnd) Do
|
|
||||||
Begin
|
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
|
Begin
|
||||||
GetLastInstruction(p, hp);
|
CurProp:=TPaiProp.Create;
|
||||||
CurProp^.Regs := PPaiProp(hp^.OptInfo)^.Regs;
|
If (p <> NewBlockStart) Then
|
||||||
{ !!!!!!!!!!!! }
|
Begin
|
||||||
{$ifdef x86}
|
GetLastInstruction(p, hp);
|
||||||
CurProp^.CondRegs.Flags :=
|
CurProp.Regs := TPaiProp(hp.OptInfo).Regs;
|
||||||
PPaiProp(hp^.OptInfo)^.CondRegs.Flags;
|
{ !!!!!!!!!!!! }
|
||||||
{$endif}
|
{$ifdef x86}
|
||||||
End;
|
CurProp.CondRegs.Flags :=
|
||||||
CurProp^.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
|
TPaiProp(hp.OptInfo).CondRegs.Flags;
|
||||||
UsedRegs.Update(Pai(p^.Next));
|
{$endif}
|
||||||
PPaiProp(p^.OptInfo) := CurProp;
|
End;
|
||||||
For TmpReg := LoGPReg To HiGPReg Do
|
CurProp.UsedRegs.InitWithValue(UsedRegs.GetUsedRegs);
|
||||||
Inc(InstrSinceLastMod[TmpReg]);
|
UsedRegs.Update(tai(p.Next));
|
||||||
Case p^.typ Of
|
TPaiProp(p.OptInfo) := CurProp;
|
||||||
ait_label:
|
For TmpReg := LoGPReg To HiGPReg Do
|
||||||
If (Pai_label(p)^.l^.is_used) Then
|
Inc(InstrSinceLastMod[TmpReg]);
|
||||||
CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
Case p^.typ Of
|
||||||
{$ifdef GDB}
|
ait_label:
|
||||||
ait_stabs, ait_stabn, ait_stab_function_name:;
|
If (Pai_label(p)^.l^.is_used) Then
|
||||||
{$endif GDB}
|
CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
||||||
ait_instruction:
|
{$ifdef GDB}
|
||||||
if not(PInstr(p)^.is_jmp) then
|
ait_stabs, ait_stabn, ait_stab_function_name:;
|
||||||
begin
|
{$endif GDB}
|
||||||
If IsLoadMemReg(p) Then
|
ait_instruction:
|
||||||
Begin
|
if not(PInstr(p)^.is_jmp) then
|
||||||
CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
|
begin
|
||||||
TmpReg := RegMaxSize(PInstr(p)^.oper[LoadDst].reg);
|
If IsLoadMemReg(p) Then
|
||||||
If RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^) And
|
|
||||||
(CurProp^.GetRegContentType(TmpReg) = Con_Ref) Then
|
|
||||||
Begin
|
Begin
|
||||||
{ a load based on the value this register already }
|
CurProp^.ReadRef(PInstr(p)^.oper[LoadSrc].ref);
|
||||||
{ contained }
|
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
|
With CurProp^.Regs[TmpReg] Do
|
||||||
Begin
|
Begin
|
||||||
CurProp^.IncWState(TmpReg);
|
CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
|
||||||
{also store how many instructions are part of the }
|
typ := Con_Const;
|
||||||
{ sequence in the first instruction's PPaiProp, so }
|
StartMod := Pointer(PInstr(p)^.oper[LoadSrc].val);
|
||||||
{ 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
|
||||||
End
|
End
|
||||||
Else
|
Else CpuDFA(Pinstr(p));
|
||||||
Begin
|
End;
|
||||||
{ load of a register with a completely new value }
|
Else CurProp^.DestroyAllRegs(InstrSinceLastMod);
|
||||||
CurProp^.DestroyReg(TmpReg, InstrSinceLastMod);
|
End;
|
||||||
If Not(RegInRef(TmpReg, PInstr(p)^.oper[LoadSrc].ref^)) Then
|
{ Inc(InstrCnt);}
|
||||||
With CurProp^.Regs[TmpReg] Do
|
GetNextInstruction(p, p);
|
||||||
Begin
|
End;
|
||||||
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);
|
|
||||||
End;
|
End;
|
||||||
End;
|
|
||||||
|
|
||||||
Procedure TAoptDFA.CpuDFA(p: PInstr);
|
Procedure TAoptDFA.CpuDFA(p: PInstr);
|
||||||
Begin
|
Begin
|
||||||
Abstract;
|
Abstract;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function TAOptDFA.TCh2Reg(Ch: TInsChange): TRegister;
|
{!!!!!!!
|
||||||
Begin
|
Function TAOptDFA.TCh2Reg(Ch: TInsChange): TRegister;
|
||||||
TCh2Reg:=R_NO;
|
Begin
|
||||||
Abstract;
|
TCh2Reg:=R_NO;
|
||||||
End;
|
Abstract;
|
||||||
|
End;
|
||||||
|
}
|
||||||
|
|
||||||
Function TAOptDFA.RegReadByInstr(Reg: TRegister; p: Pai): Boolean;
|
Function TAOptDFA.RegReadByInstr(Reg: TRegister; p: tai): Boolean;
|
||||||
Begin
|
Begin
|
||||||
RegReadByInstr:=false;
|
RegReadByInstr:=false;
|
||||||
Abstract;
|
Abstract;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
||||||
End.
|
End.
|
||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* logs truncated
|
||||||
|
|
||||||
Revision 1.7 2004/01/31 17:45:16 peter
|
Revision 1.7 2004/01/31 17:45:16 peter
|
||||||
* Change several $ifdef i386 to x86
|
* Change several $ifdef i386 to x86
|
||||||
* Change several OS_32 to OS_INT/OS_ADDR
|
* 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}
|
{$ifndef USEOPT}
|
||||||
{$define NOOPT}
|
{$define NOOPT}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{ 1.0.x generates broken code for sysutils }
|
{ 1.0.x generates broken code for sysutils }
|
||||||
{$ifndef FORCE_SYSUTILS}
|
{$ifndef FORCE_SYSUTILS}
|
||||||
{$undef USE_SYSUTILS}
|
{$undef USE_SYSUTILS}
|
||||||
@ -37,7 +37,7 @@
|
|||||||
{$undef USE_SYSUTILS}
|
{$undef USE_SYSUTILS}
|
||||||
{$endif}
|
{$endif}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
{$define FPCPROCVAR}
|
{$define FPCPROCVAR}
|
||||||
{$define USEEXCEPT}
|
{$define USEEXCEPT}
|
||||||
|
|
||||||
@ -58,18 +58,15 @@
|
|||||||
{$define cpu64bit}
|
{$define cpu64bit}
|
||||||
{$define cpuextended}
|
{$define cpuextended}
|
||||||
{$define cpufloat128}
|
{$define cpufloat128}
|
||||||
{$define noopt}
|
|
||||||
{$define cputargethasfixedstack}
|
{$define cputargethasfixedstack}
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
|
|
||||||
{$ifdef alpha}
|
{$ifdef alpha}
|
||||||
{$define cpu64bit}
|
{$define cpu64bit}
|
||||||
{$define noopt}
|
|
||||||
{$endif alpha}
|
{$endif alpha}
|
||||||
|
|
||||||
{$ifdef sparc}
|
{$ifdef sparc}
|
||||||
{$define cpuflags}
|
{$define cpuflags}
|
||||||
{$define noopt}
|
|
||||||
{$define cputargethasfixedstack}
|
{$define cputargethasfixedstack}
|
||||||
{$define cpurequiresproperalignment}
|
{$define cpurequiresproperalignment}
|
||||||
{$endif sparc}
|
{$endif sparc}
|
||||||
@ -84,19 +81,21 @@
|
|||||||
{$define cpuflags}
|
{$define cpuflags}
|
||||||
{$define cpuneedsdiv32helper}
|
{$define cpuneedsdiv32helper}
|
||||||
{$define cputargethasfixedstack}
|
{$define cputargethasfixedstack}
|
||||||
{$define noopt}
|
|
||||||
{$define cpurequiresproperalignment}
|
{$define cpurequiresproperalignment}
|
||||||
{$endif arm}
|
{$endif arm}
|
||||||
|
|
||||||
{$ifdef m68k}
|
{$ifdef m68k}
|
||||||
{$define cpuflags}
|
{$define cpuflags}
|
||||||
{$define cpufpemu}
|
{$define cpufpemu}
|
||||||
{$define noopt}
|
|
||||||
{$endif m68k}
|
{$endif m68k}
|
||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* disable USE_SYSUTILS when compiled with 1.9.4 or 1.0.x
|
||||||
|
|
||||||
Revision 1.43 2004/10/10 14:57:29 jonas
|
Revision 1.43 2004/10/10 14:57:29 jonas
|
||||||
|
@ -24,7 +24,6 @@ unit psub;
|
|||||||
|
|
||||||
{$i fpcdefs.inc}
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -105,7 +104,7 @@ implementation
|
|||||||
{$ifdef i386}
|
{$ifdef i386}
|
||||||
,aopt386
|
,aopt386
|
||||||
{$else i386}
|
{$else i386}
|
||||||
,aoptcpu
|
,aopt
|
||||||
{$endif i386}
|
{$endif i386}
|
||||||
{$endif}
|
{$endif}
|
||||||
;
|
;
|
||||||
@ -1404,7 +1403,11 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* remove saveregister calling convention
|
||||||
|
|
||||||
Revision 1.209 2004/10/15 09:14:17 mazen
|
Revision 1.209 2004/10/15 09:14:17 mazen
|
||||||
|
@ -1235,7 +1235,7 @@ unit rgobj;
|
|||||||
i,j,k : word;
|
i,j,k : word;
|
||||||
n,a,c : Tsuperregister;
|
n,a,c : Tsuperregister;
|
||||||
colourednodes : Tsuperregisterset;
|
colourednodes : Tsuperregisterset;
|
||||||
adj_colours:set of 0..255;
|
adj_colours:set of 0..255;
|
||||||
found : boolean;
|
found : boolean;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -1994,7 +1994,11 @@ unit rgobj;
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* during translation only process regalloc for the current regtype
|
||||||
|
|
||||||
Revision 1.143 2004/10/15 09:14:17 mazen
|
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);
|
constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
|
||||||
begin
|
begin
|
||||||
inherited create(op);
|
inherited create(op);
|
||||||
|
is_jmp:=op in [A_BA,A_Bxx];
|
||||||
condition:=cond;
|
condition:=cond;
|
||||||
ops:=1;
|
ops:=1;
|
||||||
loadsymbol(0,_op1,0);
|
loadsymbol(0,_op1,0);
|
||||||
@ -217,6 +218,7 @@ implementation
|
|||||||
constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
|
constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
|
||||||
begin
|
begin
|
||||||
inherited create(op);
|
inherited create(op);
|
||||||
|
is_jmp:=op in [A_BA,A_Bxx];
|
||||||
ops:=1;
|
ops:=1;
|
||||||
loadsymbol(0,_op1,0);
|
loadsymbol(0,_op1,0);
|
||||||
end;
|
end;
|
||||||
@ -311,7 +313,11 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* logs truncated
|
||||||
|
|
||||||
Revision 1.49 2004/06/20 08:47:33 florian
|
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
|
Helpers
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
|
function RefsEqual(Const r1,r2: TReference) : Boolean;
|
||||||
function is_calljmp(o:tasmop):boolean;
|
function is_calljmp(o:tasmop):boolean;
|
||||||
|
|
||||||
procedure inverse_flags(var f: TResFlags);
|
procedure inverse_flags(var f: TResFlags);
|
||||||
@ -427,6 +428,17 @@ implementation
|
|||||||
Helpers
|
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;
|
function is_calljmp(o:tasmop):boolean;
|
||||||
const
|
const
|
||||||
CallJmpOp=[A_JMPL..A_CBccc];
|
CallJmpOp=[A_JMPL..A_CBccc];
|
||||||
@ -509,7 +521,11 @@ implementation
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* add saved_standard_registers
|
||||||
|
|
||||||
Revision 1.72 2004/09/21 17:25:13 peter
|
Revision 1.72 2004/09/21 17:25:13 peter
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
unit cputarg;
|
unit cputarg;
|
||||||
|
|
||||||
{$INCLUDE fpcdefs.inc}
|
{$i fpcdefs.inc}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -32,6 +32,10 @@ implementation
|
|||||||
uses
|
uses
|
||||||
systems { prevent a syntax error when nothing is included }
|
systems { prevent a syntax error when nothing is included }
|
||||||
|
|
||||||
|
{$ifndef NOOPT}
|
||||||
|
,aoptcpu
|
||||||
|
{$endif NOOPT}
|
||||||
|
|
||||||
{**************************************
|
{**************************************
|
||||||
Targets
|
Targets
|
||||||
**************************************}
|
**************************************}
|
||||||
@ -48,12 +52,16 @@ implementation
|
|||||||
**************************************}
|
**************************************}
|
||||||
|
|
||||||
,CpuGas
|
,CpuGas
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.5 2004-06-20 08:55:32 florian
|
Revision 1.6 2004-10-30 15:21:38 florian
|
||||||
* logs truncated
|
* 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