mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 16:29:24 +02:00
Rerun the peephole optimizer after removing the current instruction.
This lets the optimizer pickup on more possible optimizations. git-svn-id: trunk@26606 -
This commit is contained in:
parent
57ff589ec7
commit
9e0af11ad8
@ -38,7 +38,7 @@ Type
|
|||||||
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
||||||
procedure PeepHoleOptPass2;override;
|
procedure PeepHoleOptPass2;override;
|
||||||
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override;
|
Function RegInInstruction(Reg: TRegister; p1: tai): Boolean;override;
|
||||||
procedure RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string);
|
function RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string): boolean;
|
||||||
function RegUsedAfterInstruction(reg: Tregister; p: tai;
|
function RegUsedAfterInstruction(reg: Tregister; p: tai;
|
||||||
var AllUsedRegs: TAllUsedRegs): Boolean;
|
var AllUsedRegs: TAllUsedRegs): Boolean;
|
||||||
{ returns true if reg reaches it's end of life at p, this means it is either
|
{ returns true if reg reaches it's end of life at p, this means it is either
|
||||||
@ -152,8 +152,9 @@ Implementation
|
|||||||
result := (oper.typ = top_reg) and (oper.reg = reg);
|
result := (oper.typ = top_reg) and (oper.reg = reg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure RemoveRedundantMove(const cmpp: tai; movp: tai; asml: TAsmList);
|
function RemoveRedundantMove(const cmpp: tai; movp: tai; asml: TAsmList):Boolean;
|
||||||
begin
|
begin
|
||||||
|
Result:=false;
|
||||||
if (taicpu(movp).condition = C_EQ) and
|
if (taicpu(movp).condition = C_EQ) and
|
||||||
(taicpu(cmpp).oper[0]^.reg = taicpu(movp).oper[0]^.reg) and
|
(taicpu(cmpp).oper[0]^.reg = taicpu(movp).oper[0]^.reg) and
|
||||||
(taicpu(cmpp).oper[1]^.val = taicpu(movp).oper[1]^.val) then
|
(taicpu(cmpp).oper[1]^.val = taicpu(movp).oper[1]^.val) then
|
||||||
@ -161,6 +162,7 @@ Implementation
|
|||||||
asml.insertafter(tai_comment.Create(strpnew('Peephole CmpMovMov - Removed redundant moveq')), movp);
|
asml.insertafter(tai_comment.Create(strpnew('Peephole CmpMovMov - Removed redundant moveq')), movp);
|
||||||
asml.remove(movp);
|
asml.remove(movp);
|
||||||
movp.free;
|
movp.free;
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -337,12 +339,13 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
{$endif DEBUG_AOPTCPU}
|
{$endif DEBUG_AOPTCPU}
|
||||||
|
|
||||||
procedure TCpuAsmOptimizer.RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string);
|
function TCpuAsmOptimizer.RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string):boolean;
|
||||||
var
|
var
|
||||||
alloc,
|
alloc,
|
||||||
dealloc : tai_regalloc;
|
dealloc : tai_regalloc;
|
||||||
hp1 : tai;
|
hp1 : tai;
|
||||||
begin
|
begin
|
||||||
|
Result:=false;
|
||||||
if MatchInstruction(movp, A_MOV, [taicpu(p).condition], [PF_None]) and
|
if MatchInstruction(movp, A_MOV, [taicpu(p).condition], [PF_None]) and
|
||||||
(taicpu(movp).ops=2) and {We can't optimize if there is a shiftop}
|
(taicpu(movp).ops=2) and {We can't optimize if there is a shiftop}
|
||||||
MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and
|
MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and
|
||||||
@ -374,6 +377,7 @@ Implementation
|
|||||||
if assigned(dealloc) then
|
if assigned(dealloc) then
|
||||||
begin
|
begin
|
||||||
DebugMsg('Peephole '+optimizer+' removed superfluous mov', movp);
|
DebugMsg('Peephole '+optimizer+' removed superfluous mov', movp);
|
||||||
|
result:=true;
|
||||||
|
|
||||||
{ taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation
|
{ taicpu(p).oper[0]^.reg is not used anymore, try to find its allocation
|
||||||
and remove it if possible }
|
and remove it if possible }
|
||||||
@ -586,6 +590,7 @@ Implementation
|
|||||||
|
|
||||||
asml.remove(hp1);
|
asml.remove(hp1);
|
||||||
hp1.free;
|
hp1.free;
|
||||||
|
Result:=true;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
case taicpu(p).opcode of
|
case taicpu(p).opcode of
|
||||||
@ -647,8 +652,9 @@ Implementation
|
|||||||
taicpu(p).oppostfix:=PF_D;
|
taicpu(p).oppostfix:=PF_D;
|
||||||
asml.remove(hp1);
|
asml.remove(hp1);
|
||||||
hp1.free;
|
hp1.free;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
LookForPostindexedPattern(taicpu(p));
|
Result:=LookForPostindexedPattern(taicpu(p)) or Result;
|
||||||
end;
|
end;
|
||||||
A_LDR:
|
A_LDR:
|
||||||
begin
|
begin
|
||||||
@ -711,6 +717,7 @@ Implementation
|
|||||||
taicpu(p).oppostfix:=PF_D;
|
taicpu(p).oppostfix:=PF_D;
|
||||||
asml.remove(hp1);
|
asml.remove(hp1);
|
||||||
hp1.free;
|
hp1.free;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -738,8 +745,9 @@ Implementation
|
|||||||
taicpu(p).oper[0]^.reg := taicpu(hp1).oper[0]^.reg;
|
taicpu(p).oper[0]^.reg := taicpu(hp1).oper[0]^.reg;
|
||||||
asml.remove(hp1);
|
asml.remove(hp1);
|
||||||
hp1.free;
|
hp1.free;
|
||||||
|
result:=true;
|
||||||
end;
|
end;
|
||||||
LookForPostindexedPattern(taicpu(p));
|
Result:=LookForPostindexedPattern(taicpu(p)) or Result;
|
||||||
{ Remove superfluous mov after ldr
|
{ Remove superfluous mov after ldr
|
||||||
changes
|
changes
|
||||||
ldr reg1, ref
|
ldr reg1, ref
|
||||||
@ -754,8 +762,10 @@ Implementation
|
|||||||
* ldr+mov have the same conditions
|
* ldr+mov have the same conditions
|
||||||
* mov does not set flags
|
* mov does not set flags
|
||||||
}
|
}
|
||||||
if (taicpu(p).oppostfix<>PF_D) and GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
|
if (taicpu(p).oppostfix<>PF_D) and
|
||||||
RemoveSuperfluousMove(p, hp1, 'LdrMov2Ldr');
|
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
|
RemoveSuperfluousMove(p, hp1, 'LdrMov2Ldr') then
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
A_MOV:
|
A_MOV:
|
||||||
begin
|
begin
|
||||||
@ -803,6 +813,7 @@ Implementation
|
|||||||
p.free;
|
p.free;
|
||||||
hp1.free;
|
hp1.free;
|
||||||
p:=hp2;
|
p:=hp2;
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
ReleaseUsedRegs(TmpUsedRegs);
|
ReleaseUsedRegs(TmpUsedRegs);
|
||||||
end
|
end
|
||||||
@ -1090,6 +1101,7 @@ Implementation
|
|||||||
GetNextInstruction(hp2,hp1);
|
GetNextInstruction(hp2,hp1);
|
||||||
asml.remove(hp2);
|
asml.remove(hp2);
|
||||||
hp2.free;
|
hp2.free;
|
||||||
|
result:=true;
|
||||||
if not assigned(hp1) then break;
|
if not assigned(hp1) then break;
|
||||||
end
|
end
|
||||||
{
|
{
|
||||||
@ -1109,6 +1121,7 @@ Implementation
|
|||||||
p.free;
|
p.free;
|
||||||
p:=hp1;
|
p:=hp1;
|
||||||
GetNextInstruction(hp1,hp1);
|
GetNextInstruction(hp1,hp1);
|
||||||
|
result:=true;
|
||||||
if not assigned(hp1) then
|
if not assigned(hp1) then
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -1162,6 +1175,7 @@ Implementation
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=hp1;
|
p:=hp1;
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1301,6 +1315,7 @@ Implementation
|
|||||||
hp1.free;
|
hp1.free;
|
||||||
p:=hp2;
|
p:=hp2;
|
||||||
DebugMsg('Peephole FoldShiftProcess done', p);
|
DebugMsg('Peephole FoldShiftProcess done', p);
|
||||||
|
Result:=true;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1372,14 +1387,16 @@ Implementation
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=hp1;
|
p:=hp1;
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
{
|
{
|
||||||
Often we see shifts and then a superfluous mov to another register
|
Often we see shifts and then a superfluous mov to another register
|
||||||
In the future this might be handled in RedundantMovProcess when it uses RegisterTracking
|
In the future this might be handled in RedundantMovProcess when it uses RegisterTracking
|
||||||
}
|
}
|
||||||
if (taicpu(p).opcode = A_MOV) and
|
if (taicpu(p).opcode = A_MOV) and
|
||||||
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
|
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
RemoveSuperfluousMove(p, hp1, 'MovMov2Mov');
|
RemoveSuperfluousMove(p, hp1, 'MovMov2Mov') then
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
A_ADD,
|
A_ADD,
|
||||||
A_ADC,
|
A_ADC,
|
||||||
@ -1621,6 +1638,7 @@ Implementation
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=hp1;
|
p:=hp1;
|
||||||
|
result:=true;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1632,11 +1650,10 @@ Implementation
|
|||||||
to
|
to
|
||||||
add reg2, ...
|
add reg2, ...
|
||||||
}
|
}
|
||||||
if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
|
if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
begin
|
(taicpu(p).ops=3) and
|
||||||
if (taicpu(p).ops=3) then
|
RemoveSuperfluousMove(p, hp1, 'DataMov2Data') then
|
||||||
RemoveSuperfluousMove(p, hp1, 'DataMov2Data');
|
Result:=true;
|
||||||
end;
|
|
||||||
|
|
||||||
if MatchInstruction(p, [A_ADD,A_SUB], [C_None], [PF_None]) and
|
if MatchInstruction(p, [A_ADD,A_SUB], [C_None], [PF_None]) and
|
||||||
LookForPreindexedPattern(taicpu(p)) then
|
LookForPreindexedPattern(taicpu(p)) then
|
||||||
@ -1646,6 +1663,7 @@ Implementation
|
|||||||
asml.remove(p);
|
asml.remove(p);
|
||||||
p.free;
|
p.free;
|
||||||
p:=hp1;
|
p:=hp1;
|
||||||
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$ifdef dummy}
|
{$ifdef dummy}
|
||||||
@ -1795,11 +1813,9 @@ Implementation
|
|||||||
p:=hp2;
|
p:=hp2;
|
||||||
result:=true;
|
result:=true;
|
||||||
end
|
end
|
||||||
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
|
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
begin
|
RemoveSuperfluousMove(p, hp1, 'UxtbMov2Data') then
|
||||||
//if (taicpu(p).ops=3) then
|
Result:=true;
|
||||||
RemoveSuperfluousMove(p, hp1, 'UxtbMov2Data');
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
A_UXTH:
|
A_UXTH:
|
||||||
begin
|
begin
|
||||||
@ -1883,11 +1899,9 @@ Implementation
|
|||||||
p:=hp1;
|
p:=hp1;
|
||||||
result:=true;
|
result:=true;
|
||||||
end
|
end
|
||||||
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) then
|
else if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
begin
|
RemoveSuperfluousMove(p, hp1, 'UxthMov2Data') then
|
||||||
//if (taicpu(p).ops=3) then
|
Result:=true;
|
||||||
RemoveSuperfluousMove(p, hp1, 'UxthMov2Data');
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
A_CMP:
|
A_CMP:
|
||||||
begin
|
begin
|
||||||
@ -1908,8 +1922,8 @@ Implementation
|
|||||||
MatchInstruction(hp2, A_MOV, [C_EQ, C_NE], [PF_NONE]) and
|
MatchInstruction(hp2, A_MOV, [C_EQ, C_NE], [PF_NONE]) and
|
||||||
(taicpu(hp1).oper[1]^.typ = top_const) then
|
(taicpu(hp1).oper[1]^.typ = top_const) then
|
||||||
begin
|
begin
|
||||||
RemoveRedundantMove(p, hp1, asml);
|
Result:=RemoveRedundantMove(p, hp1, asml) or Result;
|
||||||
RemoveRedundantMove(p, hp2, asml);
|
Result:=RemoveRedundantMove(p, hp2, asml) or Result;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
A_STM:
|
A_STM:
|
||||||
|
Loading…
Reference in New Issue
Block a user