+ MIPS: implemented peephole optimization which changes appropriate patterns into conditional moves, which are available on MIPS4 and higher.

git-svn-id: trunk@28008 -
This commit is contained in:
sergei 2014-06-20 05:57:39 +00:00
parent 4e7c908b0d
commit c2a29a0dbb

View File

@ -38,6 +38,7 @@ unit aoptcpu;
var AllUsedRegs: TAllUsedRegs): Boolean;
function TryRemoveMov(var p: tai; opcode: TAsmOp): boolean;
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
procedure PeepHoleOptPass2; override;
End;
Implementation
@ -92,6 +93,56 @@ unit aoptcpu;
end;
function CanBeCMOV(p: tai): boolean;
begin
result:=assigned(p) and (p.typ=ait_instruction) and
(taicpu(p).opcode in [A_MOV_D,A_MOV_S,A_MOVE]);
end;
procedure ChangeToCMOV(p: taicpu; cond: tasmcond; reg: tregister);
begin
case cond of
C_COP1TRUE:
case p.opcode of
A_MOV_D: p.opcode:=A_MOVT_D;
A_MOV_S: p.opcode:=A_MOVT_S;
A_MOVE: p.opcode:=A_MOVT;
else
InternalError(2014061701);
end;
C_COP1FALSE:
case p.opcode of
A_MOV_D: p.opcode:=A_MOVF_D;
A_MOV_S: p.opcode:=A_MOVF_S;
A_MOVE: p.opcode:=A_MOVF;
else
InternalError(2014061702);
end;
C_EQ:
case p.opcode of
A_MOV_D: p.opcode:=A_MOVZ_D;
A_MOV_S: p.opcode:=A_MOVZ_S;
A_MOVE: p.opcode:=A_MOVZ;
else
InternalError(2014061703);
end;
C_NE:
case p.opcode of
A_MOV_D: p.opcode:=A_MOVN_D;
A_MOV_S: p.opcode:=A_MOVN_S;
A_MOVE: p.opcode:=A_MOVN;
else
InternalError(2014061704);
end;
else
InternalError(2014061705);
end;
p.ops:=3;
p.loadreg(2,reg);
end;
function instructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;
var
p: taicpu;
@ -357,6 +408,158 @@ unit aoptcpu;
end;
end;
procedure TCpuAsmOptimizer.PeepHoleOptPass2;
var
p: tai;
l: longint;
hp1,hp2,hp3: tai;
condition: tasmcond;
condreg: tregister;
begin
{ Currently, everything below is mips4+ }
if (current_settings.cputype<cpu_mips4) then
exit;
p:=BlockStart;
ClearUsedRegs;
while (p<>BlockEnd) Do
begin
UpdateUsedRegs(tai(p.next));
case p.typ of
ait_instruction:
begin
case taicpu(p).opcode of
A_BC:
begin
condreg:=NR_NO;
if (taicpu(p).condition in [C_COP1TRUE,C_COP1FALSE]) then
{ TODO: must be taken from "p" if/when codegen makes use of multiple %fcc }
condreg:=NR_FCC0
else if (taicpu(p).condition in [C_EQ,C_NE]) then
begin
if (taicpu(p).oper[0]^.reg=NR_R0) then
condreg:=taicpu(p).oper[1]^.reg
else if (taicpu(p).oper[1]^.reg=NR_R0) then
condreg:=taicpu(p).oper[0]^.reg
end;
if (condreg<>NR_NO) then
begin
{ check for
bCC xxx
<several movs>
xxx:
}
l:=0;
GetNextInstruction(p, hp1);
while CanBeCMOV(hp1) do // CanBeCMOV returns False for nil or labels
begin
inc(l);
GetNextInstruction(hp1,hp1);
end;
if assigned(hp1) then
begin
if FindLabel(tasmlabel(taicpu(p).oper[taicpu(p).ops-1]^.ref^.symbol),hp1) then
begin
if (l<=4) and (l>0) then
begin
condition:=inverse_cond(taicpu(p).condition);
hp2:=p;
GetNextInstruction(p,hp1);
p:=hp1;
repeat
ChangeToCMOV(taicpu(hp1),condition,condreg);
GetNextInstruction(hp1,hp1);
until not CanBeCMOV(hp1);
{ wait with removing else GetNextInstruction could
ignore the label if it was the only usage in the
jump moved away }
tasmlabel(taicpu(hp2).oper[taicpu(hp2).ops-1]^.ref^.symbol).decrefs;
RemoveDelaySlot(hp2);
asml.remove(hp2);
hp2.free;
continue;
end;
end
else
begin
{ check further for
bCC xxx
<several movs 1>
b yyy
xxx:
<several movs 2>
yyy:
}
{ hp2 points to jmp yyy }
hp2:=hp1;
{ skip hp1 to xxx }
GetNextInstruction(hp1, hp1);
if assigned(hp2) and
assigned(hp1) and
(l<=3) and
(hp2.typ=ait_instruction) and
(taicpu(hp2).opcode=A_BA) and
{ real label and jump, no further references to the
label are allowed }
(tasmlabel(taicpu(p).oper[taicpu(p).ops-1]^.ref^.symbol).getrefs<=2) and
FindLabel(tasmlabel(taicpu(p).oper[taicpu(p).ops-1]^.ref^.symbol),hp1) then
begin
l:=0;
{ skip hp1 to <several moves 2> }
GetNextInstruction(hp1, hp1);
while CanBeCMOV(hp1) do
begin
inc(l);
GetNextInstruction(hp1, hp1);
end;
{ hp1 points to yyy: }
if assigned(hp1) and
FindLabel(tasmlabel(taicpu(hp2).oper[taicpu(hp2).ops-1]^.ref^.symbol),hp1) then
begin
condition:=inverse_cond(taicpu(p).condition);
GetNextInstruction(p,hp1);
hp3:=p;
p:=hp1;
repeat
ChangeToCMOV(taicpu(hp1),condition,condreg);
GetNextInstruction(hp1,hp1);
until not CanBeCMOV(hp1);
{ hp2 is still at b yyy }
GetNextInstruction(hp2,hp1);
{ hp2 is now at xxx: }
condition:=inverse_cond(condition);
GetNextInstruction(hp1,hp1);
{ hp1 is now at <several movs 2> }
repeat
ChangeToCMOV(taicpu(hp1),condition,condreg);
GetNextInstruction(hp1,hp1);
until not CanBeCMOV(hp1);
{ remove bCC }
tasmlabel(taicpu(hp3).oper[taicpu(hp3).ops-1]^.ref^.symbol).decrefs;
RemoveDelaySlot(hp3);
asml.remove(hp3);
hp3.free;
{ remove jmp }
tasmlabel(taicpu(hp2).oper[taicpu(hp2).ops-1]^.ref^.symbol).decrefs;
RemoveDelaySlot(hp2);
asml.remove(hp2);
hp2.free;
continue;
end;
end;
end;
end;
end;
end;
end;
end;
end;
UpdateUsedRegs(p);
p:=tai(p.next);
end;
end;
begin
casmoptimizer:=TCpuAsmOptimizer;
end.