+ m68k: LEA, MOVE(M) to MOVE(M) predecremented optimization and MOVE(M), LEA to MOVE(M) postincremented optimization

git-svn-id: trunk@47762 -
This commit is contained in:
florian 2020-12-11 22:14:17 +00:00
parent a0a8a6911a
commit 0ab69ea0ad

View File

@ -40,6 +40,8 @@ unit aoptcpu;
function TryToOptimizeMove(var p: tai): boolean; function TryToOptimizeMove(var p: tai): boolean;
function MaybeRealConstOperSimplify(var p: tai): boolean; function MaybeRealConstOperSimplify(var p: tai): boolean;
function OptPass1LEA(var p: tai): Boolean;
function OptPass1MOVEM(var p: tai): Boolean;
{ outputs a debug message into the assembler file } { outputs a debug message into the assembler file }
procedure DebugMsg(const s: string; p: tai); procedure DebugMsg(const s: string; p: tai);
@ -48,7 +50,8 @@ unit aoptcpu;
Implementation Implementation
uses uses
cutils, aasmcpu, cgutils, globtype, globals, verbose, cpuinfo, itcpugas, procinfo, cpupi; cutils, aasmcpu, cgutils, globtype, globals, verbose, cpuinfo, itcpugas, procinfo, cpupi,
aoptutils;
{ Range check must be disabled explicitly as conversions between signed and unsigned { Range check must be disabled explicitly as conversions between signed and unsigned
32-bit values are done without explicit typecasts } 32-bit values are done without explicit typecasts }
@ -344,6 +347,79 @@ unit aoptcpu;
end; end;
end; end;
function TCpuAsmOptimizer.OptPass1LEA(var p: tai): Boolean;
var
next: tai;
begin
Result:=false;
{ LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. }
if not assigned(taicpu(p).oper[0]^.ref^.symbol) and
(((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and
(taicpu(p).oper[0]^.ref^.index = NR_NO)) or
((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and
(taicpu(p).oper[0]^.ref^.base = NR_NO))) and
(taicpu(p).oper[0]^.ref^.offset = 0) then
begin
DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p);
GetNextInstruction(p,next);
asml.remove(p);
p.free;
p:=next;
result:=true;
exit;
end;
if (taicpu(p).oper[1]^.reg=NR_A7) and
(taicpu(p).oper[0]^.ref^.base=NR_A7) and
(taicpu(p).oper[0]^.ref^.index=NR_NO) and
(taicpu(p).oper[0]^.ref^.symbol=nil) and
(taicpu(p).oper[0]^.ref^.direction=dir_none) and
GetNextInstruction(p,next) and
MatchInstruction(next,A_MOVEM,[S_L]) and
MatchOpType(taicpu(next),top_regset,top_ref) and
((taicpu(p).oper[0]^.ref^.offset=-(PopCnt(Byte(taicpu(next).oper[0]^.dataregset))+PopCnt(Byte(taicpu(next).oper[0]^.addrregset)))*4)) and
(taicpu(next).oper[1]^.ref^.base=NR_A7) and
(taicpu(next).oper[1]^.ref^.index=NR_NO) and
(taicpu(next).oper[1]^.ref^.symbol=nil) and
(taicpu(next).oper[1]^.ref^.direction=dir_none) then
begin
DebugMsg('Optimizer: LEA, MOVE(M) to MOVE(M) predecremented',p);
taicpu(next).oper[1]^.ref^.direction:=dir_dec;
asml.remove(p);
p.free;
p:=next;
result:=true;
exit;
end;
end;
function TCpuAsmOptimizer.OptPass1MOVEM(var p: tai): Boolean;
var
next: tai;
begin
Result:=false;
if MatchOpType(taicpu(p),top_ref,top_regset) and
(taicpu(p).oper[0]^.ref^.base=NR_A7) and
(taicpu(p).oper[0]^.ref^.index=NR_NO) and
(taicpu(p).oper[0]^.ref^.symbol=nil) and
(taicpu(p).oper[0]^.ref^.direction=dir_none) and
GetNextInstruction(p,next) and
MatchInstruction(next,A_LEA,[S_L]) and
(taicpu(next).oper[1]^.reg=NR_A7) and
(taicpu(next).oper[0]^.ref^.base=NR_A7) and
(taicpu(next).oper[0]^.ref^.index=NR_NO) and
(taicpu(next).oper[0]^.ref^.symbol=nil) and
(taicpu(next).oper[0]^.ref^.direction=dir_none) and
((taicpu(next).oper[0]^.ref^.offset=(PopCnt(Byte(taicpu(p).oper[1]^.dataregset))+PopCnt(Byte(taicpu(p).oper[1]^.addrregset)))*4)) then
begin
DebugMsg('Optimizer: MOVE(M), LEA to MOVE(M) postincremented',p);
taicpu(p).oper[0]^.ref^.direction:=dir_inc;
asml.remove(next);
next.free;
result:=true;
exit;
end;
end;
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean; function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
var var
next: tai; next: tai;
@ -358,22 +434,10 @@ unit aoptcpu;
case taicpu(p).opcode of case taicpu(p).opcode of
A_MOVE: A_MOVE:
result:=TryToOptimizeMove(p); result:=TryToOptimizeMove(p);
{ LEA (Ax),Ax is a NOP if src and dest reg is equal, so remove it. } A_MOVEM:
result:=OptPass1MOVEM(p);
A_LEA: A_LEA:
if not assigned(taicpu(p).oper[0]^.ref^.symbol) and Result:=OptPass1LEA(p);
(((taicpu(p).oper[0]^.ref^.base = taicpu(p).oper[1]^.reg) and
(taicpu(p).oper[0]^.ref^.index = NR_NO)) or
((taicpu(p).oper[0]^.ref^.index = taicpu(p).oper[1]^.reg) and
(taicpu(p).oper[0]^.ref^.base = NR_NO))) and
(taicpu(p).oper[0]^.ref^.offset = 0) then
begin
DebugMsg('Optimizer: LEA 0(Ax),Ax removed',p);
GetNextInstruction(p,next);
asml.remove(p);
p.free;
p:=next;
result:=true;
end;
{ Address register sub/add can be replaced with ADDQ/SUBQ or LEA if the value is in the { Address register sub/add can be replaced with ADDQ/SUBQ or LEA if the value is in the
SmallInt range, which is shorter to encode and faster to execute on most 68k } SmallInt range, which is shorter to encode and faster to execute on most 68k }
A_SUB,A_SUBA,A_ADD,A_ADDA: A_SUB,A_SUBA,A_ADD,A_ADDA: