* patch by J. Gareth Moreton: Long-range MOV + MOVS/Z optimisation, resolves #37390

git-svn-id: trunk@46346 -
This commit is contained in:
florian 2020-08-09 18:55:46 +00:00
parent 867786c953
commit 8761545848

View File

@ -2611,8 +2611,11 @@ unit aoptx86;
checking for GetNextInstruction_p } checking for GetNextInstruction_p }
{ GetNextInstructionUsingReg only searches one instruction ahead unless -O3 is specified } { GetNextInstructionUsingReg only searches one instruction ahead unless -O3 is specified }
GetNextInstructionUsingReg(hp1,hp2,taicpu(p).oper[1]^.reg) and GetNextInstructionUsingReg(hp1,hp2,taicpu(p).oper[1]^.reg) and
MatchInstruction(hp2,A_MOV,[]) and (hp2.typ=ait_instruction) then
MatchOperand(taicpu(p).oper[1]^,taicpu(hp2).oper[0]^) and begin
case taicpu(hp2).opcode of
A_MOV:
if MatchOperand(taicpu(hp2).oper[0]^,taicpu(p).oper[1]^.reg) and
((taicpu(p).oper[0]^.typ=top_const) or ((taicpu(p).oper[0]^.typ=top_const) or
((taicpu(p).oper[0]^.typ=top_reg) and ((taicpu(p).oper[0]^.typ=top_reg) and
not(RegUsedBetween(taicpu(p).oper[0]^.reg, p, hp2)) not(RegUsedBetween(taicpu(p).oper[0]^.reg, p, hp2))
@ -2734,6 +2737,46 @@ unit aoptx86;
Internalerror(2019103001); Internalerror(2019103001);
end; end;
end; end;
A_MOVZX, A_MOVSX{$ifdef x86_64}, A_MOVSXD{$endif x86_64}:
if MatchOpType(taicpu(hp2), top_reg, top_reg) and
MatchOperand(taicpu(hp2).oper[0]^, taicpu(p).oper[1]^.reg) and
SuperRegistersEqual(taicpu(hp2).oper[1]^.reg, taicpu(p).oper[1]^.reg) then
begin
{
Change from:
mov ###, %reg
...
movs/z %reg,%reg (Same register, just different sizes)
To:
movs/z ###, %reg (Longer version)
...
(remove)
}
DebugMsg(SPeepholeOptimization + 'MovMovs/z2Mov/s/z done', p);
taicpu(p).oper[1]^.reg := taicpu(hp2).oper[1]^.reg;
{ Keep the first instruction as mov if ### is a constant }
if taicpu(p).oper[0]^.typ = top_const then
taicpu(p).opsize := reg2opsize(taicpu(hp2).oper[1]^.reg)
else
begin
taicpu(p).opcode := taicpu(hp2).opcode;
taicpu(p).opsize := taicpu(hp2).opsize;
end;
DebugMsg(SPeepholeOptimization + 'Removed movs/z instruction and extended earlier write (MovMovs/z2Mov/s/z)', hp2);
AllocRegBetween(taicpu(hp2).oper[1]^.reg, p, hp2, UsedRegs);
AsmL.Remove(hp2);
hp2.Free;
Result := True;
Exit;
end;
else
;
end;
end;
if (aoc_MovAnd2Mov_3 in OptsToCheck) and if (aoc_MovAnd2Mov_3 in OptsToCheck) and
(taicpu(p).oper[1]^.typ = top_reg) and (taicpu(p).oper[1]^.typ = top_reg) and