mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-28 14:35:21 +02:00
* arm: "OpCmp2OpS" moved to Pass 2 so it doesn't conflict with AND; CMP -> TST optimisation
This commit is contained in:
parent
bf29f2051c
commit
6b2e4fa413
@ -86,6 +86,7 @@ Type
|
|||||||
function OptPass1Push(var p: tai): Boolean;
|
function OptPass1Push(var p: tai): Boolean;
|
||||||
|
|
||||||
function OptPass2Bcc(var p: tai): Boolean;
|
function OptPass2Bcc(var p: tai): Boolean;
|
||||||
|
function OptPass2CMP(var p: tai): Boolean;
|
||||||
function OptPass2STM(var p: tai): Boolean;
|
function OptPass2STM(var p: tai): Boolean;
|
||||||
function OptPass2STR(var p: tai): Boolean;
|
function OptPass2STR(var p: tai): Boolean;
|
||||||
End;
|
End;
|
||||||
@ -853,53 +854,6 @@ Implementation
|
|||||||
else
|
else
|
||||||
hp1 := hp2;
|
hp1 := hp2;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
|
||||||
change
|
|
||||||
<op> reg,x,y
|
|
||||||
cmp reg,#0
|
|
||||||
into
|
|
||||||
<op>s reg,x,y
|
|
||||||
}
|
|
||||||
if (taicpu(p).oppostfix = PF_None) and
|
|
||||||
(taicpu(p).oper[1]^.val = 0) and
|
|
||||||
{ be careful here, following instructions could use other flags
|
|
||||||
however after a jump fpc never depends on the value of flags }
|
|
||||||
{ All above instructions set Z and N according to the following
|
|
||||||
Z := result = 0;
|
|
||||||
N := result[31];
|
|
||||||
EQ = Z=1; NE = Z=0;
|
|
||||||
MI = N=1; PL = N=0; }
|
|
||||||
(MatchInstruction(hp1, A_B, [C_EQ,C_NE,C_MI,C_PL], []) or
|
|
||||||
{ mov is also possible, but only if there is no shifter operand, it could be an rxx,
|
|
||||||
we are too lazy to check if it is rxx or something else }
|
|
||||||
(MatchInstruction(hp1, A_MOV, [C_EQ,C_NE,C_MI,C_PL], []) and (taicpu(hp1).ops=2))) and
|
|
||||||
GetLastInstruction(p, hp_last) and
|
|
||||||
MatchInstruction(hp_last, [A_ADC,A_ADD,A_BIC,A_SUB,A_MUL,A_MVN,A_MOV,A_ORR,
|
|
||||||
A_EOR,A_AND,A_RSB,A_RSC,A_SBC,A_MLA], [C_None], [PF_None]) and
|
|
||||||
(
|
|
||||||
{ mlas is only allowed in arm mode }
|
|
||||||
(taicpu(hp_last).opcode<>A_MLA) or
|
|
||||||
(current_settings.instructionset<>is_thumb)
|
|
||||||
) and
|
|
||||||
(taicpu(hp_last).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
|
|
||||||
assigned(FindRegDealloc(NR_DEFAULTFLAGS,tai(hp1.Next))) then
|
|
||||||
begin
|
|
||||||
DebugMsg(SPeepholeOptimization + 'OpCmp2OpS done', hp_last);
|
|
||||||
|
|
||||||
taicpu(hp_last).oppostfix:=PF_S;
|
|
||||||
|
|
||||||
{ move flag allocation if possible }
|
|
||||||
hp1:=FindRegAlloc(NR_DEFAULTFLAGS,tai(hp_last.Next));
|
|
||||||
if assigned(hp1) then
|
|
||||||
begin
|
|
||||||
asml.Remove(hp1);
|
|
||||||
asml.insertbefore(hp1, hp_last);
|
|
||||||
end;
|
|
||||||
|
|
||||||
RemoveCurrentP(p);
|
|
||||||
Result:=true;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2135,6 +2089,61 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.OptPass2CMP(var p: tai): Boolean;
|
||||||
|
var
|
||||||
|
hp1, hp_last: tai;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
{
|
||||||
|
change
|
||||||
|
<op> reg,x,y
|
||||||
|
cmp reg,#0
|
||||||
|
into
|
||||||
|
<op>s reg,x,y
|
||||||
|
}
|
||||||
|
if (taicpu(p).oppostfix = PF_None) and
|
||||||
|
(taicpu(p).oper[1]^.val = 0) and
|
||||||
|
GetNextInstruction(p, hp1) and
|
||||||
|
{ be careful here, following instructions could use other flags
|
||||||
|
however after a jump fpc never depends on the value of flags }
|
||||||
|
{ All above instructions set Z and N according to the following
|
||||||
|
Z := result = 0;
|
||||||
|
N := result[31];
|
||||||
|
EQ = Z=1; NE = Z=0;
|
||||||
|
MI = N=1; PL = N=0; }
|
||||||
|
(MatchInstruction(hp1, A_B, [C_EQ,C_NE,C_MI,C_PL], []) or
|
||||||
|
{ mov is also possible, but only if there is no shifter operand, it could be an rxx,
|
||||||
|
we are too lazy to check if it is rxx or something else }
|
||||||
|
(MatchInstruction(hp1, A_MOV, [C_EQ,C_NE,C_MI,C_PL], []) and (taicpu(hp1).ops=2))) and
|
||||||
|
GetLastInstruction(p, hp_last) and
|
||||||
|
MatchInstruction(hp_last, [A_ADC,A_ADD,A_BIC,A_SUB,A_MUL,A_MVN,A_MOV,A_ORR,
|
||||||
|
A_EOR,A_AND,A_RSB,A_RSC,A_SBC,A_MLA], [C_None], [PF_None]) and
|
||||||
|
(
|
||||||
|
{ mlas is only allowed in arm mode }
|
||||||
|
(taicpu(hp_last).opcode<>A_MLA) or
|
||||||
|
(current_settings.instructionset<>is_thumb)
|
||||||
|
) and
|
||||||
|
(taicpu(hp_last).oper[0]^.reg = taicpu(p).oper[0]^.reg) and
|
||||||
|
assigned(FindRegDealloc(NR_DEFAULTFLAGS,tai(hp1.Next))) then
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'OpCmp2OpS done', hp_last);
|
||||||
|
|
||||||
|
taicpu(hp_last).oppostfix:=PF_S;
|
||||||
|
|
||||||
|
{ move flag allocation if possible }
|
||||||
|
hp1:=FindRegAlloc(NR_DEFAULTFLAGS,tai(hp_last.Next));
|
||||||
|
if assigned(hp1) then
|
||||||
|
begin
|
||||||
|
asml.Remove(hp1);
|
||||||
|
asml.insertbefore(hp1, hp_last);
|
||||||
|
end;
|
||||||
|
|
||||||
|
RemoveCurrentP(p);
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TCpuAsmOptimizer.OptPass2STR(var p: tai): Boolean;
|
function TCpuAsmOptimizer.OptPass2STR(var p: tai): Boolean;
|
||||||
var
|
var
|
||||||
hp1: tai;
|
hp1: tai;
|
||||||
@ -2390,6 +2399,8 @@ Implementation
|
|||||||
case taicpu(p).opcode of
|
case taicpu(p).opcode of
|
||||||
A_AND:
|
A_AND:
|
||||||
Result := OptPass2AND(p);
|
Result := OptPass2AND(p);
|
||||||
|
A_CMP:
|
||||||
|
Result := OptPass2CMP(p);
|
||||||
A_B:
|
A_B:
|
||||||
Result := OptPass2Bcc(p);
|
Result := OptPass2Bcc(p);
|
||||||
A_STM:
|
A_STM:
|
||||||
|
Loading…
Reference in New Issue
Block a user