mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 02:29:19 +02:00
* fixes some issues with reg. allocation information
git-svn-id: trunk@21303 -
This commit is contained in:
parent
08784aca44
commit
748694a325
@ -61,6 +61,7 @@ Unit aopt;
|
|||||||
uses
|
uses
|
||||||
globtype, globals,
|
globtype, globals,
|
||||||
verbose,
|
verbose,
|
||||||
|
cgbase,
|
||||||
aoptda,aoptcpu,aoptcpud;
|
aoptda,aoptcpu,aoptcpud;
|
||||||
|
|
||||||
Constructor TAsmOptimizer.create(_AsmL: TAsmList);
|
Constructor TAsmOptimizer.create(_AsmL: TAsmList);
|
||||||
@ -110,11 +111,11 @@ Unit aopt;
|
|||||||
Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
|
Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
|
||||||
{ Builds a table with the locations of the labels in the TAsmList. }
|
{ Builds a table with the locations of the labels in the TAsmList. }
|
||||||
{ Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
|
{ Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
|
||||||
Var p{, hp1, hp2}: tai;
|
Var p,hp1, hp2: tai;
|
||||||
{UsedRegs: TRegSet;}
|
Regs: TAllUsedRegs;
|
||||||
LabelIdx : longint;
|
LabelIdx : longint;
|
||||||
Begin
|
Begin
|
||||||
{UsedRegs := [];}
|
CreateUsedRegs(Regs);
|
||||||
With LabelInfo^ Do
|
With LabelInfo^ Do
|
||||||
If (LabelDif <> 0) Then
|
If (LabelDif <> 0) Then
|
||||||
Begin
|
Begin
|
||||||
@ -137,13 +138,17 @@ Unit aopt;
|
|||||||
end;
|
end;
|
||||||
ait_regAlloc:
|
ait_regAlloc:
|
||||||
begin
|
begin
|
||||||
{!!!!!!!!!
|
|
||||||
if tai_regalloc(p).ratype=ra_alloc then
|
if tai_regalloc(p).ratype=ra_alloc then
|
||||||
Begin
|
Begin
|
||||||
If Not(tai_regalloc(p).Reg in UsedRegs) Then
|
If Not(RegInUsedRegs(tai_regalloc(p).Reg,Regs)) Then
|
||||||
UsedRegs := UsedRegs + [tai_regalloc(p).Reg]
|
IncludeRegInUsedRegs(tai_regalloc(p).Reg,Regs)
|
||||||
Else
|
Else
|
||||||
Begin
|
Begin
|
||||||
|
hp1 := tai(p.previous);
|
||||||
|
AsmL.remove(p);
|
||||||
|
p.free;
|
||||||
|
p := hp1;
|
||||||
|
{ not sure if this is useful, it even skips previous deallocs of the register (FK)
|
||||||
hp1 := p;
|
hp1 := p;
|
||||||
hp2 := nil;
|
hp2 := nil;
|
||||||
While GetLastInstruction(hp1, hp1) And
|
While GetLastInstruction(hp1, hp1) And
|
||||||
@ -154,11 +159,12 @@ Unit aopt;
|
|||||||
hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
|
hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
|
||||||
InsertLLItem(tai(hp2.previous), hp2, hp1);
|
InsertLLItem(tai(hp2.previous), hp2, hp1);
|
||||||
End;
|
End;
|
||||||
|
}
|
||||||
End;
|
End;
|
||||||
End
|
End
|
||||||
else
|
else
|
||||||
Begin
|
Begin
|
||||||
UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
|
ExcludeRegFromUsedRegs(tai_regalloc(p).Reg,Regs);
|
||||||
hp1 := p;
|
hp1 := p;
|
||||||
hp2 := nil;
|
hp2 := nil;
|
||||||
While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
|
While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
|
||||||
@ -172,8 +178,17 @@ Unit aopt;
|
|||||||
InsertLLItem(hp2, tai(hp2.Next), p);
|
InsertLLItem(hp2, tai(hp2.Next), p);
|
||||||
p := hp1;
|
p := hp1;
|
||||||
End
|
End
|
||||||
|
else if findregalloc(tai_regalloc(p).reg, tai(p.next))
|
||||||
|
and getnextinstruction(p,hp1) then
|
||||||
|
begin
|
||||||
|
hp1 := tai(p.previous);
|
||||||
|
AsmL.remove(p);
|
||||||
|
p.free;
|
||||||
|
p := hp1;
|
||||||
|
// don't include here, since then the allocation will be removed when it's processed
|
||||||
|
// include(usedregs,supreg);
|
||||||
|
end;
|
||||||
End
|
End
|
||||||
};
|
|
||||||
End
|
End
|
||||||
End;
|
End;
|
||||||
P := tai(p.Next);
|
P := tai(p.Next);
|
||||||
@ -182,7 +197,8 @@ Unit aopt;
|
|||||||
(p.typ in (SkipInstr - [ait_regalloc])) Do
|
(p.typ in (SkipInstr - [ait_regalloc])) Do
|
||||||
P := tai(P.Next)
|
P := tai(P.Next)
|
||||||
End;
|
End;
|
||||||
End
|
End;
|
||||||
|
ReleaseUsedRegs(Regs);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
procedure tasmoptimizer.clear;
|
procedure tasmoptimizer.clear;
|
||||||
|
@ -47,7 +47,7 @@ unit aoptbase;
|
|||||||
constructor create; virtual;
|
constructor create; virtual;
|
||||||
destructor destroy;override;
|
destructor destroy;override;
|
||||||
{ returns true if register Reg is used by instruction p1 }
|
{ returns true if register Reg is used by instruction p1 }
|
||||||
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;virtual;
|
||||||
{ returns true if register Reg occurs in operand op }
|
{ returns true if register Reg occurs in operand op }
|
||||||
Function RegInOp(Reg: TRegister; const op: toper): Boolean;
|
Function RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||||
{ returns true if register Reg is used in the reference Ref }
|
{ returns true if register Reg is used in the reference Ref }
|
||||||
@ -201,12 +201,12 @@ unit aoptbase;
|
|||||||
Current := Tai(Current.previous);
|
Current := Tai(Current.previous);
|
||||||
While Assigned(Current) And
|
While Assigned(Current) And
|
||||||
(((Current.typ = ait_Marker) And
|
(((Current.typ = ait_Marker) And
|
||||||
Not(Tai_Marker(Current).Kind in [mark_AsmBlockEnd,mark_NoPropInfoEnd])) or
|
Not(Tai_Marker(Current).Kind in [mark_AsmBlockEnd{,mark_NoPropInfoEnd}])) or
|
||||||
(Current.typ In SkipInstr) or
|
(Current.typ In SkipInstr) or
|
||||||
((Current.typ = ait_label) And
|
((Current.typ = ait_label) And
|
||||||
labelCanBeSkipped(Tai_Label(Current)))) Do
|
labelCanBeSkipped(Tai_Label(Current)))) Do
|
||||||
Current := Tai(Current.previous);
|
Current := Tai(Current.previous);
|
||||||
If Assigned(Current) And
|
{ If Assigned(Current) And
|
||||||
(Current.typ = ait_Marker) And
|
(Current.typ = ait_Marker) And
|
||||||
(Tai_Marker(Current).Kind = mark_NoPropInfoEnd) Then
|
(Tai_Marker(Current).Kind = mark_NoPropInfoEnd) Then
|
||||||
Begin
|
Begin
|
||||||
@ -214,10 +214,10 @@ unit aoptbase;
|
|||||||
((Current.typ <> ait_Marker) Or
|
((Current.typ <> ait_Marker) Or
|
||||||
(Tai_Marker(Current).Kind <> mark_NoPropInfoStart)) Do
|
(Tai_Marker(Current).Kind <> mark_NoPropInfoStart)) Do
|
||||||
Current := Tai(Current.previous);
|
Current := Tai(Current.previous);
|
||||||
End;
|
End; }
|
||||||
Until Not(Assigned(Current)) Or
|
Until Not(Assigned(Current)) Or
|
||||||
(Current.typ <> ait_Marker) Or
|
(Current.typ <> ait_Marker) Or
|
||||||
(Tai_Marker(Current).Kind <> mark_NoPropInfoStart);
|
not(tai_Marker(current).Kind in [mark_NoPropInfoStart,mark_NoPropInfoEnd]);
|
||||||
If Not(Assigned(Current)) or
|
If Not(Assigned(Current)) or
|
||||||
(Current.typ In SkipInstr) or
|
(Current.typ In SkipInstr) or
|
||||||
((Current.typ = ait_label) And
|
((Current.typ = ait_label) And
|
||||||
|
@ -164,17 +164,17 @@ Unit AoptObj;
|
|||||||
TInstrSinceLastMod);
|
TInstrSinceLastMod);
|
||||||
{ destroy the contents of all registers }
|
{ destroy the contents of all registers }
|
||||||
Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
|
Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
|
||||||
{ a register's contents are modified, but not destroyed (the new value }
|
{ a register's contents are modified, but not destroyed (the new value
|
||||||
{ depends on the old one) }
|
depends on the old one) }
|
||||||
Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod:
|
Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod:
|
||||||
TInstrSinceLastMod);
|
TInstrSinceLastMod);
|
||||||
{ an operand's contents are modified, but not destroyed (the new value }
|
{ an operand's contents are modified, but not destroyed (the new value
|
||||||
{ depends on the old one) }
|
depends on the old one) }
|
||||||
Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod:
|
Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod:
|
||||||
TInstrSinceLastMod);
|
TInstrSinceLastMod);
|
||||||
|
|
||||||
{ increase the write state of a register (call every time a register is }
|
{ increase the write state of a register (call every time a register is
|
||||||
{ written to) }
|
written to) }
|
||||||
Procedure IncWState(Reg: TRegister);
|
Procedure IncWState(Reg: TRegister);
|
||||||
{ increase the read state of a register (call every time a register is }
|
{ increase the read state of a register (call every time a register is }
|
||||||
{ read from) }
|
{ read from) }
|
||||||
@ -262,11 +262,15 @@ Unit AoptObj;
|
|||||||
|
|
||||||
{ processor independent methods }
|
{ processor independent methods }
|
||||||
|
|
||||||
|
Procedure CreateUsedRegs(var regs: TAllUsedRegs);
|
||||||
Procedure ClearUsedRegs;
|
Procedure ClearUsedRegs;
|
||||||
Procedure UpdateUsedRegs(p : Tai);
|
Procedure UpdateUsedRegs(p : Tai);
|
||||||
procedure UpdateUsedRegs(var Regs: TAllUsedRegs; p: Tai);
|
procedure UpdateUsedRegs(var Regs: TAllUsedRegs; p: Tai);
|
||||||
Function CopyUsedRegs(var dest : TAllUsedRegs) : boolean;
|
Function CopyUsedRegs(var dest : TAllUsedRegs) : boolean;
|
||||||
Procedure ReleaseUsedRegs(const regs : TAllUsedRegs);
|
Procedure ReleaseUsedRegs(const regs : TAllUsedRegs);
|
||||||
|
Function RegInUsedRegs(reg : TRegister;regs : TAllUsedRegs) : boolean;
|
||||||
|
Procedure IncludeRegInUsedRegs(reg : TRegister;var regs : TAllUsedRegs);
|
||||||
|
Procedure ExcludeRegFromUsedRegs(reg: TRegister;var regs : TAllUsedRegs);
|
||||||
|
|
||||||
{ returns true if the label L is found between hp and the next }
|
{ returns true if the label L is found between hp and the next }
|
||||||
{ instruction }
|
{ instruction }
|
||||||
@ -778,15 +782,12 @@ Unit AoptObj;
|
|||||||
|
|
||||||
Constructor TAoptObj.create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
|
Constructor TAoptObj.create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
|
||||||
_LabelInfo: PLabelInfo);
|
_LabelInfo: PLabelInfo);
|
||||||
var
|
|
||||||
i : TRegisterType;
|
|
||||||
Begin
|
Begin
|
||||||
AsmL := _AsmL;
|
AsmL := _AsmL;
|
||||||
BlockStart := _BlockStart;
|
BlockStart := _BlockStart;
|
||||||
BlockEnd := _BlockEnd;
|
BlockEnd := _BlockEnd;
|
||||||
LabelInfo := _LabelInfo;
|
LabelInfo := _LabelInfo;
|
||||||
for i:=low(TRegisterType) to high(TRegisterType) do
|
CreateUsedRegs(UsedRegs);
|
||||||
UsedRegs[i]:=TUsedRegs.Create(i);
|
|
||||||
End;
|
End;
|
||||||
|
|
||||||
destructor TAOptObj.Destroy;
|
destructor TAOptObj.Destroy;
|
||||||
@ -799,6 +800,15 @@ Unit AoptObj;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TAOptObj.CreateUsedRegs(var regs: TAllUsedRegs);
|
||||||
|
var
|
||||||
|
i : TRegisterType;
|
||||||
|
begin
|
||||||
|
for i:=low(TRegisterType) to high(TRegisterType) do
|
||||||
|
Regs[i]:=TUsedRegs.Create(i);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TAOptObj.ClearUsedRegs;
|
procedure TAOptObj.ClearUsedRegs;
|
||||||
var
|
var
|
||||||
i : TRegisterType;
|
i : TRegisterType;
|
||||||
@ -835,6 +845,7 @@ Unit AoptObj;
|
|||||||
dest[i]:=TUsedRegs.Create_Regset(i,UsedRegs[i].GetUsedRegs);
|
dest[i]:=TUsedRegs.Create_Regset(i,UsedRegs[i].GetUsedRegs);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TAOptObj.ReleaseUsedRegs(const regs: TAllUsedRegs);
|
procedure TAOptObj.ReleaseUsedRegs(const regs: TAllUsedRegs);
|
||||||
var
|
var
|
||||||
i : TRegisterType;
|
i : TRegisterType;
|
||||||
@ -844,6 +855,26 @@ Unit AoptObj;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Function TAOptObj.RegInUsedRegs(reg : TRegister;regs : TAllUsedRegs) : boolean;
|
||||||
|
begin
|
||||||
|
result:=regs[getregtype(reg)].IsUsed(reg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TAOptObj.IncludeRegInUsedRegs(reg: TRegister;
|
||||||
|
var regs: TAllUsedRegs);
|
||||||
|
begin
|
||||||
|
include(regs[getregtype(reg)].UsedRegs,getsupreg(Reg));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure TAOptObj.ExcludeRegFromUsedRegs(reg: TRegister;
|
||||||
|
var regs: TAllUsedRegs);
|
||||||
|
begin
|
||||||
|
exclude(regs[getregtype(reg)].UsedRegs,getsupreg(Reg));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
Function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
|
Function TAOptObj.FindLabel(L: TasmLabel; Var hp: Tai): Boolean;
|
||||||
Var TempP: Tai;
|
Var TempP: Tai;
|
||||||
Begin
|
Begin
|
||||||
|
@ -28,13 +28,17 @@ Unit aoptcpu;
|
|||||||
|
|
||||||
Interface
|
Interface
|
||||||
|
|
||||||
uses cpubase, aasmtai, aopt, aoptcpub;
|
uses cgbase, cpubase, aasmtai, aopt, aoptcpub, aoptobj;
|
||||||
|
|
||||||
Type
|
Type
|
||||||
|
|
||||||
|
{ TCpuAsmOptimizer }
|
||||||
|
|
||||||
TCpuAsmOptimizer = class(TAsmOptimizer)
|
TCpuAsmOptimizer = class(TAsmOptimizer)
|
||||||
{ uses the same constructor as TAopObj }
|
{ uses the same constructor as TAopObj }
|
||||||
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
||||||
procedure PeepHoleOptPass2;override;
|
procedure PeepHoleOptPass2;override;
|
||||||
|
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
TCpuPreRegallocScheduler = class(TAsmOptimizer)
|
TCpuPreRegallocScheduler = class(TAsmOptimizer)
|
||||||
@ -51,7 +55,7 @@ Implementation
|
|||||||
uses
|
uses
|
||||||
cutils,
|
cutils,
|
||||||
verbose,
|
verbose,
|
||||||
cgbase,cgutils,
|
cgutils,
|
||||||
aasmbase,aasmdata,aasmcpu;
|
aasmbase,aasmdata,aasmcpu;
|
||||||
|
|
||||||
function CanBeCond(p : tai) : boolean;
|
function CanBeCond(p : tai) : boolean;
|
||||||
@ -118,6 +122,7 @@ Implementation
|
|||||||
var
|
var
|
||||||
hp1,hp2: tai;
|
hp1,hp2: tai;
|
||||||
i: longint;
|
i: longint;
|
||||||
|
TmpUsedRegs: TAllUsedRegs;
|
||||||
begin
|
begin
|
||||||
result := false;
|
result := false;
|
||||||
case p.typ of
|
case p.typ of
|
||||||
@ -216,6 +221,36 @@ Implementation
|
|||||||
taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
|
taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
|
||||||
end;
|
end;
|
||||||
result := true;
|
result := true;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
{ Remove superfluous mov after ldr
|
||||||
|
changes
|
||||||
|
ldr reg1, ref
|
||||||
|
mov reg2, reg1
|
||||||
|
to
|
||||||
|
ldr reg2, ref
|
||||||
|
|
||||||
|
conditions are:
|
||||||
|
* reg1 must be released after mov
|
||||||
|
* mov can not contain shifterops
|
||||||
|
* ldr+mov have the same conditions
|
||||||
|
* mov does not set flags
|
||||||
|
}
|
||||||
|
if GetNextInstruction(p, hp1) and
|
||||||
|
MatchInstruction(hp1, A_MOV, [taicpu(p).condition], [PF_None]) and
|
||||||
|
(taicpu(hp1).ops=2) and {We can't optimize if there is a shiftop}
|
||||||
|
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[0]^.reg) then
|
||||||
|
begin
|
||||||
|
CopyUsedRegs(TmpUsedRegs);
|
||||||
|
UpdateUsedRegs(TmpUsedRegs, tai(p.next));
|
||||||
|
If not(RegUsedAfterInstruction(taicpu(p).oper[0]^.reg,hp1,TmpUsedRegs)) then
|
||||||
|
begin
|
||||||
|
asml.insertbefore(tai_comment.Create(strpnew('Peephole LdrMov2Ldr removed superfluous mov')), hp1);
|
||||||
|
taicpu(p).loadreg(0,taicpu(hp1).oper[0]^.reg);
|
||||||
|
asml.remove(hp1);
|
||||||
|
hp1.free;
|
||||||
|
end;
|
||||||
|
ReleaseUsedRegs(TmpUsedRegs);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
A_MOV:
|
A_MOV:
|
||||||
@ -562,6 +597,14 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.RegInInstruction(Reg: TRegister; p1: tai): Boolean;
|
||||||
|
begin
|
||||||
|
If (p1.typ = ait_instruction) and (taicpu(p1).opcode=A_BL) then
|
||||||
|
Result:=true
|
||||||
|
else
|
||||||
|
Result:=inherited RegInInstruction(Reg, p1);
|
||||||
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
{ set of opcode which might or do write to memory }
|
{ set of opcode which might or do write to memory }
|
||||||
{ TODO : extend armins.dat to contain r/w info }
|
{ TODO : extend armins.dat to contain r/w info }
|
||||||
|
Loading…
Reference in New Issue
Block a user