mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 19:29:26 +02:00
+ generic TAOptObj.AllocRegBetween
- removed x86 specific AllocRegBetween git-svn-id: trunk@38445 -
This commit is contained in:
parent
6e79c8ba86
commit
78878f59b1
@ -315,6 +315,10 @@ Unit AoptObj;
|
||||
nil }
|
||||
Function FindRegDeAlloc(Reg: TRegister; StartPai: Tai): tai_regalloc;
|
||||
|
||||
{ allocates register reg between (and including) instructions p1 and p2
|
||||
the type of p1 and p2 must not be in SkipInstr }
|
||||
procedure AllocRegBetween(reg : tregister; p1,p2 : tai; var initialusedregs : TAllUsedRegs);
|
||||
|
||||
{ reg used after p? }
|
||||
function RegUsedAfterInstruction(reg: Tregister; p: tai; var AllUsedRegs: TAllUsedRegs): Boolean;
|
||||
|
||||
@ -370,7 +374,8 @@ Unit AoptObj;
|
||||
cutils,
|
||||
globals,
|
||||
verbose,
|
||||
aoptutils;
|
||||
aoptutils,
|
||||
procinfo;
|
||||
|
||||
|
||||
function JumpTargetOp(ai: taicpu): poper; inline;
|
||||
@ -1146,6 +1151,120 @@ Unit AoptObj;
|
||||
End;
|
||||
|
||||
|
||||
{ allocates register reg between (and including) instructions p1 and p2
|
||||
the type of p1 and p2 must not be in SkipInstr }
|
||||
procedure TAOptObj.AllocRegBetween(reg: tregister; p1, p2: tai; var initialusedregs: TAllUsedRegs);
|
||||
var
|
||||
hp, start: tai;
|
||||
removedsomething,
|
||||
firstRemovedWasAlloc,
|
||||
lastRemovedWasDealloc: boolean;
|
||||
begin
|
||||
{$ifdef EXTDEBUG}
|
||||
{ if assigned(p1.optinfo) and
|
||||
(ptaiprop(p1.optinfo)^.usedregs <> initialusedregs) then
|
||||
internalerror(2004101010); }
|
||||
{$endif EXTDEBUG}
|
||||
start := p1;
|
||||
if (reg = NR_STACK_POINTER_REG) or
|
||||
(reg = current_procinfo.framepointer) or
|
||||
not(assigned(p1)) then
|
||||
{ this happens with registers which are loaded implicitely, outside the }
|
||||
{ current block (e.g. esi with self) }
|
||||
exit;
|
||||
{ make sure we allocate it for this instruction }
|
||||
getnextinstruction(p2,p2);
|
||||
lastRemovedWasDealloc := false;
|
||||
removedSomething := false;
|
||||
firstRemovedWasAlloc := false;
|
||||
{$ifdef allocregdebug}
|
||||
hp := tai_comment.Create(strpnew('allocating '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
|
||||
' from here...'));
|
||||
insertllitem(asml,p1.previous,p1,hp);
|
||||
hp := tai_comment.Create(strpnew('allocated '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
|
||||
' till here...'));
|
||||
insertllitem(asml,p2,p2.next,hp);
|
||||
{$endif allocregdebug}
|
||||
{ do it the safe way: always allocate the full super register,
|
||||
as we do no register re-allocation in the peephole optimizer,
|
||||
this does not hurt
|
||||
}
|
||||
case getregtype(reg) of
|
||||
R_MMREGISTER:
|
||||
reg:=newreg(R_MMREGISTER,getsupreg(reg),R_SUBMMWHOLE);
|
||||
R_INTREGISTER:
|
||||
reg:=newreg(R_INTREGISTER,getsupreg(reg),R_SUBWHOLE);
|
||||
R_FPUREGISTER:
|
||||
reg:=newreg(R_FPUREGISTER,getsupreg(reg),R_SUBWHOLE);
|
||||
R_ADDRESSREGISTER:
|
||||
reg:=newreg(R_ADDRESSREGISTER,getsupreg(reg),R_SUBWHOLE);
|
||||
else
|
||||
Internalerror(2018030701);
|
||||
end;
|
||||
if not(RegInUsedRegs(reg,initialusedregs)) then
|
||||
begin
|
||||
hp := tai_regalloc.alloc(reg,nil);
|
||||
insertllItem(p1.previous,p1,hp);
|
||||
IncludeRegInUsedRegs(reg,initialusedregs);
|
||||
end;
|
||||
while assigned(p1) and
|
||||
(p1 <> p2) do
|
||||
begin
|
||||
if assigned(p1.optinfo) then
|
||||
internalerror(2014022301); // IncludeRegInUsedRegs(reg,ptaiprop(p1.optinfo)^.usedregs);
|
||||
p1 := tai(p1.next);
|
||||
repeat
|
||||
while assigned(p1) and
|
||||
(p1.typ in (SkipInstr-[ait_regalloc])) Do
|
||||
p1 := tai(p1.next);
|
||||
|
||||
{ remove all allocation/deallocation info about the register in between }
|
||||
if assigned(p1) and
|
||||
(p1.typ = ait_regalloc) then
|
||||
begin
|
||||
{ same super register, different sub register? }
|
||||
if SuperRegistersEqual(reg,tai_regalloc(p1).reg) and (tai_regalloc(p1).reg<>reg) then
|
||||
begin
|
||||
if (getsubreg(tai_regalloc(p1).reg)>getsubreg(reg)) or (getsubreg(reg)=R_SUBH) then
|
||||
internalerror(2016101501);
|
||||
tai_regalloc(p1).reg:=reg;
|
||||
end;
|
||||
|
||||
if tai_regalloc(p1).reg=reg then
|
||||
begin
|
||||
if not removedSomething then
|
||||
begin
|
||||
firstRemovedWasAlloc := tai_regalloc(p1).ratype=ra_alloc;
|
||||
removedSomething := true;
|
||||
end;
|
||||
lastRemovedWasDealloc := (tai_regalloc(p1).ratype=ra_dealloc);
|
||||
hp := tai(p1.Next);
|
||||
asml.Remove(p1);
|
||||
p1.free;
|
||||
p1 := hp;
|
||||
end
|
||||
else
|
||||
p1 := tai(p1.next);
|
||||
end;
|
||||
until not(assigned(p1)) or
|
||||
not(p1.typ in SkipInstr);
|
||||
end;
|
||||
if assigned(p1) then
|
||||
begin
|
||||
if firstRemovedWasAlloc then
|
||||
begin
|
||||
hp := tai_regalloc.Alloc(reg,nil);
|
||||
insertLLItem(start.previous,start,hp);
|
||||
end;
|
||||
if lastRemovedWasDealloc then
|
||||
begin
|
||||
hp := tai_regalloc.DeAlloc(reg,nil);
|
||||
insertLLItem(p1.previous,p1,hp);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TAOptObj.RegUsedAfterInstruction(reg: Tregister; p: tai;var AllUsedRegs: TAllUsedRegs): Boolean;
|
||||
begin
|
||||
AllUsedRegs[getregtype(reg)].Update(tai(p.Next),true);
|
||||
|
@ -50,7 +50,6 @@ unit aoptx86;
|
||||
|
||||
procedure DebugMsg(const s : string; p : tai);inline;
|
||||
|
||||
procedure AllocRegBetween(reg : tregister; p1,p2 : tai;var initialusedregs : TAllUsedRegs);
|
||||
class function IsExitCode(p : tai) : boolean;
|
||||
class function isFoldableArithOp(hp1 : taicpu; reg : tregister) : boolean;
|
||||
procedure RemoveLastDeallocForFuncRes(p : tai);
|
||||
@ -609,116 +608,6 @@ unit aoptx86;
|
||||
end;
|
||||
|
||||
|
||||
{ allocates register reg between (and including) instructions p1 and p2
|
||||
the type of p1 and p2 must not be in SkipInstr
|
||||
note that this routine is both called from the peephole optimizer
|
||||
where optinfo is not yet initialised) and from the cse (where it is) }
|
||||
procedure TX86AsmOptimizer.AllocRegBetween(reg: tregister; p1, p2: tai; var initialusedregs: TAllUsedRegs);
|
||||
var
|
||||
hp, start: tai;
|
||||
removedsomething,
|
||||
firstRemovedWasAlloc,
|
||||
lastRemovedWasDealloc: boolean;
|
||||
begin
|
||||
{$ifdef EXTDEBUG}
|
||||
{ if assigned(p1.optinfo) and
|
||||
(ptaiprop(p1.optinfo)^.usedregs <> initialusedregs) then
|
||||
internalerror(2004101010); }
|
||||
{$endif EXTDEBUG}
|
||||
start := p1;
|
||||
if (reg = NR_ESP) or
|
||||
(reg = current_procinfo.framepointer) or
|
||||
not(assigned(p1)) then
|
||||
{ this happens with registers which are loaded implicitely, outside the }
|
||||
{ current block (e.g. esi with self) }
|
||||
exit;
|
||||
{ make sure we allocate it for this instruction }
|
||||
getnextinstruction(p2,p2);
|
||||
lastRemovedWasDealloc := false;
|
||||
removedSomething := false;
|
||||
firstRemovedWasAlloc := false;
|
||||
{$ifdef allocregdebug}
|
||||
hp := tai_comment.Create(strpnew('allocating '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
|
||||
' from here...'));
|
||||
insertllitem(asml,p1.previous,p1,hp);
|
||||
hp := tai_comment.Create(strpnew('allocated '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+
|
||||
' till here...'));
|
||||
insertllitem(asml,p2,p2.next,hp);
|
||||
{$endif allocregdebug}
|
||||
{ do it the safe way: always allocate the full super register,
|
||||
as we do no register re-allocation in the peephole optimizer,
|
||||
this does not hurt
|
||||
}
|
||||
case getregtype(reg) of
|
||||
R_MMREGISTER:
|
||||
reg:=newreg(R_MMREGISTER,getsupreg(reg),R_SUBMMWHOLE);
|
||||
R_INTREGISTER:
|
||||
reg:=newreg(R_INTREGISTER,getsupreg(reg),R_SUBWHOLE);
|
||||
end;
|
||||
if not(RegInUsedRegs(reg,initialusedregs)) then
|
||||
begin
|
||||
hp := tai_regalloc.alloc(reg,nil);
|
||||
insertllItem(p1.previous,p1,hp);
|
||||
IncludeRegInUsedRegs(reg,initialusedregs);
|
||||
end;
|
||||
while assigned(p1) and
|
||||
(p1 <> p2) do
|
||||
begin
|
||||
if assigned(p1.optinfo) then
|
||||
internalerror(2014022301); // IncludeRegInUsedRegs(reg,ptaiprop(p1.optinfo)^.usedregs);
|
||||
p1 := tai(p1.next);
|
||||
repeat
|
||||
while assigned(p1) and
|
||||
(p1.typ in (SkipInstr-[ait_regalloc])) Do
|
||||
p1 := tai(p1.next);
|
||||
|
||||
{ remove all allocation/deallocation info about the register in between }
|
||||
if assigned(p1) and
|
||||
(p1.typ = ait_regalloc) then
|
||||
begin
|
||||
{ same super register, different sub register? }
|
||||
if SuperRegistersEqual(reg,tai_regalloc(p1).reg) and (tai_regalloc(p1).reg<>reg) then
|
||||
begin
|
||||
if (getsubreg(tai_regalloc(p1).reg)>getsubreg(reg)) or (getsubreg(reg)=R_SUBH) then
|
||||
internalerror(2016101501);
|
||||
tai_regalloc(p1).reg:=reg;
|
||||
end;
|
||||
|
||||
if tai_regalloc(p1).reg=reg then
|
||||
begin
|
||||
if not removedSomething then
|
||||
begin
|
||||
firstRemovedWasAlloc := tai_regalloc(p1).ratype=ra_alloc;
|
||||
removedSomething := true;
|
||||
end;
|
||||
lastRemovedWasDealloc := (tai_regalloc(p1).ratype=ra_dealloc);
|
||||
hp := tai(p1.Next);
|
||||
asml.Remove(p1);
|
||||
p1.free;
|
||||
p1 := hp;
|
||||
end
|
||||
else
|
||||
p1 := tai(p1.next);
|
||||
end;
|
||||
until not(assigned(p1)) or
|
||||
not(p1.typ in SkipInstr);
|
||||
end;
|
||||
if assigned(p1) then
|
||||
begin
|
||||
if firstRemovedWasAlloc then
|
||||
begin
|
||||
hp := tai_regalloc.Alloc(reg,nil);
|
||||
insertLLItem(start.previous,start,hp);
|
||||
end;
|
||||
if lastRemovedWasDealloc then
|
||||
begin
|
||||
hp := tai_regalloc.DeAlloc(reg,nil);
|
||||
insertLLItem(p1.previous,p1,hp);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TX86AsmOptimizer.RegLoadedWithNewValue(reg: tregister; hp: tai): boolean;
|
||||
var
|
||||
p: taicpu;
|
||||
|
Loading…
Reference in New Issue
Block a user