* fixed generic optimizer

* enabled generic optimizer for sparc
This commit is contained in:
florian 2004-10-30 15:21:37 +00:00
parent 86f78c7300
commit e04b172854
13 changed files with 1857 additions and 1268 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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
View 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
}

View 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
}

View File

@ -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

View File

@ -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
}