mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-19 02:50:27 +02:00
+ 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:
parent
263c888555
commit
41751bc5b4
@ -202,11 +202,6 @@ unit aoptcpu;
|
|||||||
Result:=GetNextInstruction(Next,Next);
|
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
|
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));
|
(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;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -338,6 +333,35 @@ unit aoptcpu;
|
|||||||
ait_instruction:
|
ait_instruction:
|
||||||
begin
|
begin
|
||||||
case taicpu(p).opcode of
|
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:
|
A_SEH:
|
||||||
begin
|
begin
|
||||||
if GetNextInstructionUsingReg(p,next,taicpu(p).oper[0]^.reg) and
|
if GetNextInstructionUsingReg(p,next,taicpu(p).oper[0]^.reg) and
|
||||||
@ -350,13 +374,14 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
TryRemoveMov(p,A_MOVE);
|
result:=TryRemoveMov(p,A_MOVE);
|
||||||
end;
|
end;
|
||||||
A_SEB:
|
A_SEB:
|
||||||
{ TODO: can be handled similar to A_SEH, but it's almost never encountered }
|
{ 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:
|
A_SLL:
|
||||||
begin
|
begin
|
||||||
@ -384,10 +409,11 @@ unit aoptcpu;
|
|||||||
p.free;
|
p.free;
|
||||||
next.free;
|
next.free;
|
||||||
p:=next2;
|
p:=next2;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
TryRemoveMov(p,A_MOVE);
|
result:=TryRemoveMov(p,A_MOVE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
A_SRL:
|
A_SRL:
|
||||||
@ -415,9 +441,10 @@ unit aoptcpu;
|
|||||||
begin
|
begin
|
||||||
asml.remove(next);
|
asml.remove(next);
|
||||||
next.free;
|
next.free;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
TryRemoveMov(p,A_MOVE);
|
result:=TryRemoveMov(p,A_MOVE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
A_ANDI:
|
A_ANDI:
|
||||||
@ -445,6 +472,7 @@ unit aoptcpu;
|
|||||||
asml.remove(next2);
|
asml.remove(next2);
|
||||||
next.free;
|
next.free;
|
||||||
next2.free;
|
next2.free;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
{ Remove zero extension if register is used only for byte/word memory store }
|
{ Remove zero extension if register is used only for byte/word memory store }
|
||||||
else if (taicpu(p).oper[2]^.typ=top_const) and
|
else if (taicpu(p).oper[2]^.typ=top_const) and
|
||||||
@ -459,9 +487,10 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
TryRemoveMov(p,A_MOVE);
|
result:=TryRemoveMov(p,A_MOVE);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
A_MOV_S:
|
A_MOV_S:
|
||||||
@ -470,7 +499,7 @@ unit aoptcpu;
|
|||||||
(next.typ=ait_instruction) then
|
(next.typ=ait_instruction) then
|
||||||
begin
|
begin
|
||||||
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SWC1]) then
|
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SWC1]) then
|
||||||
{ optimization successful };
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -480,7 +509,7 @@ unit aoptcpu;
|
|||||||
(next.typ=ait_instruction) then
|
(next.typ=ait_instruction) then
|
||||||
begin
|
begin
|
||||||
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SDC1]) then
|
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SDC1]) then
|
||||||
{ optimization successful };
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -492,12 +521,12 @@ unit aoptcpu;
|
|||||||
begin
|
begin
|
||||||
{ MOVE Rx,Ry; store Rx,(ref); dealloc Rx ==> store Ry,(ref) }
|
{ MOVE Rx,Ry; store Rx,(ref); dealloc Rx ==> store Ry,(ref) }
|
||||||
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SB,A_SH,A_SW]) then
|
if TryRemoveMovBeforeStore(p,taicpu(next),[A_SB,A_SH,A_SW]) then
|
||||||
{ optimization successful }
|
result:=true
|
||||||
else if TryRemoveMovToRefIndex(p,taicpu(next)) then
|
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,Rx,any ==> opcode Rx,Ry,any
|
||||||
MOVE Rx,Ry; opcode Rx,Rz,Rx ==> opcode Rx,Rz,Ry }
|
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
|
MatchOperand(taicpu(next).oper[0]^,taicpu(p).oper[0]^.reg) then
|
||||||
begin
|
begin
|
||||||
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
|
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
|
||||||
@ -506,6 +535,7 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
{ TODO: if Ry=NR_R0, this effectively changes instruction into MOVE,
|
{ TODO: if Ry=NR_R0, this effectively changes instruction into MOVE,
|
||||||
providing further optimization possibilities }
|
providing further optimization possibilities }
|
||||||
@ -515,10 +545,12 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
{ MOVE Rx,Ry; opcode Rz,Rx,any; dealloc Rx ==> opcode Rz,Ry,any }
|
{ 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
|
Assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.next))) then
|
||||||
begin
|
begin
|
||||||
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
|
if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
|
||||||
@ -527,6 +559,7 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
else if MatchOperand(taicpu(next).oper[2]^,taicpu(p).oper[0]^.reg) then
|
else if MatchOperand(taicpu(next).oper[2]^,taicpu(p).oper[0]^.reg) then
|
||||||
begin
|
begin
|
||||||
@ -534,25 +567,32 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
{ MULT[U] must be handled separately due to different operand numbers }
|
{ MULT[U] and cond.branches must be handled separately due to different operand numbers }
|
||||||
else if (taicpu(next).opcode in [A_MULT,A_MULTU]) and
|
else if (taicpu(next).opcode in [A_MULT,A_MULTU,A_BC]) and
|
||||||
Assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.next))) then
|
Assigned(FindRegDealloc(taicpu(p).oper[0]^.reg,tai(next.next))) then
|
||||||
begin
|
begin
|
||||||
if MatchOperand(taicpu(next).oper[0]^,taicpu(p).oper[0]^.reg) then
|
if MatchOperand(taicpu(next).oper[0]^,taicpu(p).oper[0]^.reg) then
|
||||||
begin
|
begin
|
||||||
taicpu(next).loadreg(0,taicpu(p).oper[1]^.reg);
|
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);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end
|
end
|
||||||
else if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
|
else if MatchOperand(taicpu(next).oper[1]^,taicpu(p).oper[0]^.reg) then
|
||||||
begin
|
begin
|
||||||
taicpu(next).loadreg(1,taicpu(p).oper[1]^.reg);
|
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);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if TryRemoveMov(p,A_MOVE) then
|
else if TryRemoveMov(p,A_MOVE) then
|
||||||
@ -564,9 +604,9 @@ unit aoptcpu;
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=next;
|
p:=next;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{ TODO: MOVE Rx,Ry; Bcc Rx,Rz,label; dealloc Rx ==> Bcc Ry,Rz,label }
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -610,28 +650,51 @@ unit aoptcpu;
|
|||||||
result:=TryRemoveMov(p,A_MOVE);
|
result:=TryRemoveMov(p,A_MOVE);
|
||||||
end;
|
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_LB,A_LBU,A_LH,A_LHU,A_LW,
|
||||||
A_ADD,A_ADDU,
|
|
||||||
A_ADDI,
|
A_ADDI,
|
||||||
A_SUB,A_SUBU,
|
A_SUB,A_SUBU,
|
||||||
A_SRA,A_SRAV,
|
A_SRA,A_SRAV,
|
||||||
A_SRLV,
|
A_SRLV,
|
||||||
A_SLLV,
|
A_SLLV,
|
||||||
A_MFLO,A_MFHI,
|
A_MFLO,A_MFHI,
|
||||||
A_AND,A_OR,A_XOR,A_ORI,A_XORI:
|
A_AND,A_XOR,A_ORI,A_XORI:
|
||||||
TryRemoveMov(p,A_MOVE);
|
result:=TryRemoveMov(p,A_MOVE);
|
||||||
|
|
||||||
A_LWC1,
|
A_LWC1,
|
||||||
A_ADD_s, A_SUB_s, A_MUL_s, A_DIV_s,
|
A_ADD_s, A_SUB_s, A_MUL_s, A_DIV_s,
|
||||||
A_ABS_s, A_NEG_s, A_SQRT_s,
|
A_ABS_s, A_NEG_s, A_SQRT_s,
|
||||||
A_CVT_s_w, A_CVT_s_l, A_CVT_s_d:
|
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_LDC1,
|
||||||
A_ADD_d, A_SUB_d, A_MUL_d, A_DIV_d,
|
A_ADD_d, A_SUB_d, A_MUL_d, A_DIV_d,
|
||||||
A_ABS_d, A_NEG_d, A_SQRT_d,
|
A_ABS_d, A_NEG_d, A_SQRT_d,
|
||||||
A_CVT_d_w, A_CVT_d_l, A_CVT_d_s:
|
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;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user