mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 20:29:23 +02:00
* changed LdiCp2Cpi into LdiMov/Cp2Ldi/Cpi and improved it
git-svn-id: trunk@34920 -
This commit is contained in:
parent
c86bac021b
commit
0520d246d0
@ -30,7 +30,7 @@ Unit aoptcpu;
|
|||||||
|
|
||||||
Interface
|
Interface
|
||||||
|
|
||||||
uses cpubase, cgbase, aasmtai, aopt, aoptcpub;
|
uses cpubase, cgbase, aasmtai, aopt,AoptObj, aoptcpub;
|
||||||
|
|
||||||
Type
|
Type
|
||||||
TCpuAsmOptimizer = class(TAsmOptimizer)
|
TCpuAsmOptimizer = class(TAsmOptimizer)
|
||||||
@ -39,6 +39,8 @@ Type
|
|||||||
|
|
||||||
Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
|
Function GetNextInstructionUsingReg(Current: tai; Var Next: tai;reg : TRegister): Boolean;
|
||||||
function RegInInstruction(Reg: TRegister; p1: tai): Boolean; override;
|
function RegInInstruction(Reg: TRegister; p1: tai): Boolean; override;
|
||||||
|
function RegLoadedWithNewValue(reg : tregister; hp : tai) : boolean; override;
|
||||||
|
function InstructionLoadsFromReg(const reg : TRegister; const hp : tai) : boolean; override;
|
||||||
|
|
||||||
{ 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;
|
||||||
@ -49,6 +51,7 @@ Implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
cutils,
|
cutils,
|
||||||
|
verbose,
|
||||||
cpuinfo,
|
cpuinfo,
|
||||||
aasmbase,aasmcpu,aasmdata,
|
aasmbase,aasmcpu,aasmdata,
|
||||||
globals,globtype,
|
globals,globtype,
|
||||||
@ -114,6 +117,22 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function MatchInstruction(const instr: tai; const ops: TAsmOpSet;opcount : byte): boolean;
|
||||||
|
begin
|
||||||
|
result :=
|
||||||
|
(instr.typ = ait_instruction) and
|
||||||
|
(taicpu(instr).opcode in ops) and
|
||||||
|
(taicpu(instr).ops=opcount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function MatchOpType(const instr : tai;ot0,ot1 : toptype) : Boolean;
|
||||||
|
begin
|
||||||
|
Result:=(taicpu(instr).ops=2) and
|
||||||
|
(taicpu(instr).oper[0]^.typ=ot0) and
|
||||||
|
(taicpu(instr).oper[1]^.typ=ot1);
|
||||||
|
end;
|
||||||
|
|
||||||
{$ifdef DEBUG_AOPTCPU}
|
{$ifdef DEBUG_AOPTCPU}
|
||||||
procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
|
procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
|
||||||
begin
|
begin
|
||||||
@ -147,12 +166,72 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
|
||||||
|
var
|
||||||
|
p: taicpu;
|
||||||
|
begin
|
||||||
|
if not assigned(hp) or
|
||||||
|
(hp.typ <> ait_instruction) then
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
p := taicpu(hp);
|
||||||
|
Result := ((p.opcode in [A_LDI,A_MOV,A_LDS]) and (reg=p.oper[0]^.reg) and ((p.oper[1]^.typ<>top_reg) or (reg<>p.oper[0]^.reg))) or
|
||||||
|
((p.opcode in [A_LD,A_LDD,A_LPM]) and (reg=p.oper[0]^.reg) and not(RegInRef(reg,p.oper[1]^.ref^))) or
|
||||||
|
((p.opcode in [A_MOVW]) and ((reg=p.oper[0]^.reg) or (TRegister(ord(reg)+1)=p.oper[0]^.reg)) and not(reg=p.oper[1]^.reg) and not(TRegister(ord(reg)+1)=p.oper[1]^.reg)) or
|
||||||
|
((p.opcode in [A_POP]) and (reg=p.oper[0]^.reg));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
|
||||||
|
var
|
||||||
|
p: taicpu;
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
Result := false;
|
||||||
|
|
||||||
|
if not (assigned(hp) and (hp.typ = ait_instruction)) then
|
||||||
|
exit;
|
||||||
|
p:=taicpu(hp);
|
||||||
|
|
||||||
|
i:=0;
|
||||||
|
|
||||||
|
{ we do not care about the stack pointer }
|
||||||
|
if p.opcode in [A_POP] then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{ first operand only written?
|
||||||
|
then skip it }
|
||||||
|
if p.opcode in [A_MOV,A_LD,A_LDD,A_LDS,A_LPM,A_LDI,A_MOVW] then
|
||||||
|
i:=1;
|
||||||
|
|
||||||
|
while(i<p.ops) do
|
||||||
|
begin
|
||||||
|
case p.oper[I]^.typ of
|
||||||
|
top_reg:
|
||||||
|
Result := (p.oper[I]^.reg = reg) or
|
||||||
|
{ MOVW }
|
||||||
|
((i=1) and (p.opcode=A_MOVW) and (getsupreg(p.oper[0]^.reg)+1=getsupreg(reg)));
|
||||||
|
top_ref:
|
||||||
|
Result :=
|
||||||
|
(p.oper[I]^.ref^.base = reg) or
|
||||||
|
(p.oper[I]^.ref^.index = reg);
|
||||||
|
end;
|
||||||
|
{ Bailout if we found something }
|
||||||
|
if Result then
|
||||||
|
exit;
|
||||||
|
Inc(I);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
||||||
var
|
var
|
||||||
hp1,hp2,hp3,hp4,hp5: tai;
|
hp1,hp2,hp3,hp4,hp5: tai;
|
||||||
alloc, dealloc: tai_regalloc;
|
alloc, dealloc: tai_regalloc;
|
||||||
i: integer;
|
i: integer;
|
||||||
l: TAsmLabel;
|
l: TAsmLabel;
|
||||||
|
TmpUsedRegs : TAllUsedRegs;
|
||||||
begin
|
begin
|
||||||
result := false;
|
result := false;
|
||||||
case p.typ of
|
case p.typ of
|
||||||
@ -228,46 +307,53 @@ Implementation
|
|||||||
begin
|
begin
|
||||||
{ turn
|
{ turn
|
||||||
ldi reg0, imm
|
ldi reg0, imm
|
||||||
cp reg1, reg0
|
cp/mov reg1, reg0
|
||||||
dealloc reg0
|
dealloc reg0
|
||||||
into
|
into
|
||||||
cpi reg1, imm
|
cpi/ldi reg1, imm
|
||||||
}
|
}
|
||||||
if (taicpu(p).ops=2) and
|
if MatchOpType(p,top_reg,top_const) and
|
||||||
(taicpu(p).oper[0]^.typ=top_reg) and
|
|
||||||
(taicpu(p).oper[1]^.typ=top_const) and
|
|
||||||
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
(hp1.typ=ait_instruction) and
|
MatchInstruction(hp1,[A_CP,A_MOV],2) and
|
||||||
(not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
(not RegModifiedBetween(taicpu(p).oper[0]^.reg, p, hp1)) and
|
||||||
(taicpu(hp1).opcode=A_CP) and
|
MatchOpType(hp1,top_reg,top_reg) and
|
||||||
(taicpu(hp1).ops=2) and
|
|
||||||
(taicpu(hp1).oper[1]^.typ=top_reg) and
|
|
||||||
(getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
|
(getsupreg(taicpu(hp1).oper[0]^.reg) in [16..31]) and
|
||||||
(taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
|
(taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) then
|
||||||
assigned(FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next))) then
|
|
||||||
begin
|
begin
|
||||||
taicpu(hp1).opcode:=A_CPI;
|
CopyUsedRegs(TmpUsedRegs);
|
||||||
taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
|
if not(RegUsedAfterInstruction(taicpu(hp1).oper[1]^.reg, hp1, TmpUsedRegs)) then
|
||||||
|
|
||||||
alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
|
|
||||||
dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
|
|
||||||
|
|
||||||
if assigned(alloc) and assigned(dealloc) then
|
|
||||||
begin
|
begin
|
||||||
asml.Remove(alloc);
|
case taicpu(hp1).opcode of
|
||||||
alloc.Free;
|
A_CP:
|
||||||
asml.Remove(dealloc);
|
taicpu(hp1).opcode:=A_CPI;
|
||||||
dealloc.Free;
|
A_MOV:
|
||||||
|
taicpu(hp1).opcode:=A_LDI;
|
||||||
|
else
|
||||||
|
internalerror(2016111901);
|
||||||
|
end;
|
||||||
|
taicpu(hp1).loadconst(1, taicpu(p).oper[1]^.val);
|
||||||
|
|
||||||
|
alloc:=FindRegAllocBackward(taicpu(p).oper[0]^.reg,tai(p.Previous));
|
||||||
|
dealloc:=FindRegDeAlloc(taicpu(p).oper[0]^.reg,tai(hp1.Next));
|
||||||
|
|
||||||
|
if assigned(alloc) and assigned(dealloc) then
|
||||||
|
begin
|
||||||
|
asml.Remove(alloc);
|
||||||
|
alloc.Free;
|
||||||
|
asml.Remove(dealloc);
|
||||||
|
dealloc.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
DebugMsg('Peephole LdiMov/Cp2Ldi/Cpi performed', p);
|
||||||
|
|
||||||
|
GetNextInstruction(p,hp1);
|
||||||
|
asml.Remove(p);
|
||||||
|
p.Free;
|
||||||
|
p:=hp1;
|
||||||
|
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
|
ReleaseUsedRegs(TmpUsedRegs);
|
||||||
DebugMsg('Peephole LdiCp2Cpi performed', p);
|
|
||||||
|
|
||||||
GetNextInstruction(p,hp1);
|
|
||||||
asml.Remove(p);
|
|
||||||
p.Free;
|
|
||||||
p:=hp1;
|
|
||||||
|
|
||||||
result:=true;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
A_STS:
|
A_STS:
|
||||||
|
Loading…
Reference in New Issue
Block a user