+ Next portion of MIPS peephole optimizations. Get more aggressive and do more than a single pass if needed, enabling optimization of instructions that logically turn into MOVE due to register renaming.

git-svn-id: trunk@33095 -
This commit is contained in:
sergei 2016-02-13 12:33:30 +00:00
parent 263c888555
commit 41751bc5b4

View File

@ -202,11 +202,6 @@ unit aoptcpu;
Result:=GetNextInstruction(Next,Next);
until {not(cs_opt_level3 in current_settings.optimizerswitches) or} not(Result) or (Next.typ<>ait_instruction) or (RegInInstruction(reg,Next)) or
(is_calljmp(taicpu(Next).opcode));
if Result and (next.typ=ait_instruction) and is_calljmp(taicpu(next).opcode) then
begin
result:=false;
next:=nil;
end;
end;
@ -338,6 +333,35 @@ unit aoptcpu;
ait_instruction:
begin
case taicpu(p).opcode of
A_BC:
begin
{ BEQ/BNE with same register are bogus, but can be generated for code like
"if lo(qwordvar)=cardinal(qwordvar) ...",
optimizations below can also yield them, e.g. if one register was initially R0. }
if (taicpu(p).condition in [C_EQ,C_NE]) and
(taicpu(p).oper[0]^.reg=taicpu(p).oper[1]^.reg) then
begin
if (taicpu(p).condition=C_NE) then
begin
if (taicpu(p).oper[2]^.typ = top_ref) and
(taicpu(p).oper[2]^.ref^.symbol is TAsmLabel) then
TAsmLabel(taicpu(p).oper[2]^.ref^.symbol).decrefs;
RemoveDelaySlot(p);
GetNextInstruction(p,next);
end
else
begin
next:=taicpu.op_sym(A_BA,taicpu(p).oper[2]^.ref^.symbol);
taicpu(next).fileinfo:=taicpu(p).fileinfo;
asml.insertbefore(next,p);
end;
asml.remove(p);
p.Free;
p:=next;
result:=true;
end;
end;
A_SEH:
begin
if GetNextInstructionUsingReg(p,next,taicpu(p).oper[0]^.reg) and
@ -350,13 +374,14 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end
else
TryRemoveMov(p,A_MOVE);
result:=TryRemoveMov(p,A_MOVE);
end;
A_SEB:
{ TODO: can be handled similar to A_SEH, but it's almost never encountered }
TryRemoveMov(p,A_MOVE);
result:=TryRemoveMov(p,A_MOVE);
A_SLL:
begin
@ -384,10 +409,11 @@ unit aoptcpu;
p.free;
next.free;
p:=next2;
result:=true;
end;
end
else
TryRemoveMov(p,A_MOVE);
result:=TryRemoveMov(p,A_MOVE);
end;
A_SRL:
@ -415,9 +441,10 @@ unit aoptcpu;
begin
asml.remove(next);
next.free;
result:=true;
end
else
TryRemoveMov(p,A_MOVE);
result:=TryRemoveMov(p,A_MOVE);
end;
A_ANDI:
@ -445,6 +472,7 @@ unit aoptcpu;
asml.remove(next2);
next.free;
next2.free;
result:=true;
end
{ Remove zero extension if register is used only for byte/word memory store }
else if (taicpu(p).oper[2]^.typ=top_const) and
@ -459,9 +487,10 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end
else
TryRemoveMov(p,A_MOVE);
result:=TryRemoveMov(p,A_MOVE);
end;
A_MOV_S:
@ -470,7 +499,7 @@ unit aoptcpu;
(next.typ=ait_instruction) then
begin
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SWC1]) then
{ optimization successful };
result:=true;
end;
end;
@ -480,7 +509,7 @@ unit aoptcpu;
(next.typ=ait_instruction) then
begin
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SDC1]) then
{ optimization successful };
result:=true;
end;
end;
@ -492,12 +521,12 @@ unit aoptcpu;
begin
{ MOVE Rx,Ry; store Rx,(ref); dealloc Rx ==> store Ry,(ref) }
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SB,A_SH,A_SW]) then
{ optimization successful }
result:=true
else if TryRemoveMovToRefIndex(p,taicpu(next)) then
{ successful as well }
result:=true
{ MOVE Rx,Ry; opcode Rx,Rx,any ==> opcode Rx,Ry,any
MOVE Rx,Ry; opcode Rx,Rz,Rx ==> opcode Rx,Rz,Ry }
else if (taicpu(next).opcode in [A_ADD,A_ADDU,A_ADDI,A_ADDIU,A_SUB,A_SUBU]) and
else if (taicpu(next).opcode in [A_ADD,A_ADDU,A_ADDI,A_ADDIU,A_SUB,A_SUBU,A_AND,A_ANDI,A_SLLV,A_SRLV,A_SRAV]) and
MatchOperand(taicpu(next).oper[0]^,taicpu(p).oper[0]^.reg) then
begin
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
@ -506,6 +535,7 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end
{ TODO: if Ry=NR_R0, this effectively changes instruction into MOVE,
providing further optimization possibilities }
@ -515,10 +545,12 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end;
end
{ MOVE Rx,Ry; opcode Rz,Rx,any; dealloc Rx ==> opcode Rz,Ry,any }
else if (taicpu(next).opcode in [A_ADD,A_ADDU,A_ADDI,A_ADDIU,A_SUB,A_SUBU,A_SLT,A_SLTU,A_DIV,A_DIVU]) and
else if (taicpu(next).opcode in [A_ADD,A_ADDU,A_ADDI,A_ADDIU,A_SUB,A_SUBU,A_SLT,A_SLTU,A_DIV,A_DIVU,
A_SLL,A_SRL,A_SRA,A_SLLV,A_SRLV,A_SRAV,A_AND,A_ANDI,A_OR,A_ORI,A_XOR,A_XORI]) and
Assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.next))) then
begin
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
@ -527,6 +559,7 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end
else if MatchOperand(taicpu(next).oper[2]^,taicpu(p).oper[0]^.reg) then
begin
@ -534,25 +567,32 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end;
end
{ MULT[U] must be handled separately due to different operand numbers }
else if (taicpu(next).opcode in [A_MULT,A_MULTU]) and
{ MULT[U] and cond.branches must be handled separately due to different operand numbers }
else if (taicpu(next).opcode in [A_MULT,A_MULTU,A_BC]) and
Assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.next))) then
begin
if MatchOperand(taicpu(next).oper[0]^,taicpu(p).oper[0]^.reg) then
begin
taicpu(next).loadreg(0,taicpu(p).oper[1]^.reg);
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
taicpu(next).loadreg(1,taicpu(p).oper[1]^.reg);
asml.remove(p);
p.free;
p:=next;
result:=true;
end
else if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
begin
taicpu(next).loadreg(1,taicpu(p).oper[1]^.reg);
if MatchOperand(taicpu(next).oper[0]^,taicpu(p).oper[0]^.reg) then
taicpu(next).loadreg(0,taicpu(p).oper[1]^.reg);
asml.remove(p);
p.free;
p:=next;
result:=true;
end;
end
else if TryRemoveMov(p,A_MOVE) then
@ -564,9 +604,9 @@ unit aoptcpu;
asml.remove(p);
p.free;
p:=next;
result:=true;
end;
end;
{ TODO: MOVE Rx,Ry; Bcc Rx,Rz,label; dealloc Rx ==> Bcc Ry,Rz,label }
end;
end;
@ -610,28 +650,51 @@ unit aoptcpu;
result:=TryRemoveMov(p,A_MOVE);
end;
A_ADD,A_ADDU,A_OR:
begin
if MatchOperand(taicpu(p).oper[1]^,NR_R0) then
begin
taicpu(p).freeop(1);
taicpu(p).oper[1]:=taicpu(p).oper[2];
taicpu(p).oper[2]:=nil;
taicpu(p).ops:=2;
taicpu(p).opercnt:=2;
taicpu(p).opcode:=A_MOVE;
result:=true;
end
else if MatchOperand(taicpu(p).oper[2]^,NR_R0) then
begin
taicpu(p).freeop(2);
taicpu(p).ops:=2;
taicpu(p).opercnt:=2;
taicpu(p).opcode:=A_MOVE;
result:=true;
end
else
result:=TryRemoveMov(p,A_MOVE);
end;
A_LB,A_LBU,A_LH,A_LHU,A_LW,
A_ADD,A_ADDU,
A_ADDI,
A_SUB,A_SUBU,
A_SRA,A_SRAV,
A_SRLV,
A_SLLV,
A_MFLO,A_MFHI,
A_AND,A_OR,A_XOR,A_ORI,A_XORI:
TryRemoveMov(p,A_MOVE);
A_AND,A_XOR,A_ORI,A_XORI:
result:=TryRemoveMov(p,A_MOVE);
A_LWC1,
A_ADD_s, A_SUB_s, A_MUL_s, A_DIV_s,
A_ABS_s, A_NEG_s, A_SQRT_s,
A_CVT_s_w, A_CVT_s_l, A_CVT_s_d:
TryRemoveMov(p,A_MOV_s);
result:=TryRemoveMov(p,A_MOV_s);
A_LDC1,
A_ADD_d, A_SUB_d, A_MUL_d, A_DIV_d,
A_ABS_d, A_NEG_d, A_SQRT_d,
A_CVT_d_w, A_CVT_d_l, A_CVT_d_s:
TryRemoveMov(p,A_MOV_d);
result:=TryRemoveMov(p,A_MOV_d);
end;
end;
end;