mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-14 03:19:27 +02:00
Rerun peephole optimizers on the whole block
Up until now if a peephole optimizer matched we've only restarted from the current instruction. This patch restarts optimizations on the whole block if the previous run had at least one match. As this can take considerable time this will only be enabled if -O3 or higher is specified. git-svn-id: trunk@26640 -
This commit is contained in:
parent
4fa8998541
commit
81517fdf70
@ -1306,130 +1306,138 @@ Unit AoptObj;
|
||||
procedure TAOptObj.PeepHoleOptPass1;
|
||||
var
|
||||
p,hp1,hp2 : tai;
|
||||
stoploop:boolean;
|
||||
begin
|
||||
p := BlockStart;
|
||||
ClearUsedRegs;
|
||||
while (p <> BlockEnd) Do
|
||||
begin
|
||||
{ I'am not sure why this is done, UsedRegs should reflect the register usage before the instruction
|
||||
If an instruction needs the information of this, it can easily create a TempUsedRegs (FK)
|
||||
UpdateUsedRegs(tai(p.next));
|
||||
}
|
||||
{$ifdef DEBUG_OPTALLOC}
|
||||
if p.Typ=ait_instruction then
|
||||
InsertLLItem(tai(p.Previous),p,tai_comment.create(strpnew(GetAllocationString(UsedRegs))));
|
||||
{$endif DEBUG_OPTALLOC}
|
||||
if PeepHoleOptPass1Cpu(p) then
|
||||
begin
|
||||
UpdateUsedRegs(p);
|
||||
continue;
|
||||
end;
|
||||
case p.Typ Of
|
||||
ait_instruction:
|
||||
repeat
|
||||
stoploop:=true;
|
||||
p := BlockStart;
|
||||
ClearUsedRegs;
|
||||
while (p <> BlockEnd) Do
|
||||
begin
|
||||
{ I'am not sure why this is done, UsedRegs should reflect the register usage before the instruction
|
||||
If an instruction needs the information of this, it can easily create a TempUsedRegs (FK)
|
||||
UpdateUsedRegs(tai(p.next));
|
||||
}
|
||||
{$ifdef DEBUG_OPTALLOC}
|
||||
if p.Typ=ait_instruction then
|
||||
InsertLLItem(tai(p.Previous),p,tai_comment.create(strpnew(GetAllocationString(UsedRegs))));
|
||||
{$endif DEBUG_OPTALLOC}
|
||||
if PeepHoleOptPass1Cpu(p) then
|
||||
begin
|
||||
{ Handle Jmp Optimizations }
|
||||
if taicpu(p).is_jmp then
|
||||
begin
|
||||
{ the following if-block removes all code between a jmp and the next label,
|
||||
because it can never be executed
|
||||
}
|
||||
if IsJumpToLabel(taicpu(p)) then
|
||||
begin
|
||||
hp2:=p;
|
||||
while GetNextInstruction(hp2, hp1) and
|
||||
(hp1.typ <> ait_label) do
|
||||
if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
|
||||
begin
|
||||
if (hp1.typ = ait_instruction) and
|
||||
taicpu(hp1).is_jmp and
|
||||
(JumpTargetOp(taicpu(hp1))^.typ = top_ref) and
|
||||
(JumpTargetOp(taicpu(hp1))^.ref^.symbol is TAsmLabel) then
|
||||
TAsmLabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).decrefs;
|
||||
{ don't kill start/end of assembler block,
|
||||
no-line-info-start/end etc }
|
||||
if hp1.typ<>ait_marker then
|
||||
begin
|
||||
{$if defined(SPARC) or defined(MIPS) }
|
||||
if (hp1.typ=ait_instruction) and (taicpu(hp1).is_jmp) then
|
||||
RemoveDelaySlot(hp1);
|
||||
{$endif SPARC or MIPS }
|
||||
asml.remove(hp1);
|
||||
hp1.free;
|
||||
end
|
||||
else
|
||||
hp2:=hp1;
|
||||
end
|
||||
else break;
|
||||
end;
|
||||
{ remove jumps to a label coming right after them }
|
||||
if GetNextInstruction(p, hp1) then
|
||||
begin
|
||||
SkipEntryExitMarker(hp1,hp1);
|
||||
if FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp1) and
|
||||
{ TODO: FIXME removing the first instruction fails}
|
||||
(p<>blockstart) then
|
||||
begin
|
||||
tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol).decrefs;
|
||||
{$if defined(SPARC) or defined(MIPS)}
|
||||
RemoveDelaySlot(p);
|
||||
{$endif SPARC or MIPS}
|
||||
hp2:=tai(hp1.next);
|
||||
asml.remove(p);
|
||||
p.free;
|
||||
p:=hp2;
|
||||
continue;
|
||||
end
|
||||
else if assigned(hp1) then
|
||||
begin
|
||||
if hp1.typ = ait_label then
|
||||
SkipLabels(hp1,hp1);
|
||||
if (tai(hp1).typ=ait_instruction) and
|
||||
IsJumpToLabel(taicpu(hp1)) and
|
||||
GetNextInstruction(hp1, hp2) and
|
||||
FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp2) then
|
||||
stoploop:=false;
|
||||
UpdateUsedRegs(p);
|
||||
continue;
|
||||
end;
|
||||
case p.Typ Of
|
||||
ait_instruction:
|
||||
begin
|
||||
{ Handle Jmp Optimizations }
|
||||
if taicpu(p).is_jmp then
|
||||
begin
|
||||
{ the following if-block removes all code between a jmp and the next label,
|
||||
because it can never be executed
|
||||
}
|
||||
if IsJumpToLabel(taicpu(p)) then
|
||||
begin
|
||||
hp2:=p;
|
||||
while GetNextInstruction(hp2, hp1) and
|
||||
(hp1.typ <> ait_label) do
|
||||
if not(hp1.typ in ([ait_label,ait_align]+skipinstr)) then
|
||||
begin
|
||||
if (taicpu(p).opcode=aopt_condjmp)
|
||||
{$ifdef arm}
|
||||
and (taicpu(p).condition<>C_None)
|
||||
{$endif arm}
|
||||
then
|
||||
if (hp1.typ = ait_instruction) and
|
||||
taicpu(hp1).is_jmp and
|
||||
(JumpTargetOp(taicpu(hp1))^.typ = top_ref) and
|
||||
(JumpTargetOp(taicpu(hp1))^.ref^.symbol is TAsmLabel) then
|
||||
TAsmLabel(JumpTargetOp(taicpu(hp1))^.ref^.symbol).decrefs;
|
||||
{ don't kill start/end of assembler block,
|
||||
no-line-info-start/end etc }
|
||||
if hp1.typ<>ait_marker then
|
||||
begin
|
||||
taicpu(p).condition:=inverse_cond(taicpu(p).condition);
|
||||
tai_label(hp2).labsym.decrefs;
|
||||
JumpTargetOp(taicpu(p))^.ref^.symbol:=JumpTargetOp(taicpu(hp1))^.ref^.symbol;
|
||||
{ when freeing hp1, the reference count
|
||||
isn't decreased, so don't increase
|
||||
|
||||
taicpu(p).oper[0]^.ref^.symbol.increfs;
|
||||
}
|
||||
{$if defined(SPARC) or defined(MIPS)}
|
||||
RemoveDelaySlot(hp1);
|
||||
{$endif SPARC or MIPS}
|
||||
{$if defined(SPARC) or defined(MIPS) }
|
||||
if (hp1.typ=ait_instruction) and (taicpu(hp1).is_jmp) then
|
||||
RemoveDelaySlot(hp1);
|
||||
{$endif SPARC or MIPS }
|
||||
asml.remove(hp1);
|
||||
hp1.free;
|
||||
GetFinalDestination(taicpu(p),0);
|
||||
stoploop:=false;
|
||||
end
|
||||
else
|
||||
begin
|
||||
GetFinalDestination(taicpu(p),0);
|
||||
p:=tai(p.next);
|
||||
continue;
|
||||
end;
|
||||
hp2:=hp1;
|
||||
end
|
||||
else
|
||||
GetFinalDestination(taicpu(p),0);
|
||||
else break;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
{ All other optimizes }
|
||||
begin
|
||||
end; { if is_jmp }
|
||||
end;
|
||||
{ remove jumps to a label coming right after them }
|
||||
if GetNextInstruction(p, hp1) then
|
||||
begin
|
||||
SkipEntryExitMarker(hp1,hp1);
|
||||
if FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp1) and
|
||||
{ TODO: FIXME removing the first instruction fails}
|
||||
(p<>blockstart) then
|
||||
begin
|
||||
tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol).decrefs;
|
||||
{$if defined(SPARC) or defined(MIPS)}
|
||||
RemoveDelaySlot(p);
|
||||
{$endif SPARC or MIPS}
|
||||
hp2:=tai(hp1.next);
|
||||
asml.remove(p);
|
||||
p.free;
|
||||
p:=hp2;
|
||||
stoploop:=false;
|
||||
continue;
|
||||
end
|
||||
else if assigned(hp1) then
|
||||
begin
|
||||
if hp1.typ = ait_label then
|
||||
SkipLabels(hp1,hp1);
|
||||
if (tai(hp1).typ=ait_instruction) and
|
||||
IsJumpToLabel(taicpu(hp1)) and
|
||||
GetNextInstruction(hp1, hp2) and
|
||||
FindLabel(tasmlabel(JumpTargetOp(taicpu(p))^.ref^.symbol), hp2) then
|
||||
begin
|
||||
if (taicpu(p).opcode=aopt_condjmp)
|
||||
{$ifdef arm}
|
||||
and (taicpu(p).condition<>C_None)
|
||||
{$endif arm}
|
||||
then
|
||||
begin
|
||||
taicpu(p).condition:=inverse_cond(taicpu(p).condition);
|
||||
tai_label(hp2).labsym.decrefs;
|
||||
JumpTargetOp(taicpu(p))^.ref^.symbol:=JumpTargetOp(taicpu(hp1))^.ref^.symbol;
|
||||
{ when freeing hp1, the reference count
|
||||
isn't decreased, so don't increase
|
||||
|
||||
taicpu(p).oper[0]^.ref^.symbol.increfs;
|
||||
}
|
||||
{$if defined(SPARC) or defined(MIPS)}
|
||||
RemoveDelaySlot(hp1);
|
||||
{$endif SPARC or MIPS}
|
||||
asml.remove(hp1);
|
||||
hp1.free;
|
||||
stoploop:=false;
|
||||
GetFinalDestination(taicpu(p),0);
|
||||
end
|
||||
else
|
||||
begin
|
||||
GetFinalDestination(taicpu(p),0);
|
||||
p:=tai(p.next);
|
||||
continue;
|
||||
end;
|
||||
end
|
||||
else
|
||||
GetFinalDestination(taicpu(p),0);
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
{ All other optimizes }
|
||||
begin
|
||||
end; { if is_jmp }
|
||||
end;
|
||||
end;
|
||||
UpdateUsedRegs(p);
|
||||
p:=tai(p.next);
|
||||
end;
|
||||
UpdateUsedRegs(p);
|
||||
p:=tai(p.next);
|
||||
end;
|
||||
until stoploop or not(cs_opt_level3 in current_settings.optimizerswitches);
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user