mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 22:48:57 +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
|
||||
globtype, globals,
|
||||
verbose,
|
||||
cgbase,
|
||||
aoptda,aoptcpu,aoptcpud;
|
||||
|
||||
Constructor TAsmOptimizer.create(_AsmL: TAsmList);
|
||||
@ -110,11 +111,11 @@ Unit aopt;
|
||||
Procedure TAsmOptimizer.BuildLabelTableAndFixRegAlloc;
|
||||
{ Builds a table with the locations of the labels in the TAsmList. }
|
||||
{ Also fixes some RegDeallocs like "# %eax released; push (%eax)" }
|
||||
Var p{, hp1, hp2}: tai;
|
||||
{UsedRegs: TRegSet;}
|
||||
Var p,hp1, hp2: tai;
|
||||
Regs: TAllUsedRegs;
|
||||
LabelIdx : longint;
|
||||
Begin
|
||||
{UsedRegs := [];}
|
||||
CreateUsedRegs(Regs);
|
||||
With LabelInfo^ Do
|
||||
If (LabelDif <> 0) Then
|
||||
Begin
|
||||
@ -137,13 +138,17 @@ Unit aopt;
|
||||
end;
|
||||
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]
|
||||
If Not(RegInUsedRegs(tai_regalloc(p).Reg,Regs)) Then
|
||||
IncludeRegInUsedRegs(tai_regalloc(p).Reg,Regs)
|
||||
Else
|
||||
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;
|
||||
hp2 := nil;
|
||||
While GetLastInstruction(hp1, hp1) And
|
||||
@ -154,11 +159,12 @@ Unit aopt;
|
||||
hp1:=tai_regalloc.DeAlloc(tai_regalloc(p).Reg,hp2);
|
||||
InsertLLItem(tai(hp2.previous), hp2, hp1);
|
||||
End;
|
||||
End;
|
||||
}
|
||||
End;
|
||||
End
|
||||
else
|
||||
Begin
|
||||
UsedRegs := UsedRegs - [tai_regalloc(p).Reg];
|
||||
ExcludeRegFromUsedRegs(tai_regalloc(p).Reg,Regs);
|
||||
hp1 := p;
|
||||
hp2 := nil;
|
||||
While Not(FindRegAlloc(tai_regalloc(p).Reg, tai(hp1.Next))) And
|
||||
@ -172,8 +178,17 @@ Unit aopt;
|
||||
InsertLLItem(hp2, tai(hp2.Next), p);
|
||||
p := hp1;
|
||||
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;
|
||||
P := tai(p.Next);
|
||||
@ -182,7 +197,8 @@ Unit aopt;
|
||||
(p.typ in (SkipInstr - [ait_regalloc])) Do
|
||||
P := tai(P.Next)
|
||||
End;
|
||||
End
|
||||
End;
|
||||
ReleaseUsedRegs(Regs);
|
||||
End;
|
||||
|
||||
procedure tasmoptimizer.clear;
|
||||
|
@ -47,7 +47,7 @@ unit aoptbase;
|
||||
constructor create; virtual;
|
||||
destructor destroy;override;
|
||||
{ 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 }
|
||||
Function RegInOp(Reg: TRegister; const op: toper): Boolean;
|
||||
{ returns true if register Reg is used in the reference Ref }
|
||||
@ -201,12 +201,12 @@ unit aoptbase;
|
||||
Current := Tai(Current.previous);
|
||||
While Assigned(Current) 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 = ait_label) And
|
||||
labelCanBeSkipped(Tai_Label(Current)))) Do
|
||||
Current := Tai(Current.previous);
|
||||
If Assigned(Current) And
|
||||
{ If Assigned(Current) And
|
||||
(Current.typ = ait_Marker) And
|
||||
(Tai_Marker(Current).Kind = mark_NoPropInfoEnd) Then
|
||||
Begin
|
||||
@ -214,10 +214,10 @@ unit aoptbase;
|
||||
((Current.typ <> ait_Marker) Or
|
||||
(Tai_Marker(Current).Kind <> mark_NoPropInfoStart)) Do
|
||||
Current := Tai(Current.previous);
|
||||
End;
|
||||
End; }
|
||||
Until Not(Assigned(Current)) 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
|
||||
(Current.typ In SkipInstr) or
|
||||
((Current.typ = ait_label) And
|
||||
|
@ -164,17 +164,17 @@ Unit AoptObj;
|
||||
TInstrSinceLastMod);
|
||||
{ destroy the contents of all registers }
|
||||
Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod);
|
||||
{ a register's contents are modified, but not destroyed (the new value }
|
||||
{ depends on the old one) }
|
||||
{ a register's contents are modified, but not destroyed (the new value
|
||||
depends on the old one) }
|
||||
Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod:
|
||||
TInstrSinceLastMod);
|
||||
{ an operand's contents are modified, but not destroyed (the new value }
|
||||
{ depends on the old one) }
|
||||
{ an operand's contents are modified, but not destroyed (the new value
|
||||
depends on the old one) }
|
||||
Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod:
|
||||
TInstrSinceLastMod);
|
||||
|
||||
{ increase the write state of a register (call every time a register is }
|
||||
{ written to) }
|
||||
{ increase the write state of a register (call every time a register is
|
||||
written to) }
|
||||
Procedure IncWState(Reg: TRegister);
|
||||
{ increase the read state of a register (call every time a register is }
|
||||
{ read from) }
|
||||
@ -262,11 +262,15 @@ Unit AoptObj;
|
||||
|
||||
{ processor independent methods }
|
||||
|
||||
Procedure CreateUsedRegs(var regs: TAllUsedRegs);
|
||||
Procedure ClearUsedRegs;
|
||||
Procedure UpdateUsedRegs(p : Tai);
|
||||
procedure UpdateUsedRegs(var Regs: TAllUsedRegs; p: Tai);
|
||||
Function CopyUsedRegs(var dest : TAllUsedRegs) : boolean;
|
||||
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 }
|
||||
{ instruction }
|
||||
@ -778,15 +782,12 @@ Unit AoptObj;
|
||||
|
||||
Constructor TAoptObj.create(_AsmL: TAsmList; _BlockStart, _BlockEnd: Tai;
|
||||
_LabelInfo: PLabelInfo);
|
||||
var
|
||||
i : TRegisterType;
|
||||
Begin
|
||||
AsmL := _AsmL;
|
||||
BlockStart := _BlockStart;
|
||||
BlockEnd := _BlockEnd;
|
||||
LabelInfo := _LabelInfo;
|
||||
for i:=low(TRegisterType) to high(TRegisterType) do
|
||||
UsedRegs[i]:=TUsedRegs.Create(i);
|
||||
CreateUsedRegs(UsedRegs);
|
||||
End;
|
||||
|
||||
destructor TAOptObj.Destroy;
|
||||
@ -799,6 +800,15 @@ Unit AoptObj;
|
||||
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;
|
||||
var
|
||||
i : TRegisterType;
|
||||
@ -835,6 +845,7 @@ Unit AoptObj;
|
||||
dest[i]:=TUsedRegs.Create_Regset(i,UsedRegs[i].GetUsedRegs);
|
||||
end;
|
||||
|
||||
|
||||
procedure TAOptObj.ReleaseUsedRegs(const regs: TAllUsedRegs);
|
||||
var
|
||||
i : TRegisterType;
|
||||
@ -844,6 +855,26 @@ Unit AoptObj;
|
||||
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;
|
||||
Var TempP: Tai;
|
||||
Begin
|
||||
|
@ -28,13 +28,17 @@ Unit aoptcpu;
|
||||
|
||||
Interface
|
||||
|
||||
uses cpubase, aasmtai, aopt, aoptcpub;
|
||||
uses cgbase, cpubase, aasmtai, aopt, aoptcpub, aoptobj;
|
||||
|
||||
Type
|
||||
|
||||
{ TCpuAsmOptimizer }
|
||||
|
||||
TCpuAsmOptimizer = class(TAsmOptimizer)
|
||||
{ uses the same constructor as TAopObj }
|
||||
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
||||
procedure PeepHoleOptPass2;override;
|
||||
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override;
|
||||
End;
|
||||
|
||||
TCpuPreRegallocScheduler = class(TAsmOptimizer)
|
||||
@ -51,7 +55,7 @@ Implementation
|
||||
uses
|
||||
cutils,
|
||||
verbose,
|
||||
cgbase,cgutils,
|
||||
cgutils,
|
||||
aasmbase,aasmdata,aasmcpu;
|
||||
|
||||
function CanBeCond(p : tai) : boolean;
|
||||
@ -118,6 +122,7 @@ Implementation
|
||||
var
|
||||
hp1,hp2: tai;
|
||||
i: longint;
|
||||
TmpUsedRegs: TAllUsedRegs;
|
||||
begin
|
||||
result := false;
|
||||
case p.typ of
|
||||
@ -216,6 +221,36 @@ Implementation
|
||||
taicpu(hp1).loadreg(1,taicpu(p).oper[0]^.reg);
|
||||
end;
|
||||
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;
|
||||
A_MOV:
|
||||
@ -562,6 +597,14 @@ Implementation
|
||||
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
|
||||
{ set of opcode which might or do write to memory }
|
||||
{ TODO : extend armins.dat to contain r/w info }
|
||||
|
Loading…
Reference in New Issue
Block a user