* patch by J. Gareth Moreton: refactor OptPass2Jcc, resolves #38343

git-svn-id: trunk@48162 -
This commit is contained in:
florian 2021-01-15 21:24:44 +00:00
parent 50a13b4df4
commit 707bce74d7

View File

@ -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;