mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 10:39:18 +02:00
Refactoring of OptPass2Movx to remove goto
This commit is contained in:
parent
9894fe8082
commit
cafd708b6d
@ -7939,9 +7939,6 @@ unit aoptx86;
|
|||||||
{$push}
|
{$push}
|
||||||
{$q-}{$r-}
|
{$q-}{$r-}
|
||||||
function TX86AsmOptimizer.OptPass2Movx(var p : tai) : boolean;
|
function TX86AsmOptimizer.OptPass2Movx(var p : tai) : boolean;
|
||||||
label
|
|
||||||
{ This label permits the case block for MOVSX/D to pass into the MOVZX block }
|
|
||||||
movzx_cascade;
|
|
||||||
var
|
var
|
||||||
ThisReg: TRegister;
|
ThisReg: TRegister;
|
||||||
MinSize, MaxSize, TryShiftDown, TargetSize: TOpSize;
|
MinSize, MaxSize, TryShiftDown, TargetSize: TOpSize;
|
||||||
@ -8034,6 +8031,278 @@ unit aoptx86;
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function CompressInstructions: Boolean;
|
||||||
|
var
|
||||||
|
LocalIndex: Integer;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
|
||||||
|
{ The objective here is to try to find a combination that
|
||||||
|
removes one of the MOV/Z instructions. }
|
||||||
|
|
||||||
|
if (
|
||||||
|
(taicpu(p).oper[0]^.typ <> top_reg) or
|
||||||
|
not SuperRegistersEqual(taicpu(p).oper[0]^.reg, ThisReg)
|
||||||
|
) and
|
||||||
|
(taicpu(hp1).oper[1]^.typ = top_reg) and
|
||||||
|
SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
||||||
|
begin
|
||||||
|
{ Make a preference to remove the second MOVZX instruction }
|
||||||
|
case taicpu(hp1).opsize of
|
||||||
|
S_BL, S_WL:
|
||||||
|
begin
|
||||||
|
TargetSize := S_L;
|
||||||
|
TargetSubReg := R_SUBD;
|
||||||
|
end;
|
||||||
|
|
||||||
|
S_BW:
|
||||||
|
begin
|
||||||
|
TargetSize := S_W;
|
||||||
|
TargetSubReg := R_SUBW;
|
||||||
|
end;
|
||||||
|
|
||||||
|
else
|
||||||
|
InternalError(2020112302);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
|
||||||
|
if LowerUnsignedOverflow and not UpperUnsignedOverflow then
|
||||||
|
begin
|
||||||
|
{ Exceeded lower bound but not upper bound }
|
||||||
|
TargetSize := MaxSize;
|
||||||
|
end
|
||||||
|
else if not LowerUnsignedOverflow then
|
||||||
|
begin
|
||||||
|
{ Size didn't exceed lower bound }
|
||||||
|
TargetSize := MinSize;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Exit;
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
case TargetSize of
|
||||||
|
S_B:
|
||||||
|
TargetSubReg := R_SUBL;
|
||||||
|
S_W:
|
||||||
|
TargetSubReg := R_SUBW;
|
||||||
|
S_L:
|
||||||
|
TargetSubReg := R_SUBD;
|
||||||
|
else
|
||||||
|
InternalError(2020112350);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Update the register to its new size }
|
||||||
|
setsubreg(ThisReg, TargetSubReg);
|
||||||
|
|
||||||
|
if not SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
||||||
|
begin
|
||||||
|
|
||||||
|
{ Check to see if the active register is used afterwards;
|
||||||
|
if not, we can change it and make a saving. }
|
||||||
|
|
||||||
|
RegInUse := False;
|
||||||
|
TransferUsedRegs(TmpUsedRegs);
|
||||||
|
|
||||||
|
{ The target register may be marked as in use to cross
|
||||||
|
a jump to a distant label, so exclude it }
|
||||||
|
ExcludeRegFromUsedRegs(taicpu(hp1).oper[1]^.reg, TmpUsedRegs);
|
||||||
|
|
||||||
|
hp2 := p;
|
||||||
|
repeat
|
||||||
|
|
||||||
|
{ Explicitly check for the excluded register (don't include the first
|
||||||
|
instruction as it may be reading from here }
|
||||||
|
if ((p <> hp2) and (RegInInstruction(taicpu(hp1).oper[1]^.reg, hp2))) or
|
||||||
|
RegInUsedRegs(taicpu(hp1).oper[1]^.reg, TmpUsedRegs) then
|
||||||
|
begin
|
||||||
|
RegInUse := True;
|
||||||
|
Break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
UpdateUsedRegs(TmpUsedRegs, tai(hp2.next));
|
||||||
|
|
||||||
|
if not GetNextInstruction(hp2, hp2) then
|
||||||
|
InternalError(2020112340);
|
||||||
|
|
||||||
|
until (hp2 = hp1);
|
||||||
|
|
||||||
|
if not RegInUse and RegUsedAfterInstruction(ThisReg, hp1, TmpUsedRegs) then
|
||||||
|
{ We might still be able to get away with this }
|
||||||
|
RegInUse := not
|
||||||
|
(
|
||||||
|
GetNextInstructionUsingReg(hp1, hp2, ThisReg) and
|
||||||
|
(hp2.typ = ait_instruction) and
|
||||||
|
(
|
||||||
|
{ Under -O1 and -O2, GetNextInstructionUsingReg may return an
|
||||||
|
instruction that doesn't actually contain ThisReg }
|
||||||
|
(cs_opt_level3 in current_settings.optimizerswitches) or
|
||||||
|
RegInInstruction(ThisReg, hp2)
|
||||||
|
) and
|
||||||
|
RegLoadedWithNewValue(ThisReg, hp2)
|
||||||
|
);
|
||||||
|
|
||||||
|
if not RegInUse then
|
||||||
|
begin
|
||||||
|
{ Force the register size to the same as this instruction so it can be removed}
|
||||||
|
if (taicpu(hp1).opsize in [S_L, S_BL, S_WL]) then
|
||||||
|
begin
|
||||||
|
TargetSize := S_L;
|
||||||
|
TargetSubReg := R_SUBD;
|
||||||
|
end
|
||||||
|
else if (taicpu(hp1).opsize in [S_W, S_BW]) then
|
||||||
|
begin
|
||||||
|
TargetSize := S_W;
|
||||||
|
TargetSubReg := R_SUBW;
|
||||||
|
end;
|
||||||
|
|
||||||
|
ThisReg := taicpu(hp1).oper[1]^.reg;
|
||||||
|
setsubreg(ThisReg, TargetSubReg);
|
||||||
|
RegChanged := True;
|
||||||
|
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Simplified register usage so ' + debug_regname(ThisReg) + ' = ' + debug_regname(taicpu(p).oper[1]^.reg), p);
|
||||||
|
|
||||||
|
TransferUsedRegs(TmpUsedRegs);
|
||||||
|
AllocRegBetween(ThisReg, p, hp1, TmpUsedRegs);
|
||||||
|
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 3', hp1);
|
||||||
|
if p = hp1 then
|
||||||
|
begin
|
||||||
|
RemoveCurrentp(p); { p = hp1 and will then become the next instruction }
|
||||||
|
p_removed := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
RemoveInstruction(hp1);
|
||||||
|
|
||||||
|
{ Instruction will become "mov %reg,%reg" }
|
||||||
|
if not p_removed and (taicpu(p).opcode = A_MOV) and
|
||||||
|
MatchOperand(taicpu(p).oper[0]^, ThisReg) then
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 6', p);
|
||||||
|
RemoveCurrentP(p);
|
||||||
|
p_removed := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
taicpu(p).oper[1]^.reg := ThisReg;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if TargetSize <> MaxSize then
|
||||||
|
begin
|
||||||
|
{ Since the register is in use, we have to force it to
|
||||||
|
MaxSize otherwise part of it may become undefined later on }
|
||||||
|
TargetSize := MaxSize;
|
||||||
|
|
||||||
|
case TargetSize of
|
||||||
|
S_B:
|
||||||
|
TargetSubReg := R_SUBL;
|
||||||
|
S_W:
|
||||||
|
TargetSubReg := R_SUBW;
|
||||||
|
S_L:
|
||||||
|
TargetSubReg := R_SUBD;
|
||||||
|
else
|
||||||
|
InternalError(2020112351);
|
||||||
|
end;
|
||||||
|
|
||||||
|
setsubreg(ThisReg, TargetSubReg);
|
||||||
|
end;
|
||||||
|
|
||||||
|
AdjustFinalLoad;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
AdjustFinalLoad;
|
||||||
|
|
||||||
|
if not p_removed then
|
||||||
|
begin
|
||||||
|
if TargetSize = MinSize 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 1', p);
|
||||||
|
DebugMsg(SPeepholeOptimization + tostr(InstrMax), p);
|
||||||
|
RemoveCurrentP(p);
|
||||||
|
p_removed := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'Movzx2Mov 1', p);
|
||||||
|
taicpu(p).opcode := A_MOV;
|
||||||
|
taicpu(p).oper[1]^.reg := ThisReg;
|
||||||
|
taicpu(p).opsize := TargetSize;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else if TargetSize <> MaxSize then
|
||||||
|
begin
|
||||||
|
|
||||||
|
case MaxSize of
|
||||||
|
S_L:
|
||||||
|
if TargetSize = S_W then
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'movzbl2movzbw', p);
|
||||||
|
taicpu(p).opsize := S_BW;
|
||||||
|
taicpu(p).oper[1]^.reg := ThisReg;
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
InternalError(2020112341);
|
||||||
|
|
||||||
|
S_W:
|
||||||
|
if TargetSize = S_L then
|
||||||
|
begin
|
||||||
|
DebugMsg(SPeepholeOptimization + 'movzbw2movzbl', p);
|
||||||
|
taicpu(p).opsize := S_BL;
|
||||||
|
taicpu(p).oper[1]^.reg := ThisReg;
|
||||||
|
Result := True;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
InternalError(2020112342);
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Now go through every instruction we found and change the
|
||||||
|
size. If TargetSize = MaxSize, then almost no changes are
|
||||||
|
needed and Result can remain False if it hasn't been set
|
||||||
|
yet.
|
||||||
|
|
||||||
|
If RegChanged is True, then the register requires changing
|
||||||
|
and so the point about TargetSize = MaxSize doesn't apply. }
|
||||||
|
|
||||||
|
if ((TargetSize <> MaxSize) or RegChanged) and (InstrMax >= 0) then
|
||||||
|
begin
|
||||||
|
for LocalIndex := 0 to InstrMax do
|
||||||
|
begin
|
||||||
|
|
||||||
|
{ If p_removed is true, then the original MOV/Z was removed
|
||||||
|
and removing the AND instruction may not be safe if it
|
||||||
|
appears first }
|
||||||
|
if (InstrList[LocalIndex].oper[InstrList[LocalIndex].ops - 1]^.typ <> top_reg) then
|
||||||
|
InternalError(2020112310);
|
||||||
|
|
||||||
|
if InstrList[LocalIndex].oper[0]^.typ = top_reg then
|
||||||
|
InstrList[LocalIndex].oper[0]^.reg := ThisReg;
|
||||||
|
|
||||||
|
InstrList[LocalIndex].oper[InstrList[LocalIndex].ops - 1]^.reg := ThisReg;
|
||||||
|
InstrList[LocalIndex].opsize := TargetSize;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
p_removed := False;
|
p_removed := False;
|
||||||
@ -8671,7 +8940,7 @@ unit aoptx86;
|
|||||||
}
|
}
|
||||||
|
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
if (taicpu(hp1).opcode = A_MOVSXD) and SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
if (taicpu(hp1).opsize = S_LQ) and SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
||||||
begin
|
begin
|
||||||
{ this becomes a zero extension from 32-bit to 64-bit, but
|
{ this becomes a zero extension from 32-bit to 64-bit, but
|
||||||
the upper 32 bits are already zero, so just delete the
|
the upper 32 bits are already zero, so just delete the
|
||||||
@ -8715,10 +8984,8 @@ unit aoptx86;
|
|||||||
;
|
;
|
||||||
end;
|
end;
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
Result := True;
|
Result := CompressInstructions;
|
||||||
|
Exit;
|
||||||
{ Enter the A_MOVZX block below }
|
|
||||||
goto movzx_cascade;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -8729,11 +8996,9 @@ unit aoptx86;
|
|||||||
|
|
||||||
if not SuperRegistersEqual(taicpu(hp1).oper[0]^.reg, ThisReg) then
|
if not SuperRegistersEqual(taicpu(hp1).oper[0]^.reg, ThisReg) then
|
||||||
begin
|
begin
|
||||||
{ Because hp1 was obtained via GetNextInstructionUsingReg
|
|
||||||
and ThisReg doesn't appear in the first operand, it
|
|
||||||
must appear in the second operand and hence gets
|
|
||||||
overwritten }
|
|
||||||
if (InstrMax = -1) and
|
if (InstrMax = -1) and
|
||||||
|
{ Will return false if the second parameter isn't ThisReg
|
||||||
|
(can happen on -O2 and under) }
|
||||||
Reg1WriteOverwritesReg2Entirely(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
Reg1WriteOverwritesReg2Entirely(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
||||||
begin
|
begin
|
||||||
{ The two MOVZX instructions are adjacent, so remove the first one }
|
{ The two MOVZX instructions are adjacent, so remove the first one }
|
||||||
@ -8746,272 +9011,7 @@ unit aoptx86;
|
|||||||
Break;
|
Break;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
movzx_cascade:
|
Result := CompressInstructions;
|
||||||
{ The objective here is to try to find a combination that
|
|
||||||
removes one of the MOV/Z instructions. }
|
|
||||||
|
|
||||||
if (
|
|
||||||
(taicpu(p).oper[0]^.typ <> top_reg) or
|
|
||||||
not SuperRegistersEqual(taicpu(p).oper[0]^.reg, ThisReg)
|
|
||||||
) and
|
|
||||||
(taicpu(hp1).oper[1]^.typ = top_reg) and
|
|
||||||
SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
|
||||||
begin
|
|
||||||
{ Make a preference to remove the second MOVZX instruction }
|
|
||||||
case taicpu(hp1).opsize of
|
|
||||||
S_BL, S_WL:
|
|
||||||
begin
|
|
||||||
TargetSize := S_L;
|
|
||||||
TargetSubReg := R_SUBD;
|
|
||||||
end;
|
|
||||||
|
|
||||||
S_BW:
|
|
||||||
begin
|
|
||||||
TargetSize := S_W;
|
|
||||||
TargetSubReg := R_SUBW;
|
|
||||||
end;
|
|
||||||
|
|
||||||
else
|
|
||||||
InternalError(2020112302);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
|
|
||||||
if LowerUnsignedOverflow and not UpperUnsignedOverflow then
|
|
||||||
begin
|
|
||||||
{ Exceeded lower bound but not upper bound }
|
|
||||||
TargetSize := MaxSize;
|
|
||||||
end
|
|
||||||
else if not LowerUnsignedOverflow then
|
|
||||||
begin
|
|
||||||
{ Size didn't exceed lower bound }
|
|
||||||
TargetSize := MinSize;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Break;
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
case TargetSize of
|
|
||||||
S_B:
|
|
||||||
TargetSubReg := R_SUBL;
|
|
||||||
S_W:
|
|
||||||
TargetSubReg := R_SUBW;
|
|
||||||
S_L:
|
|
||||||
TargetSubReg := R_SUBD;
|
|
||||||
else
|
|
||||||
InternalError(2020112350);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Update the register to its new size }
|
|
||||||
setsubreg(ThisReg, TargetSubReg);
|
|
||||||
|
|
||||||
if not SuperRegistersEqual(taicpu(hp1).oper[1]^.reg, ThisReg) then
|
|
||||||
begin
|
|
||||||
|
|
||||||
{ Check to see if the active register is used afterwards;
|
|
||||||
if not, we can change it and make a saving. }
|
|
||||||
|
|
||||||
RegInUse := False;
|
|
||||||
TransferUsedRegs(TmpUsedRegs);
|
|
||||||
|
|
||||||
{ The target register may be marked as in use to cross
|
|
||||||
a jump to a distant label, so exclude it }
|
|
||||||
ExcludeRegFromUsedRegs(taicpu(hp1).oper[1]^.reg, TmpUsedRegs);
|
|
||||||
|
|
||||||
hp2 := p;
|
|
||||||
repeat
|
|
||||||
|
|
||||||
{ Explicitly check for the excluded register (don't include the first
|
|
||||||
instruction as it may be reading from here }
|
|
||||||
if ((p <> hp2) and (RegInInstruction(taicpu(hp1).oper[1]^.reg, hp2))) or
|
|
||||||
RegInUsedRegs(taicpu(hp1).oper[1]^.reg, TmpUsedRegs) then
|
|
||||||
begin
|
|
||||||
RegInUse := True;
|
|
||||||
Break;
|
|
||||||
end;
|
|
||||||
|
|
||||||
UpdateUsedRegs(TmpUsedRegs, tai(hp2.next));
|
|
||||||
|
|
||||||
if not GetNextInstruction(hp2, hp2) then
|
|
||||||
InternalError(2020112340);
|
|
||||||
|
|
||||||
until (hp2 = hp1);
|
|
||||||
|
|
||||||
if not RegInUse and RegUsedAfterInstruction(ThisReg, hp1, TmpUsedRegs) then
|
|
||||||
{ We might still be able to get away with this }
|
|
||||||
RegInUse := not
|
|
||||||
(
|
|
||||||
GetNextInstructionUsingReg(hp1, hp2, ThisReg) and
|
|
||||||
(hp2.typ = ait_instruction) and
|
|
||||||
(
|
|
||||||
{ Under -O1 and -O2, GetNextInstructionUsingReg may return an
|
|
||||||
instruction that doesn't actually contain ThisReg }
|
|
||||||
(cs_opt_level3 in current_settings.optimizerswitches) or
|
|
||||||
RegInInstruction(ThisReg, hp2)
|
|
||||||
) and
|
|
||||||
RegLoadedWithNewValue(ThisReg, hp2)
|
|
||||||
);
|
|
||||||
|
|
||||||
if not RegInUse then
|
|
||||||
begin
|
|
||||||
{ Force the register size to the same as this instruction so it can be removed}
|
|
||||||
if (taicpu(hp1).opsize in [S_L, S_BL, S_WL]) then
|
|
||||||
begin
|
|
||||||
TargetSize := S_L;
|
|
||||||
TargetSubReg := R_SUBD;
|
|
||||||
end
|
|
||||||
else if (taicpu(hp1).opsize in [S_W, S_BW]) then
|
|
||||||
begin
|
|
||||||
TargetSize := S_W;
|
|
||||||
TargetSubReg := R_SUBW;
|
|
||||||
end;
|
|
||||||
|
|
||||||
ThisReg := taicpu(hp1).oper[1]^.reg;
|
|
||||||
setsubreg(ThisReg, TargetSubReg);
|
|
||||||
RegChanged := True;
|
|
||||||
|
|
||||||
DebugMsg(SPeepholeOptimization + 'Simplified register usage so ' + debug_regname(ThisReg) + ' = ' + debug_regname(taicpu(p).oper[1]^.reg), p);
|
|
||||||
|
|
||||||
TransferUsedRegs(TmpUsedRegs);
|
|
||||||
AllocRegBetween(ThisReg, p, hp1, TmpUsedRegs);
|
|
||||||
|
|
||||||
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 3', hp1);
|
|
||||||
if p = hp1 then
|
|
||||||
begin
|
|
||||||
RemoveCurrentp(p); { p = hp1 and will then become the next instruction }
|
|
||||||
p_removed := True;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
RemoveInstruction(hp1);
|
|
||||||
|
|
||||||
{ Instruction will become "mov %reg,%reg" }
|
|
||||||
if not p_removed and (taicpu(p).opcode = A_MOV) and
|
|
||||||
MatchOperand(taicpu(p).oper[0]^, ThisReg) then
|
|
||||||
begin
|
|
||||||
DebugMsg(SPeepholeOptimization + 'Movzx2Nop 6', p);
|
|
||||||
RemoveCurrentP(p);
|
|
||||||
p_removed := True;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
taicpu(p).oper[1]^.reg := ThisReg;
|
|
||||||
|
|
||||||
Result := True;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if TargetSize <> MaxSize then
|
|
||||||
begin
|
|
||||||
{ Since the register is in use, we have to force it to
|
|
||||||
MaxSize otherwise part of it may become undefined later on }
|
|
||||||
TargetSize := MaxSize;
|
|
||||||
|
|
||||||
case TargetSize of
|
|
||||||
S_B:
|
|
||||||
TargetSubReg := R_SUBL;
|
|
||||||
S_W:
|
|
||||||
TargetSubReg := R_SUBW;
|
|
||||||
S_L:
|
|
||||||
TargetSubReg := R_SUBD;
|
|
||||||
else
|
|
||||||
InternalError(2020112351);
|
|
||||||
end;
|
|
||||||
|
|
||||||
setsubreg(ThisReg, TargetSubReg);
|
|
||||||
end;
|
|
||||||
|
|
||||||
AdjustFinalLoad;
|
|
||||||
end;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AdjustFinalLoad;
|
|
||||||
|
|
||||||
if not p_removed then
|
|
||||||
begin
|
|
||||||
if TargetSize = MinSize 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 1', p);
|
|
||||||
DebugMsg(SPeepholeOptimization + tostr(InstrMax), p);
|
|
||||||
RemoveCurrentP(p);
|
|
||||||
p_removed := True;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
DebugMsg(SPeepholeOptimization + 'Movzx2Mov 1', p);
|
|
||||||
taicpu(p).opcode := A_MOV;
|
|
||||||
taicpu(p).oper[1]^.reg := ThisReg;
|
|
||||||
taicpu(p).opsize := TargetSize;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result := True;
|
|
||||||
end
|
|
||||||
else if TargetSize <> MaxSize then
|
|
||||||
begin
|
|
||||||
|
|
||||||
case MaxSize of
|
|
||||||
S_L:
|
|
||||||
if TargetSize = S_W then
|
|
||||||
begin
|
|
||||||
DebugMsg(SPeepholeOptimization + 'movzbl2movzbw', p);
|
|
||||||
taicpu(p).opsize := S_BW;
|
|
||||||
taicpu(p).oper[1]^.reg := ThisReg;
|
|
||||||
Result := True;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
InternalError(2020112341);
|
|
||||||
|
|
||||||
S_W:
|
|
||||||
if TargetSize = S_L then
|
|
||||||
begin
|
|
||||||
DebugMsg(SPeepholeOptimization + 'movzbw2movzbl', p);
|
|
||||||
taicpu(p).opsize := S_BL;
|
|
||||||
taicpu(p).oper[1]^.reg := ThisReg;
|
|
||||||
Result := True;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
InternalError(2020112342);
|
|
||||||
else
|
|
||||||
;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Now go through every instruction we found and change the
|
|
||||||
size. If TargetSize = MaxSize, then almost no changes are
|
|
||||||
needed and Result can remain False if it hasn't been set
|
|
||||||
yet.
|
|
||||||
|
|
||||||
If RegChanged is True, then the register requires changing
|
|
||||||
and so the point about TargetSize = MaxSize doesn't apply. }
|
|
||||||
|
|
||||||
if ((TargetSize <> MaxSize) or RegChanged) and (InstrMax >= 0) then
|
|
||||||
begin
|
|
||||||
for Index := 0 to InstrMax do
|
|
||||||
begin
|
|
||||||
|
|
||||||
{ If p_removed is true, then the original MOV/Z was removed
|
|
||||||
and removing the AND instruction may not be safe if it
|
|
||||||
appears first }
|
|
||||||
if (InstrList[Index].oper[InstrList[Index].ops - 1]^.typ <> top_reg) then
|
|
||||||
InternalError(2020112310);
|
|
||||||
|
|
||||||
if InstrList[Index].oper[0]^.typ = top_reg then
|
|
||||||
InstrList[Index].oper[0]^.reg := ThisReg;
|
|
||||||
|
|
||||||
InstrList[Index].oper[InstrList[Index].ops - 1]^.reg := ThisReg;
|
|
||||||
InstrList[Index].opsize := TargetSize;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Result := True;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user