mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 12:49:12 +02:00
* i386 does not use anymore its own assembler optimizer loops
git-svn-id: trunk@43464 -
This commit is contained in:
parent
0ab0eefae0
commit
632f13c47a
@ -35,10 +35,11 @@ unit aoptcpu;
|
||||
|
||||
Type
|
||||
TCpuAsmOptimizer = class(TX86AsmOptimizer)
|
||||
procedure Optimize; override;
|
||||
procedure PrePeepHoleOpts; override;
|
||||
procedure PeepHoleOptPass1; override;
|
||||
procedure PeepHoleOptPass2; override;
|
||||
function PrePeepHoleOptsCpu(var p: tai): boolean; override;
|
||||
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
||||
function PeepHoleOptPass2Cpu(var p: tai): boolean; override;
|
||||
function PostPeepHoleOptsCpu(var p : tai) : boolean; override;
|
||||
|
||||
procedure PostPeepHoleOpts; override;
|
||||
end;
|
||||
|
||||
@ -82,28 +83,22 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TCPUAsmOptimizer.PrePeepHoleOpts;
|
||||
var
|
||||
p: tai;
|
||||
function TCPUAsmOPtimizer.PrePeepHoleOptsCpu(var p: tai): boolean;
|
||||
begin
|
||||
p := BlockStart;
|
||||
while (p <> BlockEnd) Do
|
||||
begin
|
||||
case p.Typ Of
|
||||
Ait_Instruction:
|
||||
Result:=False;
|
||||
case p.typ of
|
||||
ait_instruction:
|
||||
begin
|
||||
if InsContainsSegRef(taicpu(p)) then
|
||||
begin
|
||||
p := tai(p.next);
|
||||
continue;
|
||||
Result:=true;
|
||||
end;
|
||||
case taicpu(p).opcode Of
|
||||
A_IMUL:
|
||||
if PrePeepholeOptIMUL(p) then
|
||||
Continue;
|
||||
Result:=PrePeepholeOptIMUL(p);
|
||||
A_SAR,A_SHR:
|
||||
if PrePeepholeOptSxx(p) then
|
||||
continue;
|
||||
Result:=PrePeepholeOptSxx(p);
|
||||
A_XOR:
|
||||
begin
|
||||
if (taicpu(p).oper[0]^.typ = top_reg) and
|
||||
@ -114,6 +109,7 @@ begin
|
||||
begin
|
||||
taicpu(p).opcode := A_MOV;
|
||||
taicpu(p).loadConst(0,0);
|
||||
Result:=true;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
@ -123,13 +119,10 @@ begin
|
||||
else
|
||||
;
|
||||
end;
|
||||
p := tai(p.next)
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{ First pass of peephole optimizations }
|
||||
procedure TCPUAsmOPtimizer.PeepHoleOptPass1;
|
||||
function TCPUAsmOPtimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
||||
|
||||
function WriteOk : Boolean;
|
||||
begin
|
||||
@ -138,7 +131,7 @@ function WriteOk : Boolean;
|
||||
end;
|
||||
|
||||
var
|
||||
p,hp1,hp2 : tai;
|
||||
hp1,hp2 : tai;
|
||||
hp3,hp4: tai;
|
||||
v:aint;
|
||||
|
||||
@ -241,11 +234,7 @@ var
|
||||
end;
|
||||
|
||||
begin
|
||||
p := BlockStart;
|
||||
ClearUsedRegs;
|
||||
while (p <> BlockEnd) Do
|
||||
begin
|
||||
UpDateUsedRegs(UsedRegs, tai(p.next));
|
||||
result:=False;
|
||||
case p.Typ Of
|
||||
ait_instruction:
|
||||
begin
|
||||
@ -253,7 +242,8 @@ begin
|
||||
if InsContainsSegRef(taicpu(p)) then
|
||||
begin
|
||||
p:=tai(p.next);
|
||||
continue;
|
||||
Result:=true;
|
||||
exit;
|
||||
end;
|
||||
{ Handle Jmp Optimizations }
|
||||
if taicpu(p).is_jmp then
|
||||
@ -292,7 +282,8 @@ begin
|
||||
asml.remove(p);
|
||||
p.free;
|
||||
p:=hp2;
|
||||
continue;
|
||||
Result:=true;
|
||||
exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
@ -321,7 +312,8 @@ begin
|
||||
begin
|
||||
GetFinalDestination(asml, taicpu(p),0);
|
||||
p:=tai(p.next);
|
||||
continue;
|
||||
Result:=true;
|
||||
exit;
|
||||
end;
|
||||
end
|
||||
else
|
||||
@ -334,8 +326,7 @@ begin
|
||||
begin
|
||||
case taicpu(p).opcode Of
|
||||
A_AND:
|
||||
if OptPass1And(p) then
|
||||
continue;
|
||||
Result:=OptPass1And(p);
|
||||
A_CMP:
|
||||
begin
|
||||
{ cmp register,$8000 neg register
|
||||
@ -366,7 +357,7 @@ begin
|
||||
Taicpu(hp1).condition:=C_O
|
||||
else
|
||||
Taicpu(hp1).condition:=C_NO;
|
||||
continue;
|
||||
Result:=true;
|
||||
end;
|
||||
{
|
||||
@@2: @@2:
|
||||
@ -412,34 +403,20 @@ begin
|
||||
p.free;
|
||||
hp1.free;
|
||||
p := hp2;
|
||||
continue;
|
||||
Result:=true;
|
||||
end
|
||||
end;
|
||||
A_FLD:
|
||||
if OptPass1FLD(p) then
|
||||
continue;
|
||||
Result:=OptPass1FLD(p);
|
||||
A_FSTP,A_FISTP:
|
||||
if OptPass1FSTP(p) then
|
||||
continue;
|
||||
Result:=OptPass1FSTP(p);
|
||||
A_LEA:
|
||||
begin
|
||||
if OptPass1LEA(p) then
|
||||
continue;
|
||||
end;
|
||||
|
||||
Result:=OptPass1LEA(p);
|
||||
A_MOV:
|
||||
begin
|
||||
If OptPass1MOV(p) then
|
||||
Continue;
|
||||
end;
|
||||
|
||||
Result:=OptPass1MOV(p);
|
||||
A_MOVSX,
|
||||
A_MOVZX :
|
||||
begin
|
||||
If OptPass1Movx(p) then
|
||||
Continue
|
||||
end;
|
||||
|
||||
Result:=OptPass1Movx(p);
|
||||
(* should not be generated anymore by the current code generator
|
||||
A_POP:
|
||||
begin
|
||||
@ -539,14 +516,13 @@ begin
|
||||
taicpu(p).loadConst(0,taicpu(p).oper[0]^.val shl 16 + word(taicpu(hp1).oper[0]^.val));
|
||||
asml.remove(hp1);
|
||||
hp1.free;
|
||||
Result:=true;
|
||||
end;
|
||||
end;
|
||||
A_SHL, A_SAL:
|
||||
if OptPass1SHLSAL(p) then
|
||||
Continue;
|
||||
Result:=OptPass1SHLSAL(p);
|
||||
A_SUB:
|
||||
if OptPass1Sub(p) then
|
||||
continue;
|
||||
Result:=OptPass1Sub(p);
|
||||
A_MOVAPD,
|
||||
A_MOVAPS,
|
||||
A_MOVUPD,
|
||||
@ -555,8 +531,7 @@ begin
|
||||
A_VMOVAPD,
|
||||
A_VMOVUPS,
|
||||
A_VMOVUPD:
|
||||
if OptPass1_V_MOVAP(p) then
|
||||
continue;
|
||||
Result:=OptPass1_V_MOVAP(p);
|
||||
A_VDIVSD,
|
||||
A_VDIVSS,
|
||||
A_VSUBSD,
|
||||
@ -571,25 +546,19 @@ begin
|
||||
A_VORPS,
|
||||
A_VXORPD,
|
||||
A_VXORPS:
|
||||
if OptPass1VOP(p) then
|
||||
continue;
|
||||
Result:=OptPass1VOP(p);
|
||||
A_MULSD,
|
||||
A_MULSS,
|
||||
A_ADDSD,
|
||||
A_ADDSS:
|
||||
if OptPass1OP(p) then
|
||||
continue;
|
||||
Result:=OptPass1OP(p);
|
||||
A_VMOVSD,
|
||||
A_VMOVSS,
|
||||
A_MOVSD,
|
||||
A_MOVSS:
|
||||
if OptPass1MOVXX(p) then
|
||||
continue;
|
||||
Result:=OptPass1MOVXX(p);
|
||||
A_SETcc:
|
||||
begin
|
||||
if OptPass1SETcc(p) then
|
||||
continue;
|
||||
end
|
||||
Result:=OptPass1SETcc(p);
|
||||
else
|
||||
;
|
||||
end;
|
||||
@ -598,50 +567,30 @@ begin
|
||||
else
|
||||
;
|
||||
end;
|
||||
updateUsedRegs(UsedRegs,p);
|
||||
p:=tai(p.next);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TCPUAsmOptimizer.PeepHoleOptPass2;
|
||||
var
|
||||
p : tai;
|
||||
function TCPUAsmOptimizer.PeepHoleOptPass2Cpu(var p: tai): boolean;
|
||||
begin
|
||||
p := BlockStart;
|
||||
ClearUsedRegs;
|
||||
while (p <> BlockEnd) Do
|
||||
begin
|
||||
UpdateUsedRegs(UsedRegs, tai(p.next));
|
||||
Result:=false;
|
||||
case p.Typ Of
|
||||
Ait_Instruction:
|
||||
begin
|
||||
if InsContainsSegRef(taicpu(p)) then
|
||||
begin
|
||||
p := tai(p.next);
|
||||
continue;
|
||||
end;
|
||||
exit;
|
||||
case taicpu(p).opcode Of
|
||||
A_Jcc:
|
||||
if OptPass2Jcc(p) then
|
||||
continue;
|
||||
Result:=OptPass2Jcc(p);
|
||||
A_Lea:
|
||||
if OptPass2Lea(p) then
|
||||
continue;
|
||||
Result:=OptPass2Lea(p);
|
||||
A_FSTP,A_FISTP:
|
||||
if OptPass1FSTP(p) then
|
||||
continue;
|
||||
Result:=OptPass1FSTP(p);
|
||||
A_IMUL:
|
||||
if OptPass2Imul(p) then
|
||||
continue;
|
||||
Result:=OptPass2Imul(p);
|
||||
A_JMP:
|
||||
if OptPass2Jmp(p) then
|
||||
continue;
|
||||
Result:=OptPass2Jmp(p);
|
||||
A_MOV:
|
||||
begin
|
||||
if OptPass2MOV(p) then
|
||||
continue;
|
||||
end
|
||||
Result:=OptPass2MOV(p);
|
||||
else
|
||||
;
|
||||
end;
|
||||
@ -649,41 +598,28 @@ begin
|
||||
else
|
||||
;
|
||||
end;
|
||||
p := tai(p.next)
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TCPUAsmOptimizer.PostPeepHoleOpts;
|
||||
function TCPUAsmOptimizer.PostPeepHoleOptsCpu(var p : tai) : boolean;
|
||||
var
|
||||
p,hp1: tai;
|
||||
hp1: tai;
|
||||
begin
|
||||
p := BlockStart;
|
||||
ClearUsedRegs;
|
||||
while (p <> BlockEnd) Do
|
||||
begin
|
||||
UpdateUsedRegs(UsedRegs, tai(p.next));
|
||||
Result:=false;
|
||||
case p.Typ Of
|
||||
Ait_Instruction:
|
||||
begin
|
||||
if InsContainsSegRef(taicpu(p)) then
|
||||
begin
|
||||
p := tai(p.next);
|
||||
continue;
|
||||
end;
|
||||
Exit;
|
||||
case taicpu(p).opcode Of
|
||||
A_CALL:
|
||||
if PostPeepHoleOptCall(p) then
|
||||
Continue;
|
||||
Result:=PostPeepHoleOptCall(p);
|
||||
A_LEA:
|
||||
if PostPeepholeOptLea(p) then
|
||||
Continue;
|
||||
Result:=PostPeepholeOptLea(p);
|
||||
A_CMP:
|
||||
if PostPeepholeOptCmp(p) then
|
||||
Continue;
|
||||
Result:=PostPeepholeOptCmp(p);
|
||||
A_MOV:
|
||||
if PostPeepholeOptMov(p) then
|
||||
Continue;
|
||||
Result:=PostPeepholeOptMov(p);
|
||||
A_MOVZX:
|
||||
{ if register vars are on, it's possible there is code like }
|
||||
{ "cmpl $3,%eax; movzbl 8(%ebp),%ebx; je .Lxxx" }
|
||||
@ -734,95 +670,24 @@ begin
|
||||
end;
|
||||
end;
|
||||
A_TEST, A_OR:
|
||||
Result:=PostPeepholeOptTestOr(p);
|
||||
else
|
||||
;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TCpuAsmOptimizer.PostPeepHoleOpts;
|
||||
begin
|
||||
if PostPeepholeOptTestOr(p) then
|
||||
Continue;
|
||||
end;
|
||||
else
|
||||
;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
;
|
||||
end;
|
||||
p := tai(p.next)
|
||||
end;
|
||||
inherited;
|
||||
OptReferences;
|
||||
end;
|
||||
|
||||
|
||||
Procedure TCpuAsmOptimizer.Optimize;
|
||||
Var
|
||||
HP: Tai;
|
||||
pass: longint;
|
||||
slowopt, changed, lastLoop: boolean;
|
||||
Begin
|
||||
slowopt := (cs_opt_level3 in current_settings.optimizerswitches);
|
||||
pass := 0;
|
||||
changed := false;
|
||||
repeat
|
||||
lastLoop :=
|
||||
not(slowopt) or
|
||||
(not changed and (pass > 2)) or
|
||||
{ prevent endless loops }
|
||||
(pass = 4);
|
||||
changed := false;
|
||||
{ Setup labeltable, always necessary }
|
||||
blockstart := tai(asml.first);
|
||||
pass_1;
|
||||
{ Blockend now either contains an ait_marker with Kind = mark_AsmBlockStart, }
|
||||
{ or nil }
|
||||
While Assigned(BlockStart) Do
|
||||
Begin
|
||||
if (cs_opt_peephole in current_settings.optimizerswitches) then
|
||||
begin
|
||||
if (pass = 0) then
|
||||
PrePeepHoleOpts;
|
||||
{ Peephole optimizations }
|
||||
PeepHoleOptPass1;
|
||||
{ Only perform them twice in the first pass }
|
||||
if pass = 0 then
|
||||
PeepHoleOptPass1;
|
||||
end;
|
||||
{ More peephole optimizations }
|
||||
if (cs_opt_peephole in current_settings.optimizerswitches) then
|
||||
begin
|
||||
PeepHoleOptPass2;
|
||||
if lastLoop then
|
||||
PostPeepHoleOpts;
|
||||
end;
|
||||
|
||||
{ Continue where we left off, BlockEnd is either the start of an }
|
||||
{ assembler block or nil }
|
||||
BlockStart := BlockEnd;
|
||||
While Assigned(BlockStart) And
|
||||
(BlockStart.typ = ait_Marker) And
|
||||
(Tai_Marker(BlockStart).Kind = mark_AsmBlockStart) Do
|
||||
Begin
|
||||
{ We stopped at an assembler block, so skip it }
|
||||
Repeat
|
||||
BlockStart := Tai(BlockStart.Next);
|
||||
Until (BlockStart.Typ = Ait_Marker) And
|
||||
(Tai_Marker(Blockstart).Kind = mark_AsmBlockEnd);
|
||||
{ Blockstart now contains a Tai_marker(mark_AsmBlockEnd) }
|
||||
If GetNextInstruction(BlockStart, HP) And
|
||||
((HP.typ <> ait_Marker) Or
|
||||
(Tai_Marker(HP).Kind <> mark_AsmBlockStart)) Then
|
||||
{ There is no assembler block anymore after the current one, so }
|
||||
{ optimize the next block of "normal" instructions }
|
||||
pass_1
|
||||
{ Otherwise, skip the next assembler block }
|
||||
else
|
||||
blockStart := hp;
|
||||
End;
|
||||
End;
|
||||
inc(pass);
|
||||
until lastLoop;
|
||||
dfa.free;
|
||||
|
||||
End;
|
||||
|
||||
|
||||
begin
|
||||
casmoptimizer:=TCpuAsmOptimizer;
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user