mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 22:32:29 +02:00
* x86: CheckJumpMovTransferOpt now also copies over register deallocations to allow better optimisations
This commit is contained in:
parent
a49c0f6e0c
commit
fb66369a3b
@ -108,6 +108,8 @@ interface
|
||||
ait_eabi_attribute
|
||||
);
|
||||
|
||||
taitypes = set of taitype;
|
||||
|
||||
taiconst_type = (
|
||||
aitconst_128bit,
|
||||
aitconst_64bit,
|
||||
|
@ -60,12 +60,15 @@ unit aoptbase;
|
||||
|
||||
{ gets the next tai object after current that contains info relevant }
|
||||
{ to the optimizer in p1. If there is none, it returns false and }
|
||||
{ sets p1 to nil }
|
||||
class function GetNextInstruction(Current: tai; out Next: tai): Boolean; static;
|
||||
{ sets p1 to nil. If AlsoStopOn is set, it will also stop on these }
|
||||
{ object types that are normally skipped over. }
|
||||
class function GetNextInstruction(Current: tai; out Next: tai; AlsoStopOn: taitypes = []): Boolean; static;
|
||||
|
||||
{ gets the previous tai object after current that contains info }
|
||||
{ relevant to the optimizer in last. If there is none, it returns }
|
||||
{ false and sets last to nil }
|
||||
class function GetLastInstruction(Current: tai; out Last: tai): Boolean; static;
|
||||
{ false and sets last to nil. If AlsoStopOn is set, it will also }
|
||||
{ stop on these object types that are normally skipped over. }
|
||||
class function GetLastInstruction(Current: tai; out Last: tai; AlsoStopOn: taitypes = []): Boolean; static;
|
||||
|
||||
class function SkipEntryExitMarker(current: tai; out next: tai): boolean; static;
|
||||
|
||||
@ -185,12 +188,12 @@ unit aoptbase;
|
||||
end;
|
||||
|
||||
|
||||
class function TAOptBase.GetNextInstruction(Current: tai; out Next: tai): Boolean;
|
||||
class function TAOptBase.GetNextInstruction(Current: tai; out Next: tai; AlsoStopOn: taitypes): Boolean;
|
||||
Begin
|
||||
Repeat
|
||||
Current := tai(Current.Next);
|
||||
While Assigned(Current) And
|
||||
((Current.typ In SkipInstr) or
|
||||
((Current.typ In SkipInstr - AlsoStopOn) or
|
||||
{$ifdef cpudelayslot}
|
||||
((Current.typ=ait_instruction) and
|
||||
(taicpu(Current).opcode=A_NOP)
|
||||
@ -223,7 +226,7 @@ unit aoptbase;
|
||||
(Tai_Marker(Current).Kind <> mark_NoPropInfoEnd);
|
||||
Next := Current;
|
||||
If Assigned(Current) And
|
||||
Not((Current.typ In SkipInstr) or
|
||||
Not((Current.typ In SkipInstr - AlsoStopOn) or
|
||||
((Current.typ = ait_label) And
|
||||
labelCanBeSkipped(Tai_Label(Current))))
|
||||
Then GetNextInstruction := True
|
||||
@ -234,14 +237,15 @@ unit aoptbase;
|
||||
End;
|
||||
End;
|
||||
|
||||
class function TAOptBase.GetLastInstruction(Current: tai; out Last: tai): Boolean;
|
||||
|
||||
class function TAOptBase.GetLastInstruction(Current: tai; out Last: tai; AlsoStopOn: taitypes): Boolean;
|
||||
Begin
|
||||
Repeat
|
||||
Current := Tai(Current.previous);
|
||||
While Assigned(Current) And
|
||||
(((Current.typ = ait_Marker) And
|
||||
Not(Tai_Marker(Current).Kind in [mark_AsmBlockEnd{,mark_NoPropInfoEnd}])) or
|
||||
(Current.typ In SkipInstr) or
|
||||
(Current.typ In SkipInstr - AlsoStopOn) or
|
||||
((Current.typ = ait_label) And
|
||||
labelCanBeSkipped(Tai_Label(Current)))) Do
|
||||
Current := Tai(Current.previous);
|
||||
@ -258,7 +262,7 @@ unit aoptbase;
|
||||
(Current.typ <> ait_Marker) Or
|
||||
not(tai_Marker(current).Kind in [mark_NoPropInfoStart,mark_NoPropInfoEnd]);
|
||||
If Not(Assigned(Current)) or
|
||||
(Current.typ In SkipInstr) or
|
||||
(Current.typ In SkipInstr - AlsoStopOn) or
|
||||
((Current.typ = ait_label) And
|
||||
labelCanBeSkipped(Tai_Label(Current))) or
|
||||
((Current.typ = ait_Marker) And
|
||||
|
@ -9226,104 +9226,121 @@ unit aoptx86;
|
||||
if Assigned(hp1) and (hp1.typ = ait_label) then
|
||||
SkipLabels(hp1,hp1);
|
||||
|
||||
if (hp1.typ <> ait_instruction) then
|
||||
InternalError(2021040720);
|
||||
case hp1.typ of
|
||||
ait_regalloc:
|
||||
if tai_regalloc(hp1).ratype = ra_dealloc then
|
||||
begin
|
||||
{ Duplicate the register deallocation... }
|
||||
hp3:=tai(hp1.getcopy);
|
||||
if first_assignment = nil then
|
||||
first_assignment := hp3;
|
||||
|
||||
case taicpu(hp1).opcode of
|
||||
A_JMP:
|
||||
begin
|
||||
{ Change the original jump to the new destination }
|
||||
OrigLabel.decrefs;
|
||||
taicpu(hp1).oper[0]^.ref^.symbol.increfs;
|
||||
taicpu(p).loadref(0, taicpu(hp1).oper[0]^.ref^);
|
||||
asml.InsertBefore(hp3, p);
|
||||
|
||||
{ Set p to the first duplicated assignment so it can get optimised if needs be }
|
||||
if not Assigned(first_assignment) then
|
||||
InternalError(2021040810)
|
||||
{ ... but also reallocate it after the jump }
|
||||
hp3:=tai(hp1.getcopy);
|
||||
tai_regalloc(hp3).ratype := ra_alloc;
|
||||
|
||||
asml.InsertAfter(hp3, p);
|
||||
end;
|
||||
ait_instruction:
|
||||
case taicpu(hp1).opcode of
|
||||
A_JMP:
|
||||
begin
|
||||
{ Change the original jump to the new destination }
|
||||
OrigLabel.decrefs;
|
||||
taicpu(hp1).oper[0]^.ref^.symbol.increfs;
|
||||
taicpu(p).loadref(0, taicpu(hp1).oper[0]^.ref^);
|
||||
|
||||
{ Set p to the first duplicated assignment so it can get optimised if needs be }
|
||||
if not Assigned(first_assignment) then
|
||||
InternalError(2021040810)
|
||||
else
|
||||
p := first_assignment;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
A_RET:
|
||||
begin
|
||||
{ Now change the jump into a RET instruction }
|
||||
ConvertJumpToRET(p, hp1);
|
||||
|
||||
{ Set p to the first duplicated assignment so it can get optimised if needs be }
|
||||
if not Assigned(first_assignment) then
|
||||
InternalError(2021040811)
|
||||
else
|
||||
p := first_assignment;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
else
|
||||
p := first_assignment;
|
||||
begin
|
||||
{ Duplicate the MOV instruction }
|
||||
hp3:=tai(hp1.getcopy);
|
||||
if first_assignment = nil then
|
||||
first_assignment := hp3;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
A_RET:
|
||||
begin
|
||||
{ Now change the jump into a RET instruction }
|
||||
ConvertJumpToRET(p, hp1);
|
||||
asml.InsertBefore(hp3, p);
|
||||
|
||||
{ Set p to the first duplicated assignment so it can get optimised if needs be }
|
||||
if not Assigned(first_assignment) then
|
||||
InternalError(2021040811)
|
||||
else
|
||||
p := first_assignment;
|
||||
|
||||
Exit;
|
||||
{ Make sure the compiler knows about any final registers written here }
|
||||
for OperIdx := 0 to taicpu(hp3).ops - 1 do
|
||||
with taicpu(hp3).oper[OperIdx]^ do
|
||||
begin
|
||||
case typ of
|
||||
top_ref:
|
||||
begin
|
||||
if (ref^.base <> NR_NO) and
|
||||
(getsupreg(ref^.base) <> RS_STACK_POINTER_REG) and
|
||||
(
|
||||
(getsupreg(ref^.base) <> RS_FRAME_POINTER_REG) or
|
||||
(
|
||||
{ Allow the frame pointer if it's not being used by the procedure as such }
|
||||
Assigned(current_procinfo) and
|
||||
(current_procinfo.framepointer <> NR_FRAME_POINTER_REG)
|
||||
)
|
||||
)
|
||||
{$ifdef x86_64} and (ref^.base <> NR_RIP) {$endif x86_64}
|
||||
then
|
||||
begin
|
||||
AllocRegBetween(ref^.base, hp3, p, TmpUsedRegs);
|
||||
if not Assigned(first_assignment) then
|
||||
IncludeRegInUsedRegs(ref^.base, UsedRegs);
|
||||
end;
|
||||
if (ref^.index <> NR_NO) and
|
||||
(getsupreg(ref^.index) <> RS_STACK_POINTER_REG) and
|
||||
(
|
||||
(getsupreg(ref^.index) <> RS_FRAME_POINTER_REG) or
|
||||
(
|
||||
{ Allow the frame pointer if it's not being used by the procedure as such }
|
||||
Assigned(current_procinfo) and
|
||||
(current_procinfo.framepointer <> NR_FRAME_POINTER_REG)
|
||||
)
|
||||
)
|
||||
{$ifdef x86_64} and (ref^.index <> NR_RIP) {$endif x86_64} and
|
||||
(ref^.index <> ref^.base) then
|
||||
begin
|
||||
AllocRegBetween(ref^.index, hp3, p, TmpUsedRegs);
|
||||
if not Assigned(first_assignment) then
|
||||
IncludeRegInUsedRegs(ref^.index, UsedRegs);
|
||||
end;
|
||||
end;
|
||||
top_reg:
|
||||
begin
|
||||
AllocRegBetween(reg, hp3, p, TmpUsedRegs);
|
||||
if not Assigned(first_assignment) then
|
||||
IncludeRegInUsedRegs(reg, UsedRegs);
|
||||
end;
|
||||
else
|
||||
;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
{ Duplicate the MOV instruction }
|
||||
hp3:=tai(hp1.getcopy);
|
||||
|
||||
asml.InsertBefore(hp3, p);
|
||||
|
||||
{ Make sure the compiler knows about any final registers written here }
|
||||
for OperIdx := 0 to taicpu(hp3).ops - 1 do
|
||||
with taicpu(hp3).oper[OperIdx]^ do
|
||||
begin
|
||||
case typ of
|
||||
top_ref:
|
||||
begin
|
||||
if (ref^.base <> NR_NO) and
|
||||
(getsupreg(ref^.base) <> RS_STACK_POINTER_REG) and
|
||||
(
|
||||
(getsupreg(ref^.base) <> RS_FRAME_POINTER_REG) or
|
||||
(
|
||||
{ Allow the frame pointer if it's not being used by the procedure as such }
|
||||
Assigned(current_procinfo) and
|
||||
(current_procinfo.framepointer <> NR_FRAME_POINTER_REG)
|
||||
)
|
||||
)
|
||||
{$ifdef x86_64} and (ref^.base <> NR_RIP) {$endif x86_64}
|
||||
then
|
||||
begin
|
||||
AllocRegBetween(ref^.base, hp3, p, TmpUsedRegs);
|
||||
if not Assigned(first_assignment) then
|
||||
IncludeRegInUsedRegs(ref^.base, UsedRegs);
|
||||
end;
|
||||
if (ref^.index <> NR_NO) and
|
||||
(getsupreg(ref^.index) <> RS_STACK_POINTER_REG) and
|
||||
(
|
||||
(getsupreg(ref^.index) <> RS_FRAME_POINTER_REG) or
|
||||
(
|
||||
{ Allow the frame pointer if it's not being used by the procedure as such }
|
||||
Assigned(current_procinfo) and
|
||||
(current_procinfo.framepointer <> NR_FRAME_POINTER_REG)
|
||||
)
|
||||
)
|
||||
{$ifdef x86_64} and (ref^.index <> NR_RIP) {$endif x86_64} and
|
||||
(ref^.index <> ref^.base) then
|
||||
begin
|
||||
AllocRegBetween(ref^.index, hp3, p, TmpUsedRegs);
|
||||
if not Assigned(first_assignment) then
|
||||
IncludeRegInUsedRegs(ref^.index, UsedRegs);
|
||||
end;
|
||||
end;
|
||||
top_reg:
|
||||
begin
|
||||
AllocRegBetween(reg, hp3, p, TmpUsedRegs);
|
||||
if not Assigned(first_assignment) then
|
||||
IncludeRegInUsedRegs(reg, UsedRegs);
|
||||
end;
|
||||
else
|
||||
;
|
||||
end;
|
||||
end;
|
||||
|
||||
if first_assignment = nil then
|
||||
first_assignment := hp3;
|
||||
end;
|
||||
InternalError(2021040720);
|
||||
end;
|
||||
|
||||
if not GetNextInstruction(hp1, hp1) then
|
||||
if not GetNextInstruction(hp1, hp1, [ait_regalloc]) then
|
||||
{ Should have dropped out earlier }
|
||||
InternalError(2021040710);
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user