mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 09:59:17 +02:00
* patch by J. Gareth Moreton: AND/CMP optimisation, resolves #39287
This commit is contained in:
parent
25e937b0c9
commit
306fae299e
@ -8618,8 +8618,9 @@ unit aoptx86;
|
|||||||
begin
|
begin
|
||||||
if (taicpu(p).oper[0]^.typ = top_const) then
|
if (taicpu(p).oper[0]^.typ = top_const) then
|
||||||
begin
|
begin
|
||||||
if (taicpu(hp1).opcode = A_AND) and
|
case taicpu(hp1).opcode of
|
||||||
MatchOpType(taicpu(hp1),top_const,top_reg) and
|
A_AND:
|
||||||
|
if MatchOpType(taicpu(hp1),top_const,top_reg) and
|
||||||
(getsupreg(taicpu(p).oper[1]^.reg) = getsupreg(taicpu(hp1).oper[1]^.reg)) and
|
(getsupreg(taicpu(p).oper[1]^.reg) = getsupreg(taicpu(hp1).oper[1]^.reg)) and
|
||||||
{ the second register must contain the first one, so compare their subreg types }
|
{ the second register must contain the first one, so compare their subreg types }
|
||||||
(getsubreg(taicpu(p).oper[1]^.reg)<=getsubreg(taicpu(hp1).oper[1]^.reg)) and
|
(getsubreg(taicpu(p).oper[1]^.reg)<=getsubreg(taicpu(hp1).oper[1]^.reg)) and
|
||||||
@ -8636,19 +8637,56 @@ unit aoptx86;
|
|||||||
RemoveCurrentP(p, hp1);
|
RemoveCurrentP(p, hp1);
|
||||||
Result:=true;
|
Result:=true;
|
||||||
exit;
|
exit;
|
||||||
end
|
end;
|
||||||
else if (taicpu(hp1).opcode = A_MOVZX) and
|
|
||||||
MatchOpType(taicpu(hp1),top_reg,top_reg) and
|
A_CMP:
|
||||||
|
if (PopCnt(DWord(taicpu(p).oper[0]^.val)) = 1) and { Only 1 bit set }
|
||||||
|
MatchOperand(taicpu(hp1).oper[0]^, taicpu(p).oper[0]^.val) and
|
||||||
|
MatchOperand(taicpu(hp1).oper[1]^, taicpu(p).oper[1]^.reg) and
|
||||||
|
{ Just check that the condition on the next instruction is compatible }
|
||||||
|
GetNextInstruction(hp1, hp2) and
|
||||||
|
(hp2.typ = ait_instruction) and
|
||||||
|
(taicpu(hp2).condition in [C_Z, C_E, C_NZ, C_NE])
|
||||||
|
then
|
||||||
|
{ change
|
||||||
|
and 2^n, reg
|
||||||
|
cmp 2^n, reg
|
||||||
|
j(c) / set(c) / cmov(c) (c is equal or not equal)
|
||||||
|
to
|
||||||
|
and 2^n, reg
|
||||||
|
test reg, reg
|
||||||
|
j(~c) / set(~c) / cmov(~c)
|
||||||
|
}
|
||||||
|
begin
|
||||||
|
{ Keep TEST instruction in, rather than remove it, because
|
||||||
|
it may trigger other optimisations such as MovAndTest2Test }
|
||||||
|
taicpu(hp1).loadreg(0, taicpu(hp1).oper[1]^.reg);
|
||||||
|
taicpu(hp1).opcode := A_TEST;
|
||||||
|
DebugMsg(SPeepholeOptimization + 'AND/CMP/J(c) -> AND/J(~c) with power of 2 constant', p);
|
||||||
|
taicpu(hp2).condition := inverse_cond(taicpu(hp2).condition);
|
||||||
|
Result := True;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
A_MOVZX:
|
||||||
|
if MatchOpType(taicpu(hp1),top_reg,top_reg) and
|
||||||
SuperRegistersEqual(taicpu(p).oper[1]^.reg,taicpu(hp1).oper[1]^.reg) and
|
SuperRegistersEqual(taicpu(p).oper[1]^.reg,taicpu(hp1).oper[1]^.reg) and
|
||||||
(getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) and
|
(getsupreg(taicpu(hp1).oper[0]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) and
|
||||||
(((taicpu(p).opsize=S_W) and
|
(
|
||||||
(taicpu(hp1).opsize=S_BW)) or
|
(
|
||||||
((taicpu(p).opsize=S_L) and
|
(taicpu(p).opsize=S_W) and
|
||||||
(taicpu(hp1).opsize in [S_WL,S_BL{$ifdef x86_64},S_BQ,S_WQ{$endif x86_64}]))
|
(taicpu(hp1).opsize=S_BW)
|
||||||
|
) or
|
||||||
|
(
|
||||||
|
(taicpu(p).opsize=S_L) and
|
||||||
|
(taicpu(hp1).opsize in [S_WL,S_BL{$ifdef x86_64},S_BQ,S_WQ{$endif x86_64}])
|
||||||
|
)
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
or
|
or
|
||||||
((taicpu(p).opsize=S_Q) and
|
(
|
||||||
(taicpu(hp1).opsize in [S_BQ,S_WQ,S_BL,S_WL]))
|
(taicpu(p).opsize=S_Q) and
|
||||||
|
(taicpu(hp1).opsize in [S_BQ,S_WQ,S_BL,S_WL])
|
||||||
|
)
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
) then
|
) then
|
||||||
begin
|
begin
|
||||||
@ -8673,9 +8711,10 @@ unit aoptx86;
|
|||||||
{ See if there are other optimisations possible }
|
{ See if there are other optimisations possible }
|
||||||
Continue;
|
Continue;
|
||||||
end;
|
end;
|
||||||
end
|
end;
|
||||||
else if (taicpu(hp1).opcode = A_SHL) and
|
|
||||||
MatchOpType(taicpu(hp1),top_const,top_reg) and
|
A_SHL:
|
||||||
|
if MatchOpType(taicpu(hp1),top_const,top_reg) and
|
||||||
(getsupreg(taicpu(p).oper[1]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) then
|
(getsupreg(taicpu(p).oper[1]^.reg)=getsupreg(taicpu(hp1).oper[1]^.reg)) then
|
||||||
begin
|
begin
|
||||||
{$ifopt R+}
|
{$ifopt R+}
|
||||||
@ -8698,9 +8737,10 @@ unit aoptx86;
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end
|
end;
|
||||||
else if (taicpu(hp1).opcode = A_SHR) and
|
|
||||||
MatchOpType(taicpu(hp1),top_const,top_reg) and
|
A_SHR:
|
||||||
|
if MatchOpType(taicpu(hp1),top_const,top_reg) and
|
||||||
(taicpu(p).oper[1]^.reg = taicpu(hp1).oper[1]^.reg) and
|
(taicpu(p).oper[1]^.reg = taicpu(hp1).oper[1]^.reg) and
|
||||||
(taicpu(hp1).oper[0]^.val <= 63) then
|
(taicpu(hp1).oper[0]^.val <= 63) then
|
||||||
begin
|
begin
|
||||||
@ -8719,9 +8759,10 @@ unit aoptx86;
|
|||||||
Result := True;
|
Result := True;
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end
|
end;
|
||||||
else if ((taicpu(hp1).opcode = A_MOVSX){$ifdef x86_64} or (taicpu(hp1).opcode = A_MOVSXD){$endif x86_64}) and
|
|
||||||
(taicpu(hp1).oper[0]^.typ = top_reg) and
|
A_MOVSX{$ifdef x86_64}, A_MOVSXD{$endif x86_64}:
|
||||||
|
if (taicpu(hp1).oper[0]^.typ = top_reg) and
|
||||||
SuperRegistersEqual(taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg) then
|
SuperRegistersEqual(taicpu(hp1).oper[0]^.reg, taicpu(hp1).oper[1]^.reg) then
|
||||||
begin
|
begin
|
||||||
if SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp1).oper[1]^.reg) and
|
if SuperRegistersEqual(taicpu(p).oper[1]^.reg, taicpu(hp1).oper[1]^.reg) and
|
||||||
@ -8775,6 +8816,9 @@ unit aoptx86;
|
|||||||
Continue;
|
Continue;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if (taicpu(hp1).is_jmp) and
|
if (taicpu(hp1).is_jmp) and
|
||||||
|
Loading…
Reference in New Issue
Block a user