mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 22:49:37 +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);
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user