mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 13:29:27 +02:00
MOV/CMP optimisation is now in both Pass 1 and Pass 2 to catch more
eventualities
This commit is contained in:
parent
769aeaae03
commit
116c861af6
@ -137,6 +137,7 @@ unit aoptx86;
|
||||
procedure RemoveLastDeallocForFuncRes(p : tai);
|
||||
|
||||
function DoSubAddOpt(var p : tai) : Boolean;
|
||||
function DoMovCmpMemOpt(var p : tai; const hp1: tai; UpdateTmpUsedRegs: Boolean) : Boolean;
|
||||
|
||||
function PrePeepholeOptSxx(var p : tai) : boolean;
|
||||
function PrePeepholeOptIMUL(var p : tai) : boolean;
|
||||
@ -3878,50 +3879,10 @@ unit aoptx86;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if MatchOpType(taicpu(p),top_ref,top_reg) and
|
||||
{ The x86 assemblers have difficulty comparing values against absolute addresses }
|
||||
(taicpu(p).oper[0]^.ref^.refaddr in [addr_no, addr_pic, addr_pic_no_got]) and
|
||||
(taicpu(hp1).oper[0]^.typ <> top_ref) and
|
||||
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^.reg) and
|
||||
(
|
||||
(
|
||||
(taicpu(hp1).opcode = A_TEST)
|
||||
) or (
|
||||
(taicpu(hp1).opcode = A_CMP) and
|
||||
{ A sanity check more than anything }
|
||||
not MatchOperand(taicpu(hp1).oper[0]^, taicpu(p).oper[1]^.reg)
|
||||
)
|
||||
) then
|
||||
if DoMovCmpMemOpt(p, hp1, True) then
|
||||
begin
|
||||
{ change
|
||||
mov mem, %reg
|
||||
cmp/test x, %reg / test %reg,%reg
|
||||
(reg deallocated)
|
||||
|
||||
to
|
||||
|
||||
cmp/test x, mem / cmp 0, mem
|
||||
}
|
||||
TransferUsedRegs(TmpUsedRegs);
|
||||
UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
||||
if not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) then
|
||||
begin
|
||||
{ Convert test %reg,%reg or test $-1,%reg to cmp $0,mem }
|
||||
if (taicpu(hp1).opcode = A_TEST) and
|
||||
(
|
||||
MatchOperand(taicpu(hp1).oper[0]^, taicpu(p).oper[1]^.reg) or
|
||||
MatchOperand(taicpu(hp1).oper[0]^, -1)
|
||||
) then
|
||||
begin
|
||||
taicpu(hp1).opcode := A_CMP;
|
||||
taicpu(hp1).loadconst(0, 0);
|
||||
end;
|
||||
taicpu(hp1).loadref(1, taicpu(p).oper[0]^.ref^);
|
||||
DebugMsg(SPeepholeOptimization + 'MOV/CMP -> CMP (memory check)', p);
|
||||
RemoveCurrentP(p, hp1);
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -5226,6 +5187,59 @@ unit aoptx86;
|
||||
end;
|
||||
|
||||
|
||||
function TX86AsmOptimizer.DoMovCmpMemOpt(var p : tai; const hp1: tai; UpdateTmpUsedRegs: Boolean) : Boolean;
|
||||
begin
|
||||
Result := False;
|
||||
if UpdateTmpUsedRegs then
|
||||
TransferUsedRegs(TmpUsedRegs);
|
||||
|
||||
if MatchOpType(taicpu(p),top_ref,top_reg) and
|
||||
{ The x86 assemblers have difficulty comparing values against absolute addresses }
|
||||
(taicpu(p).oper[0]^.ref^.refaddr <> addr_full) and
|
||||
(taicpu(hp1).oper[0]^.typ <> top_ref) and
|
||||
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^.reg) and
|
||||
(
|
||||
(
|
||||
(taicpu(hp1).opcode = A_TEST)
|
||||
) or (
|
||||
(taicpu(hp1).opcode = A_CMP) and
|
||||
{ A sanity check more than anything }
|
||||
not MatchOperand(taicpu(hp1).oper[0]^, taicpu(p).oper[1]^.reg)
|
||||
)
|
||||
) then
|
||||
begin
|
||||
{ change
|
||||
mov mem, %reg
|
||||
cmp/test x, %reg / test %reg,%reg
|
||||
(reg deallocated)
|
||||
|
||||
to
|
||||
|
||||
cmp/test x, mem / cmp 0, mem
|
||||
}
|
||||
UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
||||
if not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) then
|
||||
begin
|
||||
{ Convert test %reg,%reg or test $-1,%reg to cmp $0,mem }
|
||||
if (taicpu(hp1).opcode = A_TEST) and
|
||||
(
|
||||
MatchOperand(taicpu(hp1).oper[0]^, taicpu(p).oper[1]^.reg) or
|
||||
MatchOperand(taicpu(hp1).oper[0]^, -1)
|
||||
) then
|
||||
begin
|
||||
taicpu(hp1).opcode := A_CMP;
|
||||
taicpu(hp1).loadconst(0, 0);
|
||||
end;
|
||||
taicpu(hp1).loadref(1, taicpu(p).oper[0]^.ref^);
|
||||
DebugMsg(SPeepholeOptimization + 'MOV/CMP -> CMP (memory check)', p);
|
||||
RemoveCurrentP(p, hp1);
|
||||
Result := True;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TX86AsmOptimizer.OptPass1Sub(var p : tai) : boolean;
|
||||
var
|
||||
hp1, hp2: tai;
|
||||
@ -6113,6 +6127,7 @@ unit aoptx86;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
{ Search for:
|
||||
cmp ###,###
|
||||
j(c1) @lbl1
|
||||
@ -6120,16 +6135,16 @@ unit aoptx86;
|
||||
|
||||
Remove second cmp
|
||||
}
|
||||
|
||||
if GetNextInstruction(p_jump, hp2) and
|
||||
(
|
||||
(
|
||||
MatchInstruction(hp2, A_CMP, []) and
|
||||
MatchInstruction(hp2, A_CMP, [taicpu(p).opsize]) and
|
||||
(
|
||||
(
|
||||
MatchOpType(taicpu(p), top_const, top_reg) and
|
||||
MatchOpType(taicpu(hp2), top_const, top_reg) and
|
||||
(taicpu(hp2).oper[0]^.val = taicpu(p).oper[0]^.val) and
|
||||
SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp2).oper[1]^.reg)
|
||||
Reg1WriteOverwritesReg2Entirely(taicpu(hp2).oper[1]^.reg, taicpu(p).oper[1]^.reg)
|
||||
) or (
|
||||
MatchOperand(taicpu(hp2).oper[0]^, taicpu(p).oper[0]^) and
|
||||
MatchOperand(taicpu(hp2).oper[1]^, taicpu(p).oper[1]^)
|
||||
@ -6142,7 +6157,7 @@ unit aoptx86;
|
||||
MatchInstruction(hp2, A_TEST, []) and
|
||||
MatchOpType(taicpu(hp2), top_reg, top_reg) and
|
||||
(taicpu(hp2).oper[0]^.reg = taicpu(hp2).oper[1]^.reg) and
|
||||
SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp2).oper[1]^.reg)
|
||||
Reg1WriteOverwritesReg2Entirely(taicpu(hp2).oper[1]^.reg, taicpu(p).oper[1]^.reg)
|
||||
)
|
||||
) then
|
||||
begin
|
||||
@ -6175,6 +6190,10 @@ unit aoptx86;
|
||||
a conditional branch.
|
||||
}
|
||||
if not (cs_opt_size in current_settings.optimizerswitches) and
|
||||
(
|
||||
(hp1 = p_jump) or
|
||||
GetNextInstruction(p, hp1)
|
||||
) and
|
||||
MatchInstruction(hp1, A_Jcc, []) and
|
||||
IsJumpToLabel(taicpu(hp1)) and
|
||||
(taicpu(hp1).condition in [C_E, C_Z]) and
|
||||
@ -6182,7 +6201,7 @@ unit aoptx86;
|
||||
MatchInstruction(hp2, A_CMP, A_TEST, [taicpu(p).opsize]) and
|
||||
MatchOperand(taicpu(p).oper[1]^, taicpu(hp2).oper[1]^) and
|
||||
{ The first operand of CMP instructions can only be a register or
|
||||
operand anyway, so no need to check }
|
||||
immediate anyway, so no need to check }
|
||||
GetNextInstruction(hp2, p_label) and
|
||||
(p_label.typ = ait_label) and
|
||||
(tai_label(p_label).labsym.getrefs = 1) and
|
||||
@ -7516,7 +7535,13 @@ unit aoptx86;
|
||||
if not GetNextInstruction(p, hp1) then
|
||||
Exit;
|
||||
|
||||
if MatchInstruction(hp1, A_JMP, [S_NO]) then
|
||||
if MatchInstruction(hp1, A_CMP, A_TEST, [taicpu(p).opsize])
|
||||
and DoMovCmpMemOpt(p, hp1, True) then
|
||||
begin
|
||||
Result := True;
|
||||
Exit;
|
||||
end
|
||||
else if MatchInstruction(hp1, A_JMP, [S_NO]) then
|
||||
begin
|
||||
{ Sometimes the MOVs that OptPass2JMP produces can be improved
|
||||
further, but we can't just put this jump optimisation in pass 1
|
||||
|
Loading…
Reference in New Issue
Block a user