|
@@ -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;
|