|
@@ -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);
|