mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 05:09:49 +02:00
* patch by J. Gareth Moreton: refactor OptPass2Jcc, resolves #38343
git-svn-id: trunk@48162 -
This commit is contained in:
parent
50a13b4df4
commit
707bce74d7
@ -5693,21 +5693,28 @@ unit aoptx86;
|
|||||||
symbol: TAsmSymbol;
|
symbol: TAsmSymbol;
|
||||||
reg: tsuperregister;
|
reg: tsuperregister;
|
||||||
regavailable: Boolean;
|
regavailable: Boolean;
|
||||||
tmpreg: TRegister;
|
increg, tmpreg: TRegister;
|
||||||
begin
|
begin
|
||||||
result:=false;
|
result:=false;
|
||||||
symbol:=nil;
|
if GetNextInstruction(p,hp1) and (hp1.typ=ait_instruction) then
|
||||||
if GetNextInstruction(p,hp1) then
|
|
||||||
begin
|
begin
|
||||||
symbol := TAsmLabel(taicpu(p).oper[0]^.ref^.symbol);
|
symbol := TAsmLabel(taicpu(p).oper[0]^.ref^.symbol);
|
||||||
|
|
||||||
if (hp1.typ=ait_instruction) and
|
if GetNextInstruction(hp1,hp2) and
|
||||||
GetNextInstruction(hp1,hp2) and
|
(
|
||||||
((hp2.typ=ait_label) or
|
(hp2.typ=ait_label) or
|
||||||
{ trick to skip align }
|
{ trick to skip align }
|
||||||
((hp2.typ=ait_align) and GetNextInstruction(hp2,hp2) and (hp2.typ=ait_label))
|
((hp2.typ=ait_align) and GetNextInstruction(hp2,hp2) and (hp2.typ=ait_label))
|
||||||
) and
|
) and
|
||||||
(Tasmlabel(symbol) = Tai_label(hp2).labsym) then
|
(Tasmlabel(symbol) = Tai_label(hp2).labsym) and
|
||||||
|
(
|
||||||
|
(
|
||||||
|
((Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB)) and
|
||||||
|
MatchOptype(Taicpu(hp1),top_const,top_reg) and
|
||||||
|
(Taicpu(hp1).oper[0]^.val=1)
|
||||||
|
) or
|
||||||
|
((Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC))
|
||||||
|
) then
|
||||||
{ jb @@1 cmc
|
{ jb @@1 cmc
|
||||||
inc/dec operand --> adc/sbb operand,0
|
inc/dec operand --> adc/sbb operand,0
|
||||||
@@1:
|
@@1:
|
||||||
@ -5718,23 +5725,19 @@ unit aoptx86;
|
|||||||
inc/dec operand --> adc/sbb operand,0
|
inc/dec operand --> adc/sbb operand,0
|
||||||
@@1: }
|
@@1: }
|
||||||
begin
|
begin
|
||||||
carryadd_opcode:=A_NONE;
|
|
||||||
if Taicpu(p).condition in [C_NAE,C_B,C_C] then
|
if Taicpu(p).condition in [C_NAE,C_B,C_C] then
|
||||||
begin
|
begin
|
||||||
if (Taicpu(hp1).opcode=A_INC) or
|
case taicpu(hp1).opcode of
|
||||||
((Taicpu(hp1).opcode=A_ADD) and
|
A_INC,
|
||||||
MatchOptype(Taicpu(hp1),top_const,top_reg) and
|
A_ADD:
|
||||||
(Taicpu(hp1).oper[0]^.val=1)
|
|
||||||
) then
|
|
||||||
carryadd_opcode:=A_ADC;
|
carryadd_opcode:=A_ADC;
|
||||||
if (Taicpu(hp1).opcode=A_DEC) or
|
A_DEC,
|
||||||
((Taicpu(hp1).opcode=A_SUB) and
|
A_SUB:
|
||||||
MatchOptype(Taicpu(hp1),top_const,top_reg) and
|
|
||||||
(Taicpu(hp1).oper[0]^.val=1)
|
|
||||||
) then
|
|
||||||
carryadd_opcode:=A_SBB;
|
carryadd_opcode:=A_SBB;
|
||||||
if carryadd_opcode<>A_NONE then
|
else
|
||||||
begin
|
InternalError(2021011001);
|
||||||
|
end;
|
||||||
|
|
||||||
Taicpu(p).clearop(0);
|
Taicpu(p).clearop(0);
|
||||||
Taicpu(p).ops:=0;
|
Taicpu(p).ops:=0;
|
||||||
Taicpu(p).is_jmp:=false;
|
Taicpu(p).is_jmp:=false;
|
||||||
@ -5750,24 +5753,20 @@ unit aoptx86;
|
|||||||
Taicpu(hp1).opcode:=carryadd_opcode;
|
Taicpu(hp1).opcode:=carryadd_opcode;
|
||||||
result:=true;
|
result:=true;
|
||||||
exit;
|
exit;
|
||||||
end;
|
|
||||||
end
|
end
|
||||||
else if Taicpu(p).condition in [C_AE,C_NB,C_NC] then
|
else if Taicpu(p).condition in [C_AE,C_NB,C_NC] then
|
||||||
begin
|
begin
|
||||||
if (Taicpu(hp1).opcode=A_INC) or
|
case taicpu(hp1).opcode of
|
||||||
((Taicpu(hp1).opcode=A_ADD) and
|
A_INC,
|
||||||
MatchOptype(Taicpu(hp1),top_const,top_reg) and
|
A_ADD:
|
||||||
(Taicpu(hp1).oper[0]^.val=1)
|
|
||||||
) then
|
|
||||||
carryadd_opcode:=A_ADC;
|
carryadd_opcode:=A_ADC;
|
||||||
if (Taicpu(hp1).opcode=A_DEC) or
|
A_DEC,
|
||||||
((Taicpu(hp1).opcode=A_SUB) and
|
A_SUB:
|
||||||
MatchOptype(Taicpu(hp1),top_const,top_reg) and
|
|
||||||
(Taicpu(hp1).oper[0]^.val=1)
|
|
||||||
) then
|
|
||||||
carryadd_opcode:=A_SBB;
|
carryadd_opcode:=A_SBB;
|
||||||
if carryadd_opcode<>A_NONE then
|
else
|
||||||
begin
|
InternalError(2021011002);
|
||||||
|
end;
|
||||||
|
|
||||||
Taicpu(hp1).ops:=2;
|
Taicpu(hp1).ops:=2;
|
||||||
DebugMsg(SPeepholeOptimization+'JccAdd/Inc/Dec2Adc/Sbb',p);
|
DebugMsg(SPeepholeOptimization+'JccAdd/Inc/Dec2Adc/Sbb',p);
|
||||||
if (Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB) then
|
if (Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB) then
|
||||||
@ -5779,7 +5778,6 @@ unit aoptx86;
|
|||||||
RemoveCurrentP(p, hp1);
|
RemoveCurrentP(p, hp1);
|
||||||
result:=true;
|
result:=true;
|
||||||
exit;
|
exit;
|
||||||
end;
|
|
||||||
end
|
end
|
||||||
{
|
{
|
||||||
jcc @@1 setcc tmpreg
|
jcc @@1 setcc tmpreg
|
||||||
@ -5789,67 +5787,79 @@ unit aoptx86;
|
|||||||
While this increases code size slightly, it makes the code much faster if the
|
While this increases code size slightly, it makes the code much faster if the
|
||||||
jump is unpredictable
|
jump is unpredictable
|
||||||
}
|
}
|
||||||
else if not(cs_opt_size in current_settings.optimizerswitches) and
|
else if not(cs_opt_size in current_settings.optimizerswitches) then
|
||||||
((((Taicpu(hp1).opcode=A_ADD) or (Taicpu(hp1).opcode=A_SUB)) and
|
|
||||||
(Taicpu(hp1).oper[0]^.typ=top_const) and
|
|
||||||
(Taicpu(hp1).oper[1]^.typ=top_reg) and
|
|
||||||
(Taicpu(hp1).oper[0]^.val=1)) or
|
|
||||||
((Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC))
|
|
||||||
) then
|
|
||||||
begin
|
begin
|
||||||
{ search for an available register which is volatile }
|
{ search for an available register which is volatile }
|
||||||
regavailable:=false;
|
|
||||||
for reg in tcpuregisterset do
|
for reg in tcpuregisterset do
|
||||||
begin
|
begin
|
||||||
tmpreg:=newreg(R_INTREGISTER,reg,R_SUBL);
|
if
|
||||||
if (reg in paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption)) and
|
{$if defined(i386) or defined(i8086)}
|
||||||
not(reg in UsedRegs[R_INTREGISTER].GetUsedRegs) and
|
{ Only use registers whose lowest 8-bits can Be accessed }
|
||||||
not(RegInInstruction(tmpreg,hp1))
|
(reg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX]) and
|
||||||
{$ifdef i386}
|
{$endif i386 or i8086}
|
||||||
{ use only registers which can be accessed byte wise }
|
(reg in paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption)) and
|
||||||
and (reg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX])
|
not(reg in UsedRegs[R_INTREGISTER].GetUsedRegs)
|
||||||
{$endif i386}
|
{ We don't need to check if tmpreg is in hp1 or not, because
|
||||||
|
it will be marked as in use at p (if not, this is
|
||||||
|
indictive of a compiler bug). }
|
||||||
then
|
then
|
||||||
begin
|
|
||||||
regavailable:=true;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if regavailable then
|
|
||||||
begin
|
begin
|
||||||
TAsmLabel(symbol).decrefs;
|
TAsmLabel(symbol).decrefs;
|
||||||
|
increg := newreg(R_INTREGISTER,reg,R_SUBL);
|
||||||
Taicpu(p).clearop(0);
|
Taicpu(p).clearop(0);
|
||||||
Taicpu(p).ops:=1;
|
Taicpu(p).ops:=1;
|
||||||
Taicpu(p).is_jmp:=false;
|
Taicpu(p).is_jmp:=false;
|
||||||
Taicpu(p).opcode:=A_SETcc;
|
Taicpu(p).opcode:=A_SETcc;
|
||||||
DebugMsg(SPeepholeOptimization+'JccAdd2SetccAdd',p);
|
DebugMsg(SPeepholeOptimization+'JccAdd2SetccAdd',p);
|
||||||
Taicpu(p).condition:=inverse_cond(Taicpu(p).condition);
|
Taicpu(p).condition:=inverse_cond(Taicpu(p).condition);
|
||||||
Taicpu(p).loadreg(0,tmpreg);
|
Taicpu(p).loadreg(0,increg);
|
||||||
|
|
||||||
if getsubreg(Taicpu(hp1).oper[1]^.reg)<>R_SUBL then
|
if getsubreg(Taicpu(hp1).oper[1]^.reg)<>R_SUBL then
|
||||||
begin
|
begin
|
||||||
case getsubreg(Taicpu(hp1).oper[1]^.reg) of
|
case getsubreg(Taicpu(hp1).oper[1]^.reg) of
|
||||||
R_SUBW:
|
R_SUBW:
|
||||||
hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BW,tmpreg,
|
begin
|
||||||
newreg(R_INTREGISTER,reg,R_SUBW));
|
tmpreg := newreg(R_INTREGISTER,reg,R_SUBW);
|
||||||
R_SUBD,
|
hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BW,increg,tmpreg);
|
||||||
|
end;
|
||||||
|
R_SUBD:
|
||||||
|
begin
|
||||||
|
tmpreg := newreg(R_INTREGISTER,reg,R_SUBD);
|
||||||
|
hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,increg,tmpreg);
|
||||||
|
end;
|
||||||
|
{$ifdef x86_64}
|
||||||
R_SUBQ:
|
R_SUBQ:
|
||||||
hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,tmpreg,
|
begin
|
||||||
|
{ MOVZX doesn't have a 64-bit variant, because
|
||||||
|
the 32-bit version implicitly zeroes the
|
||||||
|
upper 32-bits of the destination register }
|
||||||
|
hp2:=Taicpu.op_reg_reg(A_MOVZX,S_BL,increg,
|
||||||
newreg(R_INTREGISTER,reg,R_SUBD));
|
newreg(R_INTREGISTER,reg,R_SUBD));
|
||||||
|
tmpreg := newreg(R_INTREGISTER,reg,R_SUBQ);
|
||||||
|
end;
|
||||||
|
{$endif x86_64}
|
||||||
else
|
else
|
||||||
Internalerror(2020030601);
|
Internalerror(2020030601);
|
||||||
end;
|
end;
|
||||||
taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo;
|
taicpu(hp2).fileinfo:=taicpu(hp1).fileinfo;
|
||||||
asml.InsertAfter(hp2,p);
|
asml.InsertAfter(hp2,p);
|
||||||
end;
|
end
|
||||||
|
else
|
||||||
|
tmpreg := increg;
|
||||||
|
|
||||||
if (Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC) then
|
if (Taicpu(hp1).opcode=A_INC) or (Taicpu(hp1).opcode=A_DEC) then
|
||||||
begin
|
begin
|
||||||
Taicpu(hp1).ops:=2;
|
Taicpu(hp1).ops:=2;
|
||||||
Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^)
|
Taicpu(hp1).loadoper(1,Taicpu(hp1).oper[0]^)
|
||||||
end;
|
end;
|
||||||
Taicpu(hp1).loadreg(0,newreg(R_INTREGISTER,reg,getsubreg(Taicpu(hp1).oper[1]^.reg)));
|
Taicpu(hp1).loadreg(0,tmpreg);
|
||||||
AllocRegBetween(newreg(R_INTREGISTER,reg,getsubreg(Taicpu(hp1).oper[1]^.reg)),p,hp1,UsedRegs);
|
AllocRegBetween(tmpreg,p,hp1,UsedRegs);
|
||||||
|
|
||||||
|
Result := True;
|
||||||
|
|
||||||
|
{ p is no longer a Jcc instruction, so exit }
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -5891,10 +5901,9 @@ unit aoptx86;
|
|||||||
internalerror(2016041302);
|
internalerror(2016041302);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
end;
|
|
||||||
{$ifndef i8086}
|
{$ifndef i8086}
|
||||||
if CPUX86_HAS_CMOV in cpu_capabilities[current_settings.cputype] then
|
end
|
||||||
|
else if CPUX86_HAS_CMOV in cpu_capabilities[current_settings.cputype] then
|
||||||
begin
|
begin
|
||||||
{ check for
|
{ check for
|
||||||
jCC xxx
|
jCC xxx
|
||||||
@ -5902,7 +5911,6 @@ unit aoptx86;
|
|||||||
xxx:
|
xxx:
|
||||||
}
|
}
|
||||||
l:=0;
|
l:=0;
|
||||||
GetNextInstruction(p, hp1);
|
|
||||||
while assigned(hp1) and
|
while assigned(hp1) and
|
||||||
CanBeCMOV(hp1) and
|
CanBeCMOV(hp1) and
|
||||||
{ stop on labels }
|
{ stop on labels }
|
||||||
@ -6093,9 +6101,10 @@ unit aoptx86;
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
|
||||||
{$endif i8086}
|
{$endif i8086}
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TX86AsmOptimizer.OptPass1Movx(var p : tai) : boolean;
|
function TX86AsmOptimizer.OptPass1Movx(var p : tai) : boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user