mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 05:29:21 +02:00
New MOV optimisation that helps reduce instruction count and memory accesses
This commit is contained in:
parent
985e8d3d13
commit
bb49c190af
@ -3517,6 +3517,74 @@ unit aoptx86;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ mov x,reg1; mov y,reg1 -> mov y,reg1 is handled by the Mov2Nop 5 optimisation }
|
{ mov x,reg1; mov y,reg1 -> mov y,reg1 is handled by the Mov2Nop 5 optimisation }
|
||||||
|
|
||||||
|
{ Change:
|
||||||
|
movl %reg1,%reg2
|
||||||
|
movl x(%reg1),%reg1 (If something other than %reg1 is written to, DeepMOVOpt would have caught it)
|
||||||
|
movl x(%reg2),%regX (%regX can be %reg2 or something else)
|
||||||
|
To:
|
||||||
|
movl %reg1,%reg2 (if %regX = %reg2, then remove this instruction)
|
||||||
|
movl x(%reg1),%reg1
|
||||||
|
movl %reg1,%regX
|
||||||
|
}
|
||||||
|
if MatchOpType(taicpu(p), top_reg, top_reg) then
|
||||||
|
begin
|
||||||
|
CurrentReg := taicpu(p).oper[0]^.reg;
|
||||||
|
ActiveReg := taicpu(p).oper[1]^.reg;
|
||||||
|
|
||||||
|
if (taicpu(hp1).oper[0]^.typ = top_ref) { The other operand will be a register } and
|
||||||
|
(taicpu(hp1).oper[1]^.reg = CurrentReg) and
|
||||||
|
RegInRef(CurrentReg, taicpu(hp1).oper[0]^.ref^) and
|
||||||
|
GetNextInstruction(hp1, hp2) and
|
||||||
|
MatchInstruction(hp2, A_MOV, [taicpu(p).opsize]) and
|
||||||
|
(taicpu(hp2).oper[0]^.typ = top_ref) { The other operand will be a register } then
|
||||||
|
begin
|
||||||
|
SourceRef := taicpu(hp2).oper[0]^.ref^;
|
||||||
|
if RegInRef(ActiveReg, SourceRef) and
|
||||||
|
{ If %reg1 also appears in the second reference, then it will
|
||||||
|
not refer to the same memory block as the first reference }
|
||||||
|
not RegInRef(CurrentReg, SourceRef) then
|
||||||
|
begin
|
||||||
|
{ Check to see if the references match if %reg2 is changed to %reg1 }
|
||||||
|
if SourceRef.base = ActiveReg then
|
||||||
|
SourceRef.base := CurrentReg;
|
||||||
|
|
||||||
|
if SourceRef.index = ActiveReg then
|
||||||
|
SourceRef.index := CurrentReg;
|
||||||
|
|
||||||
|
{ RefsEqual also checks to ensure both references are non-volatile }
|
||||||
|
if RefsEqual(taicpu(hp1).oper[0]^.ref^, SourceRef) then
|
||||||
|
begin
|
||||||
|
taicpu(hp2).loadreg(0, CurrentReg);
|
||||||
|
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Optimised register duplication and memory read (MovMovMov2MovMovMov)', p);
|
||||||
|
Result := True;
|
||||||
|
if taicpu(hp2).oper[1]^.reg = ActiveReg then
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Mov2Nop 5a done', p);
|
||||||
|
RemoveCurrentP(p, hp1);
|
||||||
|
Exit;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ Check to see if %reg2 is no longer in use }
|
||||||
|
TransferUsedRegs(TmpUsedRegs);
|
||||||
|
UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
||||||
|
UpdateUsedRegs(TmpUsedRegs, tai(hp1.Next));
|
||||||
|
|
||||||
|
if not RegUsedAfterInstruction(ActiveReg, hp2, TmpUsedRegs) then
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Mov2Nop 5b done', p);
|
||||||
|
RemoveCurrentP(p, hp1);
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ If we reach this point, p and hp1 weren't actually modified,
|
||||||
|
so we can do a bit more work on this pass }
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ search further than the next instruction for a mov (as long as it's not a jump) }
|
{ search further than the next instruction for a mov (as long as it's not a jump) }
|
||||||
|
Loading…
Reference in New Issue
Block a user