+ much improved CSE: the CSE now searches further back for sequences it

can reuse. After I've also implemented register renaming, the effect
    should be even better (afaik web bug #1088 will then even be optimized
    properly). I don't know about the slow down factor this adds. Maybe
    a new optimization level should be introduced?
This commit is contained in:
Jonas Maebe 2000-09-20 15:00:58 +00:00
parent 31f57d1429
commit 3df81628bc
2 changed files with 433 additions and 88 deletions

View File

@ -34,7 +34,8 @@ Procedure CSE(AsmL: PAasmOutput; First, Last: Pai);
Implementation
Uses
CObjects, verbose, hcodegen, globals,cpubase,cpuasm,DAOpt386, tgeni386;
{$ifdef replaceregdebug}cutils,{$endif}
verbose, hcodegen, globals,cpubase,cpuasm,DAOpt386, tgeni386;
{
Function PaiInSequence(P: Pai; Const Seq: TContent): Boolean;
@ -56,14 +57,153 @@ Begin
End;
}
Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint; Var RegInfo: TRegInfo): Boolean;
function modifiesMemLocation(p1: pai): boolean;
var p: paicpu;
opCount: byte;
begin
modifiesMemLocation := false;
if p1^.typ <> ait_instruction then
exit;
p := paicpu(p1);
for opCount := 1 to MaxCh do
case InsProp[p^.opcode].Ch[opCount] of
Ch_MOp1,CH_WOp1,CH_RWOp1:
if p^.oper[0].typ = top_ref then
begin
modifiesMemLocation := true;
exit
end;
Ch_MOp2,CH_WOp2,CH_RWOp2:
if p^.oper[1].typ = top_ref then
begin
modifiesMemLocation := true;
exit
end;
Ch_MOp3,CH_WOp3,CH_RWOp3:
if p^.oper[2].typ = top_ref then
begin
modifiesMemLocation := true;
exit
end;
Ch_WMemEDI:
begin
modifiesMemLocation := true;
exit;
end;
end;
end;
function getPrevSequence(reg: tregister; current: pai; var prev: pai; var passedJump: boolean):
tregister;
function stillValid(p: pai): boolean;
begin
stillValid :=
(p^.typ = ait_instruction) and
(paicpu(p)^.opcode <> a_jmp) and
(ppaiprop(p^.optinfo)^.regs[reg].state =
ppaiprop(current^.optinfo)^.regs[reg].state) and
{ in case destroyreg is called with doIncState = false }
(ppaiprop(p^.optinfo)^.regs[reg].typ =
ppaiprop(current^.optinfo)^.regs[reg].typ);
passedJump :=
(p^.typ = ait_instruction) and
(paicpu(p)^.is_jmp);
end;
function findChangedRegister(p: pai): tregister;
var
regCounter: tregister;
begin
for regCounter := R_EAX to R_EDI do
with ppaiprop(p^.optinfo)^.regs[regCounter] do
if ((startmod <>
ppaiprop(current^.optinfo)^.regs[regCounter].startmod) or
(nrOfMods <>
ppaiprop(current^.optinfo)^.regs[regCounter].nrOfMods)) and
(not ppaiprop(p^.optinfo)^.canBeRemoved) and
(ppaiprop(p^.optinfo)^.regs[regCounter].typ in
[con_ref,con_noRemoveRef]) then
begin
findChangedRegister := regCounter;
exit;
end;
findChangedRegister := R_NO;
end;
var
hp, prevFound: pai;
tmpResult: tregister;
begin
getPrevSequence := R_NO;
{ no memory writes (could be refined further) }
if modifiesMemLocation(current) or
not getLastInstruction(current,hp) then
exit;
tmpResult := R_NO;
while (tmpResult = R_NO) and
stillValid(hp) do
begin
{ in case getPreviousInstruction fails and sets hp to nil in the }
{ next iteration }
prevFound := hp;
tmpResult := findChangedRegister(hp);
if modifiesMemLocation(hp) or
{ do not load the self pointer or a regvar before a (conditional) }
{ jump with a new value, since if the jump is taken, the old value }
{ is (probably) still necessary }
(passedJump and not(reg in (usableregs+[R_EDI]))) or
not getLastInstruction(hp,hp) then
break;
end;
getPrevSequence := tmpResult;
if tmpResult <> R_NO then
prev := prevFound;
end;
{checks whether the current instruction sequence (starting with p) and the
one between StartMod and EndMod of Reg are the same. If so, the number of
instructions that match is stored in Found and true is returned, otherwise
Found holds the number of instructions between StartMod and EndMod and false
is returned}
Var hp2, hp3{, EndMod}: Pai;
PrevNonRemovablePai: Pai;
Function CheckSequence(p: Pai; var prev: pai; Reg: TRegister; Var Found: Longint;
Var RegInfo: TRegInfo): Boolean;
function getNextRegToTest(var orgP: pai; currentReg: tregister): tregister;
const
checkingPrevSequences: boolean = false;
passedJump: boolean = false;
begin
if currentReg = R_NO then
checkingPrevSequences := false;
if not checkingPrevSequences then
begin
Repeat
Inc(currentReg);
Until (currentReg > R_EDI) or
(ppaiprop(orgP^.optInfo)^.regs[currentReg].typ
in [con_ref,con_noRemoveRef]);
if currentReg > R_EDI then
begin
if not modifiesMemLocation(orgP) and
(ppaiprop(orgP^.optinfo)^.regs[reg].rstate =
ppaiprop(p^.optinfo)^.regs[reg].rstate) then
begin
checkingPrevSequences := true;
passedJump := false;
end
else
getNextRegToTest := R_NO;
end
else getNextRegToTest := currentReg;
end;
if checkingPrevSequences then
getNextRegToTest := getPrevSequence(reg,orgP,orgP, passedJump);
end;
Var hp2, hp3{, EndMod},highPrev, orgPrev: Pai;
{Cnt,} OldNrOfMods: Longint;
startRegInfo, OrgRegInfo, HighRegInfo: TRegInfo;
HighFound, OrgRegFound: Byte;
@ -86,19 +226,16 @@ Begin {CheckSequence}
new2OldReg[stack_pointer] := stack_pointer;
oldRegsEncountered := newRegsEncountered;
end;
RegCounter := R_EAX;
GetLastInstruction(p, PrevNonRemovablePai);
While (RegCounter <= R_EDI) And
not(ppaiprop(prevNonRemovablePai^.optInfo)^.regs[regCounter].typ in
[con_ref,con_noRemoveRef]) do
Inc(RegCounter);
While (RegCounter <= R_EDI) Do
GetLastInstruction(p, prev);
regCounter := getNextRegToTest(prev,R_NO);
While (RegCounter <> R_NO) Do
Begin
regInfo := startRegInfo;
Found := 0;
hp2 := PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].StartMod;
If (PrevNonRemovablePai <> PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].StartMod)
Then OldNrOfMods := PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter].NrOfMods
hp2 := PPaiProp(prev^.OptInfo)^.Regs[RegCounter].StartMod;
If (prev <> PPaiProp(prev^.OptInfo)^.Regs[RegCounter].StartMod)
Then OldNrOfMods := PPaiProp(prev^.OptInfo)^.Regs[RegCounter].NrOfMods
Else OldNrOfMods := 1;
hp3 := p;
While (Found <> OldNrOfMods) And
@ -111,7 +248,9 @@ Begin {CheckSequence}
(paicpu(hp3)^.opcode = A_MOVSX)) and
(paicpu(hp3)^.oper[0].typ in
[top_const,top_ref,top_symbol]) and
(paicpu(hp3)^.oper[1].typ = top_reg) then
(paicpu(hp3)^.oper[1].typ = top_reg) and
not(regInRef(reg32(paicpu(hp3)^.oper[1].reg),
paicpu(hp3)^.oper[0].ref^)) then
regInfo.lastReload
[reg32(paicpu(hp3)^.oper[1].reg)] := hp3;
GetNextInstruction(hp2, hp2);
@ -120,9 +259,9 @@ Begin {CheckSequence}
End;
for regCounter2 := R_EAX to R_EDX do
if (regInfo.new2OldReg[regCounter2] <> R_NO) and
(reg in PPaiProp(hp3^.optInfo)^.usedRegs) and
not regLoadedWithNewValue(reg,false,hp3) then
include(regInfo.regsStillUsedAfterSeq,regCounter);
(regCounter2 in PPaiProp(hp3^.optInfo)^.usedRegs) and
not regLoadedWithNewValue(regCounter2,false,hp3) then
include(regInfo.regsStillUsedAfterSeq,regCounter2);
If (Found <> OldNrOfMods) or
{ the following is to avoid problems with rangecheck code (see testcse2) }
(assigned(hp3) and
@ -147,23 +286,18 @@ Begin {CheckSequence}
(Found > HighFound)
Then
Begin
highPrev := prev;
HighFound := Found;
HighRegInfo := RegInfo;
End;
If (RegCounter = Reg) Then
Begin
orgPrev := prev;
OrgRegFound := Found;
OrgRegResult := TmpResult;
OrgRegInfo := RegInfo
End;
Repeat
Inc(RegCounter);
Until (RegCounter > R_EDI) or
((ppaiprop(prevNonRemovablePai^.optInfo)^.regs[regCounter].typ
in [con_ref,con_noRemoveRef]) {And
((Regcounter = Reg) Or
Not(PaiInSequence(p, PPaiProp(PrevNonRemovablePai^.OptInfo)^.Regs[RegCounter]))) }
);
regCounter := getNextRegToTest(prev,regCounter);
End;
If (HighFound > 0) And
(Not(OrgRegResult) Or
@ -175,6 +309,7 @@ Begin {CheckSequence}
{$else fpc}
CheckSequence := True;
{$endif fpc}
prev := highPrev;
RegInfo := HighRegInfo;
Found := HighFound
End
@ -185,6 +320,7 @@ Begin {CheckSequence}
{$else fpc}
CheckSequence := OrgRegResult;
{$endif fpc}
prev := orgPrev;
Found := OrgRegFound;
RegInfo := OrgRegInfo;
End;
@ -361,12 +497,14 @@ Procedure RestoreRegContentsTo(reg: TRegister; const c: TContent; p, endP: pai);
var
{$ifdef replaceregdebug}
hp: pai;
l: longint;
{$endif replaceregdebug}
tmpState: byte;
begin
{$ifdef replaceregdebug}
l := random(1000);
hp := new(pai_asm_comment,init(strpnew(
'restored '+att_reg2str[reg]+' with data from here...')));
'restored '+att_reg2str[reg]+' with data from here... '+tostr(l))));
hp^.next := p;
hp^.previous := p^.previous;
p^.previous := hp;
@ -388,7 +526,7 @@ begin
if assigned(p) then
begin
hp := new(pai_asm_comment,init(strpnew(
'restored '+att_reg2str[reg]+' till here...')));
'restored '+att_reg2str[reg]+' till here... '+tostr(l))));
hp^.next := p;
hp^.previous := p^.previous;
p^.previous := hp;
@ -398,6 +536,7 @@ begin
{$endif replaceregdebug}
end;
function FindRegDealloc(reg: tregister; p: pai): boolean;
{ assumes reg is a 32bit register }
var
@ -438,25 +577,36 @@ Procedure ClearRegContentsFrom(reg: TRegister; p, endP: pai);
var
{$ifdef replaceregdebug}
hp: pai;
l: longint;
{$endif replaceregdebug}
tmpState: byte;
oldStartmod: pai;
begin
{$ifdef replaceregdebug}
l := random(1000);
hp := new(pai_asm_comment,init(strpnew(
'cleared '+att_reg2str[reg]+' from here... '+tostr(l))));
hp^.next := p;
hp^.previous := p^.previous;
p^.previous := hp;
if assigned(hp^.previous) then
hp^.previous^.next := hp;
{$endif replaceregdebug}
PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
While (p <> endP) Do
Begin
PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
getNextInstruction(p,p);
end;
tmpState := PPaiProp(p^.optInfo)^.Regs[reg].wState;
oldStartmod := PPaiProp(p^.optInfo)^.Regs[reg].startmod;
repeat
PPaiProp(p^.optInfo)^.Regs[reg].typ := con_unknown;
until not getNextInstruction(p,p) or
(PPaiProp(p^.optInfo)^.Regs[reg].wState <> tmpState);
(PPaiProp(p^.optInfo)^.Regs[reg].startmod <> oldStartmod);
{$ifdef replaceregdebug}
if assigned(p) then
begin
hp := new(pai_asm_comment,init(strpnew(
'cleared '+att_reg2str[reg]+' till here...')));
'cleared '+att_reg2str[reg]+' till here... '+tostr(l))));
hp^.next := p;
hp^.previous := p^.previous;
p^.previous := hp;
@ -488,33 +638,69 @@ begin
end;
end;
Procedure ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister);
function ChangeReg(var Reg: TRegister; orgReg, newReg: TRegister): boolean;
begin
changeReg := true;
if reg = newReg then
reg := orgReg
else if reg = regtoreg8(newReg) then
reg := regtoreg8(orgReg)
else if reg = regtoreg16(newReg) then
reg := regtoreg16(orgReg);
reg := regtoreg16(orgReg)
else changeReg := false;
end;
procedure changeOp(var o: toper; orgReg, newReg: tregister);
function changeOp(var o: toper; orgReg, newReg: tregister): boolean;
begin
case o.typ of
top_reg: changeReg(o.reg,orgReg,newReg);
top_reg: changeOp := changeReg(o.reg,orgReg,newReg);
top_ref:
begin
changeReg(o.ref^.base,orgReg,newReg);
changeReg(o.ref^.index,orgReg,newReg);
changeOp :=
changeReg(o.ref^.base,orgReg,newReg) or
changeReg(o.ref^.index,orgReg,newReg);
end;
end;
end;
Procedure DoReplaceReg(orgReg,newReg: tregister; hp: paicpu);
var opCount: byte;
procedure updateStates(orgReg,newReg: tregister; hp: pai; writeStateToo: boolean);
var
prev: pai;
newOrgRegRState, newOrgRegWState: byte;
begin
if getLastInstruction(hp,prev) then
with ppaiprop(prev^.optinfo)^ do
begin
newOrgRegRState := regs[orgReg].rState +
ppaiprop(hp^.optinfo)^.regs[newReg].rState - regs[newReg].rstate;
if writeStateToo then
newOrgRegWState := regs[orgReg].wState +
ppaiprop(hp^.optinfo)^.regs[newReg].wState - regs[newReg].wstate;
end
else
with ppaiprop(hp^.optinfo)^.regs[newReg] do
begin
newOrgRegRState := rState;
if writeStateToo then
newOrgRegWState := wState;
end;
with ppaiprop(hp^.optinfo)^.regs[orgReg] do
begin
rState := newOrgRegRState;
if writeStateToo then
wState := newOrgRegwState;
end;
end;
function doReplaceReg(orgReg,newReg: tregister; hp: paicpu): boolean;
var
opCount: byte;
tmpResult: boolean;
begin
for opCount := 0 to 2 do
changeOp(hp^.oper[opCount],orgReg,newReg)
tmpResult :=
changeOp(hp^.oper[opCount],orgReg,newReg) or tmpResult;
doReplaceReg := tmpResult;
end;
function RegSizesOK(oldReg,newReg: TRegister; p: paicpu): boolean;
@ -535,9 +721,10 @@ begin
end;
end;
procedure DoReplaceReadReg(orgReg,newReg: tregister; p: paicpu);
function doReplaceReadReg(orgReg,newReg: tregister; p: paicpu): boolean;
var opCount: byte;
begin
doReplaceReadReg := false;
{ handle special case }
case p^.opcode of
A_IMUL:
@ -546,9 +733,17 @@ begin
1: internalerror(1301001);
2,3:
begin
changeOp(p^.oper[0],orgReg,newReg);
if p^.ops = 3 then
changeOp(p^.oper[1],orgReg,newReg);
if changeOp(p^.oper[0],orgReg,newReg) then
begin
{ updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true;
end;
if p^.ops = 3 then
if changeOp(p^.oper[1],orgReg,newReg) then
begin
{ updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true;
end;
end;
end;
end;
@ -557,23 +752,115 @@ begin
begin
for opCount := 0 to 2 do
if p^.oper[opCount].typ = top_ref then
changeOp(p^.oper[opCount],orgReg,newReg);
if changeOp(p^.oper[opCount],orgReg,newReg) then
begin
{ updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true;
end;
for opCount := 1 to MaxCh do
case InsProp[p^.opcode].Ch[opCount] of
Ch_ROp1:
if p^.oper[0].typ = top_reg then
ChangeReg(p^.oper[0].reg,orgReg,newReg);
if changeReg(p^.oper[0].reg,orgReg,newReg) then
begin
{ updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true;
end;
Ch_ROp2:
if p^.oper[1].typ = top_reg then
ChangeReg(p^.oper[1].reg,orgReg,newReg);
if changeReg(p^.oper[1].reg,orgReg,newReg) then
begin
{ updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true;
end;
Ch_ROp3:
if p^.oper[2].typ = top_reg then
ChangeReg(p^.oper[2].reg,orgReg,newReg);
if changeReg(p^.oper[2].reg,orgReg,newReg) then
begin
{ updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true;
end;
end;
end;
end;
end;
procedure updateState(reg: tregister; p: pai);
{ this procedure updates the read and write states of the instructions }
{ coming after p. It's called when the read/write state of p has been }
{ changed and this change has to be propagated to the following }
{ instructions as well }
var
newRState, newWState: byte;
prevRState, prevWState: byte;
doRState, doWState: boolean;
begin
{ get the new read/write states from p }
with ppaiprop(p^.optinfo)^.regs[reg] do
begin
newRState := rState;
newWState := wState;
end;
if not GetNextInstruction(p,p) then
exit;
{ get the old read/write states from the next instruction, to know }
{ when we can stop updating }
with ppaiprop(p^.optinfo)^.regs[reg] do
begin
prevRState := rState;
prevWState := wState;
end;
{ adjust the states if this next instruction reads/writes the register }
if regReadByInstruction(reg,p) then
incState(newRState,1);
if regModifiedByInstruction(reg,p) then
incState(newWState,1);
{ do we still have to update the read and/or write states? }
doRState := true;
doWState := true;
repeat
{ update the states }
with ppaiprop(p^.optinfo)^.regs[reg] do
begin
if doRState then
rState := newRState;
if doWState then
wState := newWState;
end;
if not getNextInstruction(p,p) then
break;
with ppaiprop(p^.optinfo)^.regs[reg] do
begin
{ stop updating the read state if it changes }
doRState :=
doRState and (rState = prevRState);
{ if, by accident, this changed state is the same as the one }
{ we've been using, change it to a value that's definitely }
{ different from the previous and next state }
if not doRState and
(rState = newRState) then
begin
incState(newRState,1);
prevRState := rState;
doRState := true;
end;
{ ditto for the write state }
doWState :=
doWState and (WState = prevWState);
if not doWState and
(wState = newWState) then
begin
incState(newWState,1);
prevWState := wState;
doWState := true;
end;
end;
{ stop when we don't have to update either state anymore }
until not(doRState or doWState);
end;
function ReplaceReg(asmL: PaasmOutput; orgReg, newReg: TRegister; p: pai;
const c: TContent; orgRegCanBeModified: Boolean;
var returnEndP: pai): Boolean;
@ -585,7 +872,8 @@ function ReplaceReg(asmL: PaasmOutput; orgReg, newReg: TRegister; p: pai;
{ if the function returns true, returnEndP holds the last instruction }
{ where newReg was replaced by orgReg }
var endP, hp: Pai;
removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: Boolean;
removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead,
stateChanged, readStateChanged: Boolean;
function storeBack(p1: pai): boolean;
{ returns true if p1 contains an instruction that stores the contents }
@ -664,6 +952,8 @@ begin
not(newRegModified and orgRegRead)) (* and
{ since newReg will be replaced by orgReg, we can't allow that newReg }
{ gets modified if orgRegCanBeModified = false }
{ this now gets checked after the loop (JM) }
(orgRegCanBeModified or not(newRegModified)) *);
tmpResult :=
not(removeLast) and
@ -709,16 +999,28 @@ begin
{$endif replaceregdebug}
replaceReg := true;
returnEndP := endP;
getNextInstruction(p,hp);
stateChanged := false;
while hp <> endP do
begin
if not(PPaiProp(hp^.optInfo)^.canBeRemoved) and
if {not(PPaiProp(hp^.optInfo)^.canBeRemoved) and }
(hp^.typ = ait_instruction) then
DoReplaceReg(orgReg,newReg,paicpu(hp));
GetNextInstruction(hp,hp)
stateChanged :=
doReplaceReg(orgReg,newReg,paicpu(hp)) or stateChanged;
if stateChanged then
updateStates(orgReg,newReg,hp,true);
getNextInstruction(hp,hp)
end;
if assigned(endp) and (endp^.typ = ait_instruction) then
DoReplaceReadReg(orgReg,newReg,paicpu(endP));
readStateChanged :=
DoReplaceReadReg(orgReg,newReg,paicpu(endP));
if stateChanged or readStateChanged then
updateStates(orgReg,newReg,endP,stateChanged);
if stateChanged or readStateChanged then
updateState(orgReg,endP);
{ the replacing stops either at the moment that }
{ a) the newreg gets loaded with a new value (one not depending on the }
{ current value of newreg) }
@ -733,7 +1035,8 @@ begin
if removeLast or
(p <> endp) or
not RegLoadedWithNewValue(newReg,true,endP) then
RestoreRegContentsTo(newReg, c ,p, hp);
RestoreRegContentsTo(newReg,c,p,hp);
{ In both case a and b, it is possible that the new register was modified }
{ (e.g. an add/sub), so if it was replaced by oldreg in that instruction, }
{ oldreg's contents have been changed. To take this into account, we simply }
@ -743,6 +1046,7 @@ begin
if removeLast then
ppaiprop(endP^.optinfo)^.canBeRemoved := true;
allocRegBetween(asml,orgReg,p,endP);
end
{$ifdef replaceregdebug}
else
@ -834,7 +1138,7 @@ Procedure DoCSE(AsmL: PAasmOutput; First, Last: Pai);
removed immediately because sometimes an instruction needs to be checked in
two different sequences}
var cnt, cnt2, cnt3: longint;
p, hp1, hp2: Pai;
p, hp1, hp2, prevSeq, prevSeq_next: Pai;
hp3, hp4: pai;
hp5 : pai;
RegInfo: TRegInfo;
@ -875,7 +1179,7 @@ Begin
'cse checking '+att_reg2str[Reg32(Paicpu(p)^.oper[1].reg)])));
insertLLItem(asml,p,p^.next,hp5);
{$endif csdebug}
If CheckSequence(p, Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
If CheckSequence(p,prevSeq,Paicpu(p)^.oper[1].reg, Cnt, RegInfo) And
(Cnt > 0) Then
Begin
hp1 := nil;
@ -924,7 +1228,8 @@ Begin
PPaiProp(hp5^.OptInfo)^.CanBeRemoved := True;
getNextInstruction(hp5,hp5);
end;
{$endif noremove} end
end
{$endif noremove}
end
end
{$ifndef noremove}
@ -934,10 +1239,10 @@ Begin
; Inc(Cnt2);
GetNextInstruction(p, p);
End;
hp3 := New(Pai_Marker,Init(NoPropInfoStart));
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
{hp4 is used to get the contents of the registers before the sequence}
GetLastInstruction(hp2, hp4);
getNextInstruction(prevSeq,prevSeq_next);
{$IfDef CSDebug}
For RegCounter := R_EAX To R_EDI Do
If (RegCounter in RegInfo.RegsLoadedForRef) Then
@ -954,21 +1259,44 @@ Begin
(RegInfo.New2OldReg[RegCounter] <> R_NO) Then
Begin
AllocRegBetween(AsmL,RegInfo.New2OldReg[RegCounter],
PPaiProp(hp4^.OptInfo)^.Regs[RegInfo.New2OldReg[RegCounter]].StartMod,hp2);
PPaiProp(prevSeq^.OptInfo)^.Regs[RegInfo.New2OldReg[RegCounter]].StartMod,prevSeq_next);
if hp4 <> prevSeq then
begin
if assigned(reginfo.lastReload[regCounter]) then
getLastInstruction(reginfo.lastReload[regCounter],hp3)
else hp3 := hp4;
if prevSeq <> hp3 then
clearRegContentsFrom(regCounter,prevSeq_next,
hp3);
allocRegBetween(asmL,regCounter,prevSeq,hp3);
end;
If Not(RegCounter In RegInfo.RegsLoadedForRef) And
{old reg new reg}
(RegInfo.New2OldReg[RegCounter] <> RegCounter) Then
Begin
getLastInstruction(p,hp3);
If not(regCounter in usableRegs + [R_EDI,R_ESI]) or
If (hp4 <> prevSeq) or
not(regCounter in usableRegs + [R_EDI,R_ESI]) or
not ReplaceReg(asmL,RegInfo.New2OldReg[RegCounter],
regCounter,hp3,
PPaiProp(hp4^.optInfo)^.Regs[regCounter],true,hp5) then
PPaiProp(PrevSeq^.optInfo)^.Regs[regCounter],true,hp5) then
begin
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
InsertLLItem(AsmL, prevSeq, Pai(prevSeq^.next), hp3);
hp3 := New(Paicpu,Op_Reg_Reg(A_MOV, S_L,
{old reg new reg}
RegInfo.New2OldReg[RegCounter], RegCounter));
InsertLLItem(AsmL, Pai(hp2^.previous), hp2, hp3);
InsertLLItem(AsmL, prevSeq, Pai(prevSeq^.next), hp3);
hp3 := New(Pai_Marker,Init(NoPropInfoStart));
InsertLLItem(AsmL, prevSeq, Pai(prevSeq^.next), hp3);
{ adjusts states in previous instruction so that it will }
{ definitely be different from the previous or next state }
incstate(ppaiprop(prevSeq_next^.optinfo)^.
regs[RegInfo.New2OldReg[RegCounter]].rstate,20);
incstate(ppaiprop(prevSeq_next^.optinfo)^.
regs[regCounter].wstate,20);
updateState(RegInfo.New2OldReg[RegCounter],
prevSeq_next);
end
End
Else
@ -1002,8 +1330,6 @@ Begin
hp2,hp3);
End;
End;
hp3 := New(Pai_Marker,Init(NoPropInfoEnd));
InsertLLItem(AsmL, Pai(hp2^.Previous), hp2, hp3);
If hp1 <> nil Then
p := hp1;
Continue;
@ -1167,7 +1493,14 @@ End.
{
$Log$
Revision 1.7 2000-08-25 19:40:45 jonas
Revision 1.8 2000-09-20 15:00:58 jonas
+ much improved CSE: the CSE now searches further back for sequences it
can reuse. After I've also implemented register renaming, the effect
should be even better (afaik web bug 1088 will then even be optimized
properly). I don't know about the slow down factor this adds. Maybe
a new optimization level should be introduced?
Revision 1.7 2000/08/25 19:40:45 jonas
* refined previous fix a bit, some instructions weren't being removed
while they could (merged from fixes branch)
* made checksequence a bit faster

View File

@ -89,6 +89,8 @@ Procedure ShutDownDFA;
Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean;
Procedure IncState(Var S: Byte; amount: longint);
{******************************* Constants *******************************}
Const
@ -116,14 +118,17 @@ type
{start and end of block instructions that defines the
content of this register.}
StartMod: pai;
{starts at 0, gets increased everytime the register is written to}
WState: Byte;
{starts at 0, gets increased everytime the register is read from}
RState: Byte;
{how many instructions starting with StarMod does the block consist of}
NrOfMods: Byte;
{the type of the content of the register: unknown, memory, constant}
Typ: Byte;
case byte of
{starts at 0, gets increased everytime the register is written to}
1: (WState: Byte;
{starts at 0, gets increased everytime the register is read from}
RState: Byte);
{ to compare both states in one operation }
2: (state: word);
End;
{Contents of the integer registers}
@ -1177,13 +1182,13 @@ Begin
End;
Procedure IncState(Var S: Byte);
Procedure IncState(Var S: Byte; amount: longint);
{Increases S by 1, wraps around at $ffff to 0 (so we won't get overflow
errors}
Begin
If (s <> $ff)
Then Inc(s)
Else s := 0
if (s <= $ff - amount) then
inc(s, amount)
else s := longint(s) + amount - $ff;
End;
Function sequenceDependsonReg(Const Content: TContent; seqReg, Reg: TRegister): Boolean;
@ -1241,7 +1246,7 @@ begin
with p1^.regs[counter] Do
if (typ in [con_ref,con_noRemoveRef]) and
sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then
if typ = con_ref then
if typ in [con_ref,con_invalid] then
typ := con_invalid
{ con_invalid and con_noRemoveRef = con_unknown }
else typ := con_unknown;
@ -1269,7 +1274,7 @@ Begin
begin
if doIncState then
begin
incState(WState);
incState(wstate,1);
typ := con_unknown;
end
else
@ -1488,7 +1493,7 @@ Procedure ReadReg(p: PPaiProp; Reg: TRegister);
Begin
Reg := Reg32(Reg);
If Reg in [R_EAX..R_EDI] Then
IncState(p^.Regs[Reg].RState)
incState(p^.regs[Reg].rstate,1)
End;
@ -1572,14 +1577,14 @@ Begin
If (Ref.base = procinfo^.FramePointer) or
Assigned(Ref.Symbol) Then
Begin
If (Ref.Index = R_NO) And
(Not(Assigned(Ref.Symbol)) or
(Ref.base = R_NO)) Then
{ local variable which is not an array }
RefsEq := {$ifdef fpc}@{$endif}RefsEqual
If (ref.index <> R_NO) or
(assigned(ref.symbol) and
(ref.base <> R_NO)) then
{ local/global variable or parameter which is an array }
RefsEq := {$ifdef fpc}@{$endif}ArrayRefsEq
Else
{ local variable which is an array }
RefsEq := {$ifdef fpc}@{$endif}ArrayRefsEq;
{ local/global variable or parameter which is not an array }
RefsEq := {$ifdef fpc}@{$endif}RefsEqual;
{write something to a parameter, a local or global variable, so
* with uncertain optimizations on:
@ -1696,7 +1701,7 @@ Begin
if (typ in [con_ref,con_noRemoveRef])
Then
Begin
IncState(WState);
incState(wstate,1);
{also store how many instructions are part of the sequence in the first
instructions PPaiProp, so it can be easily accessed from within
CheckSequence}
@ -2031,7 +2036,7 @@ Begin
Begin
With CurProp^.Regs[TmpReg] Do
Begin
IncState(WState);
incState(wstate,1);
{also store how many instructions are part of the sequence in the first
instructions PPaiProp, so it can be easily accessed from within
CheckSequence}
@ -2333,7 +2338,14 @@ End.
{
$Log$
Revision 1.8 2000-08-25 19:39:18 jonas
Revision 1.9 2000-09-20 15:00:58 jonas
+ much improved CSE: the CSE now searches further back for sequences it
can reuse. After I've also implemented register renaming, the effect
should be even better (afaik web bug 1088 will then even be optimized
properly). I don't know about the slow down factor this adds. Maybe
a new optimization level should be introduced?
Revision 1.8 2000/08/25 19:39:18 jonas
* bugfix to FindRegAlloc function (caused wrong regalloc info in
some cases) (merged from fixes branch)