mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 10:06:23 +02:00
Refactoring and bug fix in OptPass2Movx that could cause incorrect
values in overflow conditions
This commit is contained in:
parent
546455faca
commit
5738a6ccf1
@ -8431,7 +8431,7 @@ unit aoptx86;
|
|||||||
MinSize, MaxSize, TryShiftDown, TargetSize: TOpSize;
|
MinSize, MaxSize, TryShiftDown, TargetSize: TOpSize;
|
||||||
TargetSubReg: TSubRegister;
|
TargetSubReg: TSubRegister;
|
||||||
hp1, hp2: tai;
|
hp1, hp2: tai;
|
||||||
RegInUse, RegChanged, p_removed: Boolean;
|
RegInUse, RegChanged, p_removed, hp1_removed: Boolean;
|
||||||
|
|
||||||
{ Store list of found instructions so we don't have to call
|
{ Store list of found instructions so we don't have to call
|
||||||
GetNextInstructionUsingReg multiple times }
|
GetNextInstructionUsingReg multiple times }
|
||||||
@ -8480,7 +8480,7 @@ unit aoptx86;
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function AdjustInitialLoad: Boolean;
|
function AdjustInitialLoadAndSize: Boolean;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
|
|
||||||
@ -8535,45 +8535,95 @@ unit aoptx86;
|
|||||||
else
|
else
|
||||||
;
|
;
|
||||||
end;
|
end;
|
||||||
|
end
|
||||||
|
else if not hp1_removed and not RegInUse then
|
||||||
|
begin
|
||||||
|
{ If we have something like:
|
||||||
|
movzbl (oper),%regd
|
||||||
|
add x, %regd
|
||||||
|
movzbl %regb, %regd
|
||||||
|
|
||||||
|
We can reduce the register size to the input of the final
|
||||||
|
movzbl instruction. Overflows won't have any effect.
|
||||||
|
}
|
||||||
|
if (taicpu(p).opsize in [S_BW, S_BL]) and
|
||||||
|
(taicpu(hp1).opsize in [S_BW, S_BL{$ifdef x86_64}, S_BQ{$endif x86_64}]) then
|
||||||
|
begin
|
||||||
|
TargetSize := S_B;
|
||||||
|
setsubreg(ThisReg, R_SUBL);
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else if (taicpu(p).opsize = S_WL) and
|
||||||
|
(taicpu(hp1).opsize in [S_WL{$ifdef x86_64}, S_BQ{$endif x86_64}]) then
|
||||||
|
begin
|
||||||
|
TargetSize := S_W;
|
||||||
|
setsubreg(ThisReg, R_SUBW);
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Result then
|
||||||
|
begin
|
||||||
|
{ Convert the input MOVZX to a MOV }
|
||||||
|
if (taicpu(p).oper[0]^.typ = top_reg) and
|
||||||
|
SuperRegistersEqual(taicpu(p).oper[0]^.reg, ThisReg) then
|
||||||
|
begin
|
||||||
|
{ Or remove it completely! }
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 1a', p);
|
||||||
|
RemoveCurrentP(p);
|
||||||
|
p_removed := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Movzx2Mov 1a', p);
|
||||||
|
taicpu(p).opcode := A_MOV;
|
||||||
|
taicpu(p).oper[1]^.reg := ThisReg;
|
||||||
|
taicpu(p).opsize := TargetSize;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AdjustFinalLoad;
|
procedure AdjustFinalLoad;
|
||||||
begin
|
begin
|
||||||
if ((TargetSize = S_L) and (taicpu(hp1).opsize in [S_L, S_BL, S_WL])) or
|
if not LowerUnsignedOverflow then
|
||||||
((TargetSize = S_W) and (taicpu(hp1).opsize in [S_W, S_BW])) then
|
|
||||||
begin
|
begin
|
||||||
{ Convert the output MOVZX to a MOV }
|
if ((TargetSize = S_L) and (taicpu(hp1).opsize in [S_L, S_BL, S_WL])) or
|
||||||
if SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
((TargetSize = S_W) and (taicpu(hp1).opsize in [S_W, S_BW])) then
|
||||||
begin
|
begin
|
||||||
{ Or remove it completely! }
|
{ Convert the output MOVZX to a MOV }
|
||||||
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 2', hp1);
|
if SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
||||||
|
|
||||||
{ Be careful; if p = hp1 and p was also removed, p
|
|
||||||
will become a dangling pointer }
|
|
||||||
if p = hp1 then
|
|
||||||
begin
|
begin
|
||||||
RemoveCurrentp(p); { p = hp1 and will then become the next instruction }
|
{ Or remove it completely! }
|
||||||
p_removed := True;
|
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 2', hp1);
|
||||||
|
|
||||||
|
{ Be careful; if p = hp1 and p was also removed, p
|
||||||
|
will become a dangling pointer }
|
||||||
|
if p = hp1 then
|
||||||
|
begin
|
||||||
|
RemoveCurrentp(p); { p = hp1 and will then become the next instruction }
|
||||||
|
p_removed := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
RemoveInstruction(hp1);
|
||||||
|
|
||||||
|
hp1_removed := True;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
RemoveInstruction(hp1);
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Movzx2Mov 2', hp1);
|
||||||
|
taicpu(hp1).opcode := A_MOV;
|
||||||
|
taicpu(hp1).oper[0]^.reg := ThisReg;
|
||||||
|
taicpu(hp1).opsize := TargetSize;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else
|
else if (TargetSize = S_B) and (MaxSize = S_W) and (taicpu(hp1).opsize = S_WL) then
|
||||||
begin
|
begin
|
||||||
DebugMsg(SPeepholeOptimization + 'Movzx2Mov 2', hp1);
|
{ Need to change the size of the output }
|
||||||
taicpu(hp1).opcode := A_MOV;
|
DebugMsg(SPeepholeOptimization + 'movzwl2movzbl 2', hp1);
|
||||||
taicpu(hp1).oper[0]^.reg := ThisReg;
|
taicpu(hp1).oper[0]^.reg := ThisReg;
|
||||||
taicpu(hp1).opsize := TargetSize;
|
taicpu(hp1).opsize := S_BL;
|
||||||
end;
|
end;
|
||||||
end
|
|
||||||
else if (TargetSize = S_B) and (MaxSize = S_W) and (taicpu(hp1).opsize = S_WL) then
|
|
||||||
begin
|
|
||||||
{ Need to change the size of the output }
|
|
||||||
DebugMsg(SPeepholeOptimization + 'movzwl2movzbl 2', hp1);
|
|
||||||
taicpu(hp1).oper[0]^.reg := ThisReg;
|
|
||||||
taicpu(hp1).opsize := S_BL;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -8643,6 +8693,7 @@ unit aoptx86;
|
|||||||
|
|
||||||
{ Update the register to its new size }
|
{ Update the register to its new size }
|
||||||
setsubreg(ThisReg, TargetSubReg);
|
setsubreg(ThisReg, TargetSubReg);
|
||||||
|
RegInUse := False;
|
||||||
|
|
||||||
if not SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
if not SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
||||||
begin
|
begin
|
||||||
@ -8650,7 +8701,6 @@ unit aoptx86;
|
|||||||
{ Check to see if the active register is used afterwards;
|
{ Check to see if the active register is used afterwards;
|
||||||
if not, we can change it and make a saving. }
|
if not, we can change it and make a saving. }
|
||||||
|
|
||||||
RegInUse := False;
|
|
||||||
TransferUsedRegs(TmpUsedRegs);
|
TransferUsedRegs(TmpUsedRegs);
|
||||||
|
|
||||||
{ The target register may be marked as in use to cross
|
{ The target register may be marked as in use to cross
|
||||||
@ -8723,6 +8773,8 @@ unit aoptx86;
|
|||||||
else
|
else
|
||||||
RemoveInstruction(hp1);
|
RemoveInstruction(hp1);
|
||||||
|
|
||||||
|
hp1_removed := True;
|
||||||
|
|
||||||
{ Instruction will become "mov %reg,%reg" }
|
{ Instruction will become "mov %reg,%reg" }
|
||||||
if not p_removed and (taicpu(p).opcode = A_MOV) and
|
if not p_removed and (taicpu(p).opcode = A_MOV) and
|
||||||
MatchOperand(taicpu(p).oper[0]^, ThisReg) then
|
MatchOperand(taicpu(p).oper[0]^, ThisReg) then
|
||||||
@ -8764,7 +8816,7 @@ unit aoptx86;
|
|||||||
else
|
else
|
||||||
AdjustFinalLoad;
|
AdjustFinalLoad;
|
||||||
|
|
||||||
Result := AdjustInitialLoad or Result;
|
Result := AdjustInitialLoadAndSize or Result;
|
||||||
|
|
||||||
{ Now go through every instruction we found and change the
|
{ Now go through every instruction we found and change the
|
||||||
size. If TargetSize = MaxSize, then almost no changes are
|
size. If TargetSize = MaxSize, then almost no changes are
|
||||||
@ -8799,6 +8851,7 @@ unit aoptx86;
|
|||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
p_removed := False;
|
p_removed := False;
|
||||||
|
hp1_removed := False;
|
||||||
ThisReg := taicpu(p).oper[1]^.reg;
|
ThisReg := taicpu(p).oper[1]^.reg;
|
||||||
|
|
||||||
{ Check for:
|
{ Check for:
|
||||||
@ -9057,7 +9110,7 @@ unit aoptx86;
|
|||||||
if LowerUnsignedOverflow and not UpperUnsignedOverflow then
|
if LowerUnsignedOverflow and not UpperUnsignedOverflow then
|
||||||
begin
|
begin
|
||||||
{ Exceeded lower bound but not upper bound }
|
{ Exceeded lower bound but not upper bound }
|
||||||
TargetSize := MaxSize;
|
Exit;
|
||||||
end
|
end
|
||||||
else if not LowerSignedOverflow or not LowerUnsignedOverflow then
|
else if not LowerSignedOverflow or not LowerUnsignedOverflow then
|
||||||
begin
|
begin
|
||||||
@ -9078,8 +9131,8 @@ unit aoptx86;
|
|||||||
InternalError(2021051002);
|
InternalError(2021051002);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if TargetSize <> MaxSize then
|
if TargetSize <> MaxSize then
|
||||||
begin
|
begin
|
||||||
{ Update the register to its new size }
|
{ Update the register to its new size }
|
||||||
setsubreg(ThisReg, TargetSubReg);
|
setsubreg(ThisReg, TargetSubReg);
|
||||||
|
|
||||||
@ -9088,7 +9141,7 @@ unit aoptx86;
|
|||||||
taicpu(hp1).opsize := TargetSize;
|
taicpu(hp1).opsize := TargetSize;
|
||||||
|
|
||||||
{ Convert the input MOVZX to a MOV if necessary }
|
{ Convert the input MOVZX to a MOV if necessary }
|
||||||
AdjustInitialLoad;
|
AdjustInitialLoadAndSize;
|
||||||
|
|
||||||
if (InstrMax >= 0) then
|
if (InstrMax >= 0) then
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user