mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-01 01:30:35 +02:00
* arm/a64: New "OptPass2TST" routine to catch "TST; B.c; AND -> ANDS; B.c" optimisation
This commit is contained in:
parent
9f19f582c4
commit
b18c10d0d8
@ -1266,6 +1266,8 @@ Implementation
|
||||
A_LDR,
|
||||
A_STR:
|
||||
Result:=OptPass2LDRSTR(p);
|
||||
A_TST:
|
||||
Result := OptPass2TST(p);
|
||||
else
|
||||
;
|
||||
end;
|
||||
|
@ -2396,6 +2396,8 @@ Implementation
|
||||
Result := OptPass2STM(p);
|
||||
A_STR:
|
||||
Result := OptPass2STR(p);
|
||||
A_TST:
|
||||
Result := OptPass2TST(p);
|
||||
else
|
||||
;
|
||||
end;
|
||||
|
@ -59,6 +59,7 @@ Type
|
||||
function OptPass1And(var p: tai): Boolean; virtual;
|
||||
|
||||
function OptPass2AND(var p: tai): Boolean;
|
||||
function OptPass2TST(var p: tai): Boolean;
|
||||
End;
|
||||
|
||||
function MatchInstruction(const instr: tai; const op: TCommonAsmOps; const cond: TAsmConds; const postfix: TOpPostfixes): boolean;
|
||||
@ -1692,5 +1693,120 @@ Implementation
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
|
||||
function TARMAsmOptimizer.OptPass2TST(var p: tai): Boolean;
|
||||
var
|
||||
hp1, hp2: tai;
|
||||
begin
|
||||
Result := False;
|
||||
if
|
||||
{$ifndef AARCH64}
|
||||
(taicpu(p).condition = C_None) and
|
||||
{$endif AARCH64}
|
||||
GetNextInstruction(p, hp1) and
|
||||
MatchInstruction(hp1, A_B, [C_EQ, C_NE], [PF_None]) and
|
||||
GetNextInstructionUsingReg(hp1, hp2, taicpu(p).oper[0]^.reg) then
|
||||
begin
|
||||
case taicpu(hp2).opcode of
|
||||
A_AND:
|
||||
{ Change:
|
||||
tst r1,##
|
||||
(r2 not in use, or r2 = r1)
|
||||
b.c .Lbl
|
||||
...
|
||||
and r2,r1,##
|
||||
|
||||
Optimise to:
|
||||
ands r2,r1,##
|
||||
b.c .Lbl
|
||||
...
|
||||
}
|
||||
if (taicpu(hp2).oppostfix in [PF_None, PF_S]) and
|
||||
{$ifndef AARCH64}
|
||||
(taicpu(hp2).condition = C_None) and
|
||||
{$endif AARCH64}
|
||||
(taicpu(hp2).ops = taicpu(p).ops + 1) and
|
||||
not RegInUsedRegs(taicpu(hp2).oper[0]^.reg, UsedRegs) and
|
||||
MatchOperand(taicpu(hp2).oper[1]^, taicpu(p).oper[0]^.reg) and
|
||||
MatchOperand(taicpu(hp2).oper[2]^, taicpu(p).oper[1]^) and
|
||||
(
|
||||
(taicpu(hp2).ops = 3) or
|
||||
MatchOperand(taicpu(hp2).oper[3]^, taicpu(p).oper[2]^)
|
||||
) and
|
||||
(
|
||||
not (cs_opt_level3 in current_settings.optimizerswitches) or
|
||||
(
|
||||
{ Make sure the target register isn't used in between }
|
||||
not RegUsedBetween(taicpu(hp2).oper[0]^.reg, hp1, hp2) and
|
||||
(
|
||||
{ If the second operand is a register, make sure it isn't modified in between }
|
||||
(taicpu(p).oper[1]^.typ <> top_reg) or
|
||||
not RegModifiedBetween(taicpu(p).oper[1]^.reg, hp1, hp2)
|
||||
)
|
||||
)
|
||||
) then
|
||||
begin
|
||||
AllocRegBetween(taicpu(hp2).oper[0]^.reg, p, hp2, UsedRegs);
|
||||
|
||||
if (taicpu(hp2).oppostfix = PF_S) then
|
||||
AllocRegBetween(NR_DEFAULTFLAGS, p, hp2, UsedRegs);
|
||||
|
||||
DebugMsg(SPeepholeOptimization + 'TST; B.c; AND -> ANDS; B.c (TstBcAnd2AndsBc)', p);
|
||||
taicpu(hp2).oppostfix := PF_S;
|
||||
|
||||
Asml.Remove(hp2);
|
||||
Asml.InsertAfter(hp2, p);
|
||||
|
||||
RemoveCurrentP(p, hp2);
|
||||
Result := True;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
A_TST:
|
||||
{ Change:
|
||||
tst r1,##
|
||||
b.c .Lbl
|
||||
... (flags not modified)
|
||||
tst r1,##
|
||||
|
||||
Remove second tst
|
||||
}
|
||||
if
|
||||
{$ifndef AARCH64}
|
||||
(taicpu(hp2).condition = C_None) and
|
||||
{$endif AARCH64}
|
||||
(taicpu(hp2).ops = taicpu(p).ops) and
|
||||
MatchOperand(taicpu(hp2).oper[0]^, taicpu(p).oper[0]^.reg) and
|
||||
MatchOperand(taicpu(hp2).oper[1]^, taicpu(p).oper[1]^) and
|
||||
(
|
||||
(taicpu(hp2).ops = 2) or
|
||||
MatchOperand(taicpu(hp2).oper[2]^, taicpu(p).oper[2]^)
|
||||
) and
|
||||
(
|
||||
not (cs_opt_level3 in current_settings.optimizerswitches) or
|
||||
(
|
||||
{ Make sure the flags aren't modified in between }
|
||||
not RegModifiedBetween(NR_DEFAULTFLAGS, hp1, hp2) and
|
||||
(
|
||||
{ If the second operand is a register, make sure it isn't modified in between }
|
||||
(taicpu(p).oper[1]^.typ <> top_reg) or
|
||||
not RegModifiedBetween(taicpu(p).oper[1]^.reg, hp1, hp2)
|
||||
)
|
||||
)
|
||||
) then
|
||||
begin
|
||||
DebugMsg(SPeepholeOptimization + 'TST; B.c; TST -> TST; B.c (TstBcTst2TstBc)', p);
|
||||
|
||||
AllocRegBetween(NR_DEFAULTFLAGS, hp1, hp2, UsedRegs);
|
||||
RemoveInstruction(hp2);
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
else
|
||||
;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user