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