* i386: Fixed issue where the peephole optimizer entered an infinite loop when building for CPUs older than Pentium II

This commit is contained in:
J. Gareth "Curious Kit" Moreton 2024-04-24 06:13:58 +01:00 committed by FPK
parent 0655b342d4
commit 17b7782929

View File

@ -14751,152 +14751,159 @@ unit aoptx86;
{ changes some movzx constructs to faster synonyms (all examples { changes some movzx constructs to faster synonyms (all examples
are given with eax/ax, but are also valid for other registers)} are given with eax/ax, but are also valid for other registers)}
if MatchOpType(taicpu(p),top_reg,top_reg) then if MatchOpType(taicpu(p),top_reg,top_reg) then
begin begin
case taicpu(p).opsize of case taicpu(p).opsize of
{ Technically, movzbw %al,%ax cannot be encoded in 32/64-bit mode { Technically, movzbw %al,%ax cannot be encoded in 32/64-bit mode
(the machine code is equivalent to movzbl %al,%eax), but the (the machine code is equivalent to movzbl %al,%eax), but the
code generator still generates that assembler instruction and code generator still generates that assembler instruction and
it is silently converted. This should probably be checked. it is silently converted. This should probably be checked.
[Kit] } [Kit] }
S_BW: S_BW:
begin
if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and
(
not IsMOVZXAcceptable
{ and $0xff,%ax has a smaller encoding but risks a partial write penalty }
or (
(cs_opt_size in current_settings.optimizerswitches) and
(taicpu(p).oper[1]^.reg = NR_AX)
)
) then
{Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
begin
DebugMsg(SPeepholeOptimization + 'var7',p);
taicpu(p).opcode := A_AND;
taicpu(p).changeopsize(S_W);
taicpu(p).loadConst(0,$ff);
Result := True;
end
else if not IsMOVZXAcceptable and
GetNextInstruction(p, hp1) and
(tai(hp1).typ = ait_instruction) and
(taicpu(hp1).opcode = A_AND) and
MatchOpType(taicpu(hp1),top_const,top_reg) and
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
{ Change "movzbw %reg1, %reg2; andw $const, %reg2"
to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"}
begin
DebugMsg(SPeepholeOptimization + 'var8',p);
taicpu(p).opcode := A_MOV;
taicpu(p).changeopsize(S_W);
setsubreg(taicpu(p).oper[0]^.reg,R_SUBW);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
Result := True;
end;
end;
{$ifndef i8086} { movzbl %al,%eax cannot be encoded in 16-bit mode (the machine code is equivalent to movzbw %al,%ax }
S_BL:
if not IsMOVZXAcceptable then
begin begin
if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) and if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) then
( { Change "movzbl %al, %eax" to "andl $0x0ffh, %eax" }
not IsMOVZXAcceptable
{ and $0xff,%ax has a smaller encoding but risks a partial write penalty }
or (
(cs_opt_size in current_settings.optimizerswitches) and
(taicpu(p).oper[1]^.reg = NR_AX)
)
) then
{Change "movzbw %al, %ax" to "andw $0x0ffh, %ax"}
begin begin
DebugMsg(SPeepholeOptimization + 'var7',p); DebugMsg(SPeepholeOptimization + 'var9',p);
taicpu(p).opcode := A_AND; taicpu(p).opcode := A_AND;
taicpu(p).changeopsize(S_W); taicpu(p).changeopsize(S_L);
taicpu(p).loadConst(0,$ff); taicpu(p).loadConst(0,$ff);
Result := True; Result := True;
end end
else if not IsMOVZXAcceptable and else if GetNextInstruction(p, hp1) and
GetNextInstruction(p, hp1) and
(tai(hp1).typ = ait_instruction) and (tai(hp1).typ = ait_instruction) and
(taicpu(hp1).opcode = A_AND) and (taicpu(hp1).opcode = A_AND) and
MatchOpType(taicpu(hp1),top_const,top_reg) and MatchOpType(taicpu(hp1),top_const,top_reg) and
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
{ Change "movzbw %reg1, %reg2; andw $const, %reg2" { Change "movzbl %reg1, %reg2; andl $const, %reg2"
to "movw %reg1, reg2; andw $(const1 and $ff), %reg2"} to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
begin begin
DebugMsg(SPeepholeOptimization + 'var8',p); DebugMsg(SPeepholeOptimization + 'var10',p);
taicpu(p).opcode := A_MOV; taicpu(p).opcode := A_MOV;
taicpu(p).changeopsize(S_W); taicpu(p).changeopsize(S_L);
setsubreg(taicpu(p).oper[0]^.reg,R_SUBW); { do not use R_SUBWHOLE
as movl %rdx,%eax
is invalid in assembler PM }
setsubreg(taicpu(p).oper[0]^.reg, R_SUBD);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff); taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
Result := True; Result := True;
end; end;
end; end;
{$ifndef i8086} { movzbl %al,%eax cannot be encoded in 16-bit mode (the machine code is equivalent to movzbw %al,%ax }
S_BL:
if not IsMOVZXAcceptable then
begin
if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) then
{ Change "movzbl %al, %eax" to "andl $0x0ffh, %eax" }
begin
DebugMsg(SPeepholeOptimization + 'var9',p);
taicpu(p).opcode := A_AND;
taicpu(p).changeopsize(S_L);
taicpu(p).loadConst(0,$ff);
Result := True;
end
else if GetNextInstruction(p, hp1) and
(tai(hp1).typ = ait_instruction) and
(taicpu(hp1).opcode = A_AND) and
MatchOpType(taicpu(hp1),top_const,top_reg) and
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
{ Change "movzbl %reg1, %reg2; andl $const, %reg2"
to "movl %reg1, reg2; andl $(const1 and $ff), %reg2"}
begin
DebugMsg(SPeepholeOptimization + 'var10',p);
taicpu(p).opcode := A_MOV;
taicpu(p).changeopsize(S_L);
{ do not use R_SUBWHOLE
as movl %rdx,%eax
is invalid in assembler PM }
setsubreg(taicpu(p).oper[0]^.reg, R_SUBD);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
Result := True;
end;
end;
{$endif i8086} {$endif i8086}
S_WL: S_WL:
if not IsMOVZXAcceptable then if not IsMOVZXAcceptable then
begin
if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) then
{ Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax" }
begin
DebugMsg(SPeepholeOptimization + 'var11',p);
taicpu(p).opcode := A_AND;
taicpu(p).changeopsize(S_L);
taicpu(p).loadConst(0,$ffff);
Result := True;
end
else if GetNextInstruction(p, hp1) and
(tai(hp1).typ = ait_instruction) and
(taicpu(hp1).opcode = A_AND) and
(taicpu(hp1).oper[0]^.typ = top_const) and
(taicpu(hp1).oper[1]^.typ = top_reg) and
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
{ Change "movzwl %reg1, %reg2; andl $const, %reg2"
to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
begin
DebugMsg(SPeepholeOptimization + 'var12',p);
taicpu(p).opcode := A_MOV;
taicpu(p).changeopsize(S_L);
{ do not use R_SUBWHOLE
as movl %rdx,%eax
is invalid in assembler PM }
setsubreg(taicpu(p).oper[0]^.reg, R_SUBD);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
Result := True;
end;
end;
else
InternalError(2017050705);
end;
end
else if not IsMOVZXAcceptable and (taicpu(p).oper[0]^.typ = top_ref) then
begin
if GetNextInstruction(p, hp1) and
(tai(hp1).typ = ait_instruction) and
(taicpu(hp1).opcode = A_AND) and
MatchOpType(taicpu(hp1),top_const,top_reg) and
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
begin begin
//taicpu(p).opcode := A_MOV; if (getsupreg(taicpu(p).oper[0]^.reg)=getsupreg(taicpu(p).oper[1]^.reg)) then
case taicpu(p).opsize Of { Change "movzwl %ax, %eax" to "andl $0x0ffffh, %eax" }
S_BL: begin
begin DebugMsg(SPeepholeOptimization + 'var11',p);
DebugMsg(SPeepholeOptimization + 'var13',p); taicpu(p).opcode := A_AND;
taicpu(hp1).changeopsize(S_L); taicpu(p).changeopsize(S_L);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff); taicpu(p).loadConst(0,$ffff);
end; Result := True;
S_WL: end
begin else if GetNextInstruction(p, hp1) and
DebugMsg(SPeepholeOptimization + 'var14',p); (tai(hp1).typ = ait_instruction) and
taicpu(hp1).changeopsize(S_L); (taicpu(hp1).opcode = A_AND) and
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff); (taicpu(hp1).oper[0]^.typ = top_const) and
end; (taicpu(hp1).oper[1]^.typ = top_reg) and
S_BW: (taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
begin { Change "movzwl %reg1, %reg2; andl $const, %reg2"
DebugMsg(SPeepholeOptimization + 'var15',p); to "movl %reg1, reg2; andl $(const1 and $ffff), %reg2"}
taicpu(hp1).changeopsize(S_W); begin
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff); DebugMsg(SPeepholeOptimization + 'var12',p);
end; taicpu(p).opcode := A_MOV;
else taicpu(p).changeopsize(S_L);
Internalerror(2017050704) { do not use R_SUBWHOLE
end; as movl %rdx,%eax
Result := True; is invalid in assembler PM }
setsubreg(taicpu(p).oper[0]^.reg, R_SUBD);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
Result := True;
end;
end; end;
else
InternalError(2017050705);
end;
end
else if not IsMOVZXAcceptable and (taicpu(p).oper[0]^.typ = top_ref) then
begin
if GetNextInstruction(p, hp1) and
(tai(hp1).typ = ait_instruction) and
(taicpu(hp1).opcode = A_AND) and
MatchOpType(taicpu(hp1),top_const,top_reg) and
(taicpu(hp1).oper[1]^.reg = taicpu(p).oper[1]^.reg) then
begin
case taicpu(p).opsize Of
S_BL:
if (taicpu(hp1).opsize <> S_L) or
(taicpu(hp1).oper[0]^.val > $FF) then
begin
DebugMsg(SPeepholeOptimization + 'var13',p);
taicpu(hp1).changeopsize(S_L);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
Include(OptsToCheck, aoc_ForceNewIteration);
end;
S_WL:
if (taicpu(hp1).opsize <> S_L) or
(taicpu(hp1).oper[0]^.val > $FFFF) then
begin
DebugMsg(SPeepholeOptimization + 'var14',p);
taicpu(hp1).changeopsize(S_L);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ffff);
Include(OptsToCheck, aoc_ForceNewIteration);
end;
S_BW:
if (taicpu(hp1).opsize <> S_W) or
(taicpu(hp1).oper[0]^.val > $FF) then
begin
DebugMsg(SPeepholeOptimization + 'var15',p);
taicpu(hp1).changeopsize(S_W);
taicpu(hp1).loadConst(0,taicpu(hp1).oper[0]^.val and $ff);
Include(OptsToCheck, aoc_ForceNewIteration);
end;
else
Internalerror(2017050704)
end;
end; end;
end;
end; end;
end; end;