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:
masta 2014-01-31 23:21:52 +00:00
parent 4fa8998541
commit 81517fdf70

View File

@ -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;