mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 00:09:23 +02:00
+ SETcc/Mov -> SETcc optimization
git-svn-id: trunk@48808 -
This commit is contained in:
parent
857cbddf04
commit
c6443809ba
@ -3991,76 +3991,92 @@ unit aoptx86;
|
|||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
|
|
||||||
if MatchOpType(taicpu(p),top_reg) and
|
if MatchOpType(taicpu(p),top_reg) and GetNextInstruction(p, hp1) then
|
||||||
GetNextInstruction(p, hp1) and
|
|
||||||
((MatchInstruction(hp1, A_TEST, [S_B]) and
|
|
||||||
MatchOpType(taicpu(hp1),top_reg,top_reg) and
|
|
||||||
(taicpu(hp1).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) or
|
|
||||||
(MatchInstruction(hp1, A_CMP, [S_B]) and
|
|
||||||
MatchOpType(taicpu(hp1),top_const,top_reg) and
|
|
||||||
(taicpu(hp1).oper[0]^.val=0))
|
|
||||||
) and
|
|
||||||
(taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) and
|
|
||||||
GetNextInstruction(hp1, hp2) and
|
|
||||||
MatchInstruction(hp2, A_Jcc, []) then
|
|
||||||
{ Change from: To:
|
|
||||||
|
|
||||||
set(C) %reg j(~C) label
|
|
||||||
test %reg,%reg/cmp $0,%reg
|
|
||||||
je label
|
|
||||||
|
|
||||||
|
|
||||||
set(C) %reg j(C) label
|
|
||||||
test %reg,%reg/cmp $0,%reg
|
|
||||||
jne label
|
|
||||||
}
|
|
||||||
begin
|
begin
|
||||||
next := tai(p.Next);
|
if ((MatchInstruction(hp1, A_TEST, [S_B]) and
|
||||||
|
MatchOpType(taicpu(hp1),top_reg,top_reg) and
|
||||||
|
(taicpu(hp1).oper[0]^.reg = taicpu(hp1).oper[1]^.reg)) or
|
||||||
|
(MatchInstruction(hp1, A_CMP, [S_B]) and
|
||||||
|
MatchOpType(taicpu(hp1),top_const,top_reg) and
|
||||||
|
(taicpu(hp1).oper[0]^.val=0))
|
||||||
|
) and
|
||||||
|
(taicpu(p).oper[0]^.reg = taicpu(hp1).oper[1]^.reg) and
|
||||||
|
GetNextInstruction(hp1, hp2) and
|
||||||
|
MatchInstruction(hp2, A_Jcc, []) then
|
||||||
|
{ Change from: To:
|
||||||
|
|
||||||
TransferUsedRegs(TmpUsedRegs);
|
set(C) %reg j(~C) label
|
||||||
UpdateUsedRegs(TmpUsedRegs, next);
|
test %reg,%reg/cmp $0,%reg
|
||||||
UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
|
je label
|
||||||
|
|
||||||
JumpC := taicpu(hp2).condition;
|
|
||||||
Unconditional := False;
|
|
||||||
|
|
||||||
if conditions_equal(JumpC, C_E) then
|
set(C) %reg j(C) label
|
||||||
SetC := inverse_cond(taicpu(p).condition)
|
test %reg,%reg/cmp $0,%reg
|
||||||
else if conditions_equal(JumpC, C_NE) then
|
jne label
|
||||||
SetC := taicpu(p).condition
|
}
|
||||||
else
|
|
||||||
{ We've got something weird here (and inefficent) }
|
|
||||||
begin
|
begin
|
||||||
DebugMsg('DEBUG: Inefficient jump - check code generation', p);
|
next := tai(p.Next);
|
||||||
SetC := C_NONE;
|
|
||||||
|
|
||||||
{ JAE/JNB will always branch (use 'condition_in', since C_AE <> C_NB normally) }
|
TransferUsedRegs(TmpUsedRegs);
|
||||||
if condition_in(C_AE, JumpC) then
|
UpdateUsedRegs(TmpUsedRegs, next);
|
||||||
Unconditional := True
|
UpdateUsedRegs(TmpUsedRegs, tai(hp1.next));
|
||||||
|
|
||||||
|
JumpC := taicpu(hp2).condition;
|
||||||
|
Unconditional := False;
|
||||||
|
|
||||||
|
if conditions_equal(JumpC, C_E) then
|
||||||
|
SetC := inverse_cond(taicpu(p).condition)
|
||||||
|
else if conditions_equal(JumpC, C_NE) then
|
||||||
|
SetC := taicpu(p).condition
|
||||||
else
|
else
|
||||||
{ Not sure what to do with this jump - drop out }
|
{ We've got something weird here (and inefficent) }
|
||||||
Exit;
|
begin
|
||||||
end;
|
DebugMsg('DEBUG: Inefficient jump - check code generation', p);
|
||||||
|
SetC := C_NONE;
|
||||||
|
|
||||||
RemoveInstruction(hp1);
|
{ JAE/JNB will always branch (use 'condition_in', since C_AE <> C_NB normally) }
|
||||||
|
if condition_in(C_AE, JumpC) then
|
||||||
|
Unconditional := True
|
||||||
|
else
|
||||||
|
{ Not sure what to do with this jump - drop out }
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
if Unconditional then
|
RemoveInstruction(hp1);
|
||||||
MakeUnconditional(taicpu(hp2))
|
|
||||||
else
|
if Unconditional then
|
||||||
|
MakeUnconditional(taicpu(hp2))
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if SetC = C_NONE then
|
||||||
|
InternalError(2018061402);
|
||||||
|
|
||||||
|
taicpu(hp2).SetCondition(SetC);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not RegUsedAfterInstruction(taicpu(p).oper[0]^.reg, hp2, TmpUsedRegs) then
|
||||||
|
begin
|
||||||
|
RemoveCurrentp(p, hp2);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
DebugMsg(SPeepholeOptimization + 'SETcc/TESTCmp/Jcc -> Jcc',p);
|
||||||
|
end
|
||||||
|
else if MatchInstruction(hp1, A_MOV, [S_B]) and
|
||||||
|
MatchOpType(taicpu(hp1),top_reg,top_reg) and
|
||||||
|
MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[0]^) then
|
||||||
begin
|
begin
|
||||||
if SetC = C_NONE then
|
TransferUsedRegs(TmpUsedRegs);
|
||||||
InternalError(2018061402);
|
UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
||||||
|
if not RegUsedAfterInstruction(taicpu(p).oper[0]^.reg, hp1, TmpUsedRegs) then
|
||||||
taicpu(hp2).SetCondition(SetC);
|
begin
|
||||||
|
AllocRegBetween(taicpu(p).oper[0]^.reg,p,hp1,UsedRegs);
|
||||||
|
taicpu(p).oper[0]^.reg:=taicpu(hp1).oper[1]^.reg;
|
||||||
|
RemoveInstruction(hp1);
|
||||||
|
DebugMsg(SPeepholeOptimization + 'SETcc/Mov -> SETcc',p);
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not RegUsedAfterInstruction(taicpu(p).oper[0]^.reg, hp2, TmpUsedRegs) then
|
|
||||||
begin
|
|
||||||
RemoveCurrentp(p, hp2);
|
|
||||||
Result := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
DebugMsg(SPeepholeOptimization + 'SETcc/TESTCmp/Jcc -> Jcc',p);
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user