|
@@ -15564,6 +15564,7 @@ unit aoptx86;
|
|
NewRef: TReference;
|
|
NewRef: TReference;
|
|
Distance: Cardinal;
|
|
Distance: Cardinal;
|
|
TempTracking: TAllUsedRegs;
|
|
TempTracking: TAllUsedRegs;
|
|
|
|
+ DoAddMov2Lea: Boolean;
|
|
|
|
|
|
{ This entire nested function is used in an if-statement below, but we
|
|
{ This entire nested function is used in an if-statement below, but we
|
|
want to avoid all the used reg transfers and GetNextInstruction calls
|
|
want to avoid all the used reg transfers and GetNextInstruction calls
|
|
@@ -15573,10 +15574,11 @@ unit aoptx86;
|
|
hp2: tai;
|
|
hp2: tai;
|
|
begin
|
|
begin
|
|
TransferUsedRegs(TmpUsedRegs);
|
|
TransferUsedRegs(TmpUsedRegs);
|
|
- hp2 := p;
|
|
|
|
- repeat
|
|
|
|
- UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next));
|
|
|
|
- until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1);
|
|
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ UpdateUsedRegsBetween(TmpUsedRegs, p, hp1)
|
|
|
|
+ else
|
|
|
|
+ { p and hp1 will be adjacent }
|
|
|
|
+ UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
|
|
|
|
|
Result := not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs);
|
|
Result := not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs);
|
|
end;
|
|
end;
|
|
@@ -15625,11 +15627,13 @@ unit aoptx86;
|
|
begin
|
|
begin
|
|
{ Update the register tracking to the MOV instruction }
|
|
{ Update the register tracking to the MOV instruction }
|
|
CopyUsedRegs(TempTracking);
|
|
CopyUsedRegs(TempTracking);
|
|
- hp2 := p;
|
|
|
|
- repeat
|
|
|
|
- UpdateUsedRegs(tai(hp2.Next));
|
|
|
|
- until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1);
|
|
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ UpdateUsedRegsBetween(UsedRegs, p, hp1)
|
|
|
|
+ else
|
|
|
|
+ { p and hp1 will be adjacent }
|
|
|
|
+ UpdateUsedRegs(UsedRegs, tai(p.Next));
|
|
|
|
|
|
|
|
+ hp2 := hp1;
|
|
{ if hp1 <> hp2 after the call, then hp1 got removed, so let
|
|
{ if hp1 <> hp2 after the call, then hp1 got removed, so let
|
|
OptPass2ADD get called again }
|
|
OptPass2ADD get called again }
|
|
if OptPass2MOV(hp1) and (hp1 <> hp2) then
|
|
if OptPass2MOV(hp1) and (hp1 <> hp2) then
|
|
@@ -15750,18 +15754,22 @@ unit aoptx86;
|
|
) then
|
|
) then
|
|
begin
|
|
begin
|
|
TransferUsedRegs(TmpUsedRegs);
|
|
TransferUsedRegs(TmpUsedRegs);
|
|
- hp2 := p;
|
|
|
|
- repeat
|
|
|
|
- UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next));
|
|
|
|
- until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1);
|
|
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ UpdateUsedRegsBetween(TmpUsedRegs, p, hp1)
|
|
|
|
+ else
|
|
|
|
+ { p and hp1 will be adjacent }
|
|
|
|
+ UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
|
|
|
|
|
if (
|
|
if (
|
|
|
|
+ SetAndTest(
|
|
|
|
+ (
|
|
|
|
+ not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and
|
|
|
|
+ not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs)
|
|
|
|
+ ),
|
|
|
|
+ DoAddMov2Lea
|
|
|
|
+ ) or
|
|
{ Don't do AddMov2LeaAdd under -Os, but do allow AddMov2Lea }
|
|
{ Don't do AddMov2LeaAdd under -Os, but do allow AddMov2Lea }
|
|
- not (cs_opt_size in current_settings.optimizerswitches) or
|
|
|
|
- (
|
|
|
|
- not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and
|
|
|
|
- not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs)
|
|
|
|
- )
|
|
|
|
|
|
+ not (cs_opt_size in current_settings.optimizerswitches)
|
|
) then
|
|
) then
|
|
begin
|
|
begin
|
|
{ Change the MOV instruction to a LEA instruction, and update the
|
|
{ Change the MOV instruction to a LEA instruction, and update the
|
|
@@ -15775,8 +15783,18 @@ unit aoptx86;
|
|
taicpu(hp1).opcode := A_LEA;
|
|
taicpu(hp1).opcode := A_LEA;
|
|
taicpu(hp1).loadref(0, NewRef);
|
|
taicpu(hp1).loadref(0, NewRef);
|
|
|
|
|
|
- if RegUsedAfterInstruction(NewRef.base, hp1, TmpUsedRegs) or
|
|
|
|
- RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) then
|
|
|
|
|
|
+ if DoAddMov2Lea then
|
|
|
|
+ begin
|
|
|
|
+ { Since %reg1 or the flags aren't used afterwards, we can delete p completely }
|
|
|
|
+ DebugMsg(SPeepholeOptimization + 'AddMov2Lea', hp1);
|
|
|
|
+
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ { hp1 may not be the immediate next instruction under -O3 }
|
|
|
|
+ RemoveCurrentp(p)
|
|
|
|
+ else
|
|
|
|
+ RemoveCurrentp(p, hp1);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
begin
|
|
begin
|
|
hp2 := tai(hp1.Next); { for the benefit of AllocRegBetween }
|
|
hp2 := tai(hp1.Next); { for the benefit of AllocRegBetween }
|
|
|
|
|
|
@@ -15787,17 +15805,6 @@ unit aoptx86;
|
|
|
|
|
|
DebugMsg(SPeepholeOptimization + 'AddMov2LeaAdd', p);
|
|
DebugMsg(SPeepholeOptimization + 'AddMov2LeaAdd', p);
|
|
p := hp1;
|
|
p := hp1;
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- { Since %reg1 or the flags aren't used afterwards, we can delete p completely }
|
|
|
|
- DebugMsg(SPeepholeOptimization + 'AddMov2Lea', hp1);
|
|
|
|
-
|
|
|
|
- if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
- { hp1 may not be the immediate next instruction under -O3 }
|
|
|
|
- RemoveCurrentp(p)
|
|
|
|
- else
|
|
|
|
- RemoveCurrentp(p, hp1);
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
Result := True;
|
|
Result := True;
|
|
@@ -15923,6 +15930,7 @@ unit aoptx86;
|
|
NewRef: TReference;
|
|
NewRef: TReference;
|
|
Distance: Cardinal;
|
|
Distance: Cardinal;
|
|
TempTracking: TAllUsedRegs;
|
|
TempTracking: TAllUsedRegs;
|
|
|
|
+ DoSubMov2Lea: Boolean;
|
|
|
|
|
|
begin
|
|
begin
|
|
Result := False;
|
|
Result := False;
|
|
@@ -15968,11 +15976,13 @@ unit aoptx86;
|
|
begin
|
|
begin
|
|
{ Update the register tracking to the MOV instruction }
|
|
{ Update the register tracking to the MOV instruction }
|
|
CopyUsedRegs(TempTracking);
|
|
CopyUsedRegs(TempTracking);
|
|
- hp2 := p;
|
|
|
|
- repeat
|
|
|
|
- UpdateUsedRegs(tai(hp2.Next));
|
|
|
|
- until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1);
|
|
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ UpdateUsedRegsBetween(UsedRegs, p, hp1)
|
|
|
|
+ else
|
|
|
|
+ { p and hp1 will be adjacent }
|
|
|
|
+ UpdateUsedRegs(UsedRegs, tai(p.Next));
|
|
|
|
|
|
|
|
+ hp2 := hp1;
|
|
{ if hp1 <> hp2 after the call, then hp1 got removed, so let
|
|
{ if hp1 <> hp2 after the call, then hp1 got removed, so let
|
|
OptPass2SUB get called again }
|
|
OptPass2SUB get called again }
|
|
if OptPass2MOV(hp1) and (hp1 <> hp2) then
|
|
if OptPass2MOV(hp1) and (hp1 <> hp2) then
|
|
@@ -16023,18 +16033,22 @@ unit aoptx86;
|
|
) then
|
|
) then
|
|
begin
|
|
begin
|
|
TransferUsedRegs(TmpUsedRegs);
|
|
TransferUsedRegs(TmpUsedRegs);
|
|
- hp2 := p;
|
|
|
|
- repeat
|
|
|
|
- UpdateUsedRegs(TmpUsedRegs, tai(hp2.Next));
|
|
|
|
- until not (cs_opt_level3 in current_settings.optimizerswitches) or not GetNextInstruction(hp2, hp2) or (hp2 = hp1);
|
|
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ UpdateUsedRegsBetween(TmpUsedRegs, p, hp1)
|
|
|
|
+ else
|
|
|
|
+ { p and hp1 will be adjacent }
|
|
|
|
+ UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
|
|
|
|
|
if (
|
|
if (
|
|
|
|
+ SetAndTest(
|
|
|
|
+ (
|
|
|
|
+ not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and
|
|
|
|
+ not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs)
|
|
|
|
+ ),
|
|
|
|
+ DoSubMov2Lea
|
|
|
|
+ ) or
|
|
{ Don't do SubMov2LeaSub under -Os, but do allow SubMov2Lea }
|
|
{ Don't do SubMov2LeaSub under -Os, but do allow SubMov2Lea }
|
|
- not (cs_opt_size in current_settings.optimizerswitches) or
|
|
|
|
- (
|
|
|
|
- not RegUsedAfterInstruction(taicpu(p).oper[1]^.reg, hp1, TmpUsedRegs) and
|
|
|
|
- not RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs)
|
|
|
|
- )
|
|
|
|
|
|
+ not (cs_opt_size in current_settings.optimizerswitches)
|
|
) then
|
|
) then
|
|
begin
|
|
begin
|
|
{ Change the MOV instruction to a LEA instruction, and update the
|
|
{ Change the MOV instruction to a LEA instruction, and update the
|
|
@@ -16047,10 +16061,18 @@ unit aoptx86;
|
|
taicpu(hp1).opcode := A_LEA;
|
|
taicpu(hp1).opcode := A_LEA;
|
|
taicpu(hp1).loadref(0, NewRef);
|
|
taicpu(hp1).loadref(0, NewRef);
|
|
|
|
|
|
- TransferUsedRegs(TmpUsedRegs);
|
|
|
|
- UpdateUsedRegs(TmpUsedRegs, tai(p.Next));
|
|
|
|
- if RegUsedAfterInstruction(NewRef.base, hp1, TmpUsedRegs) or
|
|
|
|
- RegUsedAfterInstruction(NR_DEFAULTFLAGS, hp1, TmpUsedRegs) then
|
|
|
|
|
|
+ if DoSubMov2Lea then
|
|
|
|
+ begin
|
|
|
|
+ { Since %reg1 or the flags aren't used afterwards, we can delete p completely }
|
|
|
|
+ DebugMsg(SPeepholeOptimization + 'SubMov2Lea', hp1);
|
|
|
|
+
|
|
|
|
+ if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
+ { hp1 may not be the immediate next instruction under -O3 }
|
|
|
|
+ RemoveCurrentp(p)
|
|
|
|
+ else
|
|
|
|
+ RemoveCurrentp(p, hp1);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
begin
|
|
begin
|
|
hp2 := tai(hp1.Next); { for the benefit of AllocRegBetween }
|
|
hp2 := tai(hp1.Next); { for the benefit of AllocRegBetween }
|
|
|
|
|
|
@@ -16061,17 +16083,6 @@ unit aoptx86;
|
|
|
|
|
|
DebugMsg(SPeepholeOptimization + 'SubMov2LeaSub', p);
|
|
DebugMsg(SPeepholeOptimization + 'SubMov2LeaSub', p);
|
|
p := hp1;
|
|
p := hp1;
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- { Since %reg1 or the flags aren't used afterwards, we can delete p completely }
|
|
|
|
- DebugMsg(SPeepholeOptimization + 'SubMov2Lea', hp1);
|
|
|
|
-
|
|
|
|
- if (cs_opt_level3 in current_settings.optimizerswitches) then
|
|
|
|
- { hp1 may not be the immediate next instruction under -O3 }
|
|
|
|
- RemoveCurrentp(p)
|
|
|
|
- else
|
|
|
|
- RemoveCurrentp(p, hp1);
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
Result := True;
|
|
Result := True;
|