Overflow bug fixes to MovZX/SX optimisations when CMP instructions are encountered.

This commit is contained in:
J. Gareth "Curious Kit" Moreton 2021-12-22 03:34:49 +00:00
parent 6dbe71cd30
commit b4c8c1da12

View File

@ -7968,7 +7968,7 @@ unit aoptx86;
function CheckOverflowConditions: Boolean; function CheckOverflowConditions: Boolean;
begin begin
Result := True; Result := True;
if (TestValSignedMax > SignedUpperLimit) or (TestValSignedMax < SignedUpperLimitBottom) then if (TestValSignedMax > SignedUpperLimit) then
UpperSignedOverflow := True; UpperSignedOverflow := True;
if (TestValSignedMax > SignedLowerLimit) or (TestValSignedMax < SignedLowerLimitBottom) then if (TestValSignedMax > SignedLowerLimit) or (TestValSignedMax < SignedLowerLimitBottom) then
@ -7978,7 +7978,7 @@ unit aoptx86;
LowerUnsignedOverflow := True; LowerUnsignedOverflow := True;
if (TestValMin > UpperLimit) or (TestValMax > UpperLimit) or (TestValSignedMax > UpperLimit) or if (TestValMin > UpperLimit) or (TestValMax > UpperLimit) or (TestValSignedMax > UpperLimit) or
(TestValMin < SignedUpperLimitBottom) or (TestValMax < SignedUpperLimitBottom) or (TestValSignedMax > SignedUpperLimit) then (TestValMin < SignedUpperLimitBottom) or (TestValMax < SignedUpperLimitBottom) or (TestValSignedMax < SignedUpperLimitBottom) then
begin begin
{ Absolute overflow } { Absolute overflow }
Result := False; Result := False;
@ -8270,12 +8270,15 @@ unit aoptx86;
smallest allowed signed value for the minimum size (e.g. smallest allowed signed value for the minimum size (e.g.
-128 for 8-bit) } -128 for 8-bit) }
not ( not (
((taicpu(hp1).oper[0]^.val and UpperLimit) = taicpu(hp1).oper[0]^.val) or ((taicpu(hp1).oper[0]^.val and LowerLimit) = taicpu(hp1).oper[0]^.val) or
{ Is it in the negative range? } { Is it in the negative range? }
(
(taicpu(hp1).oper[0]^.val < 0) and
(taicpu(hp1).oper[0]^.val >= SignedLowerLimitBottom) (taicpu(hp1).oper[0]^.val >= SignedLowerLimitBottom)
)
) then ) then
Break; Break;
(*
{ ANDing can't increase the value past the limit or decrease { ANDing can't increase the value past the limit or decrease
it below 0, so we can skip the checks, plus the test value it below 0, so we can skip the checks, plus the test value
won't change afterwards } won't change afterwards }
@ -8285,17 +8288,6 @@ unit aoptx86;
(taicpu(hp1).oper[0]^.val <> 0) then (taicpu(hp1).oper[0]^.val <> 0) then
begin begin
WorkingValue := taicpu(hp1).oper[0]^.val; WorkingValue := taicpu(hp1).oper[0]^.val;
case MinSize of
S_B:
if (WorkingValue and $ff)<>WorkingValue then
break;
S_W:
if (WorkingValue and $ffff)<>WorkingValue then
break;
else
;
end;
TestValMin := TestValMin - WorkingValue; TestValMin := TestValMin - WorkingValue;
TestValMax := TestValMax - WorkingValue; TestValMax := TestValMax - WorkingValue;
@ -8309,18 +8301,36 @@ unit aoptx86;
TestValMin := TestValMin + WorkingValue; TestValMin := TestValMin + WorkingValue;
TestValMax := TestValMax + WorkingValue; TestValMax := TestValMax + WorkingValue;
TestValSignedMax := TestValSignedMax + WorkingValue; TestValSignedMax := TestValSignedMax + WorkingValue;
end; end; *)
{ Check to see if the active register is used afterwards } { Check to see if the active register is used afterwards }
TransferUsedRegs(TmpUsedRegs); TransferUsedRegs(TmpUsedRegs);
IncludeRegInUsedRegs(ThisReg, TmpUsedRegs); IncludeRegInUsedRegs(ThisReg, TmpUsedRegs);
if not RegUsedAfterInstruction(ThisReg, hp1, TmpUsedRegs) then if not RegUsedAfterInstruction(ThisReg, hp1, TmpUsedRegs) then
begin begin
case MinSize of { Make sure the comparison or any previous instructions
hasn't pushed the test values outside of the range of
MinSize }
if LowerUnsignedOverflow and not UpperUnsignedOverflow then
begin
{ Exceeded lower bound but not upper bound }
TargetSize := MaxSize;
end
else if not LowerSignedOverflow or not LowerUnsignedOverflow then
begin
{ Size didn't exceed lower bound }
TargetSize := MinSize;
end
else
Break;
case TargetSize of
S_B: S_B:
TargetSubReg := R_SUBL; TargetSubReg := R_SUBL;
S_W: S_W:
TargetSubReg := R_SUBW; TargetSubReg := R_SUBW;
S_L:
TargetSubReg := R_SUBD;
else else
InternalError(2021051002); InternalError(2021051002);
end; end;
@ -8427,19 +8437,14 @@ unit aoptx86;
end end
else else
begin begin
TestValMin := TestValMin + taicpu(hp1).oper[0]^.val; WorkingValue := taicpu(hp1).oper[0]^.val;
TestValMax := TestValMax + taicpu(hp1).oper[0]^.val; TestValMin := TestValMin + WorkingValue;
TestValSignedMax := TestValSignedMax + taicpu(hp1).oper[0]^.val; TestValMax := TestValMax + WorkingValue;
TestValSignedMax := TestValSignedMax + WorkingValue;
end; end;
end; end;
A_SUB: A_SUB:
begin begin
if OrXorUsed then
{ Too high a risk of non-linear behaviour that breaks DFA here }
Break
else
BitwiseOnly := False;
if (taicpu(hp1).oper[0]^.typ = top_reg) then if (taicpu(hp1).oper[0]^.typ = top_reg) then
begin begin
TestValMin := 0; TestValMin := 0;
@ -8448,9 +8453,16 @@ unit aoptx86;
end end
else else
begin begin
TestValMin := TestValMin - taicpu(hp1).oper[0]^.val; if OrXorUsed then
TestValMax := TestValMax - taicpu(hp1).oper[0]^.val; { Too high a risk of non-linear behaviour that breaks DFA here }
TestValSignedMax := TestValSignedMax - taicpu(hp1).oper[0]^.val; Break
else
BitwiseOnly := False;
WorkingValue := taicpu(hp1).oper[0]^.val;
TestValMin := TestValMin - WorkingValue;
TestValMax := TestValMax - WorkingValue;
TestValSignedMax := TestValSignedMax - WorkingValue;
end; end;
end; end;
A_AND: A_AND:
@ -8485,9 +8497,10 @@ unit aoptx86;
InternalError(2020112320); InternalError(2020112320);
end; end;
TestValMin := TestValMin and taicpu(hp1).oper[0]^.val; WorkingValue := taicpu(hp1).oper[0]^.val;
TestValMax := TestValMax and taicpu(hp1).oper[0]^.val; TestValMin := TestValMin and WorkingValue;
TestValSignedMax := TestValSignedMax and taicpu(hp1).oper[0]^.val; TestValMax := TestValMax and WorkingValue;
TestValSignedMax := TestValSignedMax and WorkingValue;
end; end;
A_OR: A_OR:
begin begin
@ -8496,33 +8509,49 @@ unit aoptx86;
OrXorUsed := True; OrXorUsed := True;
TestValMin := TestValMin or taicpu(hp1).oper[0]^.val; WorkingValue := taicpu(hp1).oper[0]^.val;
TestValMax := TestValMax or taicpu(hp1).oper[0]^.val; TestValMin := TestValMin or WorkingValue;
TestValSignedMax := TestValSignedMax or taicpu(hp1).oper[0]^.val; TestValMax := TestValMax or WorkingValue;
TestValSignedMax := TestValSignedMax or WorkingValue;
end; end;
A_XOR: A_XOR:
begin
if (taicpu(hp1).oper[0]^.typ = top_reg) then
begin
TestValMin := 0;
TestValMax := 0;
TestValSignedMax := 0;
end
else
begin begin
if not BitwiseOnly then if not BitwiseOnly then
Break; Break;
OrXorUsed := True; OrXorUsed := True;
TestValMin := TestValMin xor taicpu(hp1).oper[0]^.val; WorkingValue := taicpu(hp1).oper[0]^.val;
TestValMax := TestValMax xor taicpu(hp1).oper[0]^.val; TestValMin := TestValMin xor WorkingValue;
TestValSignedMax := TestValSignedMax xor taicpu(hp1).oper[0]^.val; TestValMax := TestValMax xor WorkingValue;
TestValSignedMax := TestValSignedMax xor WorkingValue;
end;
end; end;
A_SHL: A_SHL:
begin begin
TestValMin := TestValMin shl taicpu(hp1).oper[0]^.val; BitwiseOnly := False;
TestValMax := TestValMax shl taicpu(hp1).oper[0]^.val;
TestValSignedMax := TestValSignedMax shl taicpu(hp1).oper[0]^.val; WorkingValue := taicpu(hp1).oper[0]^.val;
TestValMin := TestValMin shl WorkingValue;
TestValMax := TestValMax shl WorkingValue;
TestValSignedMax := TestValSignedMax shl WorkingValue;
end; end;
A_SHR, A_SHR,
{ The first instruction was MOVZX, so the value won't be negative } { The first instruction was MOVZX, so the value won't be negative }
A_SAR: A_SAR:
begin begin
if InstrMax <> -1 then
BitwiseOnly := False
else
{ we might be able to go smaller if SHR appears first } { we might be able to go smaller if SHR appears first }
if InstrMax = -1 then
case MinSize of case MinSize of
S_B: S_B:
; ;
@ -8553,17 +8582,18 @@ unit aoptx86;
InternalError(2020112321); InternalError(2020112321);
end; end;
WorkingValue := taicpu(hp1).oper[0]^.val;
if taicpu(hp1).opcode = A_SAR then if taicpu(hp1).opcode = A_SAR then
begin begin
TestValMin := SarInt64(TestValMin, taicpu(hp1).oper[0]^.val); TestValMin := SarInt64(TestValMin, WorkingValue);
TestValMax := SarInt64(TestValMax, taicpu(hp1).oper[0]^.val); TestValMax := SarInt64(TestValMax, WorkingValue);
TestValSignedMax := SarInt64(TestValSignedMax, taicpu(hp1).oper[0]^.val); TestValSignedMax := SarInt64(TestValSignedMax, WorkingValue);
end end
else else
begin begin
TestValMin := TestValMin shr taicpu(hp1).oper[0]^.val; TestValMin := TestValMin shr WorkingValue;
TestValMax := TestValMax shr taicpu(hp1).oper[0]^.val; TestValMax := TestValMax shr WorkingValue;
TestValSignedMax := TestValSignedMax shr taicpu(hp1).oper[0]^.val; TestValSignedMax := TestValSignedMax shr WorkingValue;
end; end;
end; end;
else else