* fixed tracking of usage of flags register

* fixed destroying of "memwrite"'s
  * fixed checking of entire sequences in all cases (previously this was
    only guaranteed if the new sequence was longer than the old one, and
    not if vice versa)
  * fixed wrong removal of sequences if a register load was already
    completely removed in the previous sequence (because in that case,
    that register has to be removed and renamed in the new sequence as
    well before removing the new sequence)
This commit is contained in:
Jonas Maebe 2004-12-18 15:16:10 +00:00
parent a3627d9345
commit 84aa52942f
2 changed files with 119 additions and 41 deletions

View File

@ -258,7 +258,7 @@ var
getlastinstruction(p,hp) then
stillValid := stillValid and
not(supreg in ptaiprop(hp.optinfo)^.usedregs);
passedFlagsModifyingInstr :=
passedFlagsModifyingInstr := passedFlagsModifyingInstr or
instrWritesFlags(currentPrev);
end;
@ -274,9 +274,9 @@ var
for regCounter := loopstart to RS_EDI do
with ptaiprop(p.optinfo)^.regs[regCounter] do
if ((startmod <>
ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or
ptaiprop(currentPrev.optinfo)^.regs[regCounter].startmod) or
(nrofMods <>
ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and
ptaiprop(currentPrev.optinfo)^.regs[regCounter].nrofMods)) and
(ptaiprop(p.optinfo)^.regs[regCounter].typ in [con_ref,con_noRemoveRef]) then
begin
findChangedRegister := regCounter;
@ -305,7 +305,8 @@ var
end;
getPrevSequence := RS_INVALID;
passedFlagsModifyingInstr := instrWritesFlags(currentPrev);
passedFlagsModifyingInstr := passedFlagsModifyingInstr or
instrWritesFlags(currentPrev);
if not getLastInstruction(currentPrev,hp) then
exit;
@ -402,7 +403,7 @@ var
hp2, hp3{, EndMod},highPrev, orgPrev: tai;
{Cnt,} OldNrofMods: Longint;
startRegInfo, OrgRegInfo, HighRegInfo: toptreginfo;
regModified: array[RS_EAX..RS_ESP] of boolean;
regModified, lastregloadremoved: array[RS_EAX..RS_ESP] of boolean;
HighFound, OrgRegFound: longint;
regcounter, regCounter2, tmpreg, base, index: tsuperregister;
OrgRegResult: Boolean;
@ -434,6 +435,7 @@ begin {CheckSequence}
while (regcounter <> RS_INVALID) do
begin
fillchar(regModified,sizeof(regModified),0);
fillchar(lastregloadremoved,sizeof(lastregloadremoved),0);
reginfo := startRegInfo;
Found := 0;
hp2 := ptaiprop(prev.optinfo)^.Regs[regcounter].StartMod;
@ -454,8 +456,8 @@ begin {CheckSequence}
if checkingprevsequences then
begin
prevreginfo := reginfo;
end
else if (hp3.typ = ait_instruction) and
end;
if (hp3.typ = ait_instruction) and
((taicpu(hp3).opcode = A_MOV) or
(taicpu(hp3).opcode = A_MOVZX) or
(taicpu(hp3).opcode = A_LEA) or
@ -464,6 +466,7 @@ begin {CheckSequence}
not(regInOp(getsupreg(taicpu(hp3).oper[1]^.reg),taicpu(hp3).oper[0]^)) then
begin
tmpreg := getsupreg(taicpu(hp3).oper[1]^.reg);
lastregloadremoved[tmpreg] := ptaiprop(hp2.optinfo)^.canberemoved;
reginfo.lastReload[tmpreg] := hp3;
case taicpu(hp3).oper[0]^.typ of
top_ref:
@ -481,13 +484,22 @@ begin {CheckSequence}
with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
if nrofMods > (oldNrofMods - found) then
oldNrofMods := found + nrofMods;
{ next is safe because instructions are equivalent }
with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
if nrofMods > (oldNrofMods - found) then
oldNrofMods := found + nrofMods;
end;
end;
top_reg:
if regModified[getsupreg(taicpu(hp3).oper[0]^.reg)] then
with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
if nrofMods > (oldNrofMods - found) then
oldNrofMods := found + nrofMods;
begin
with ptaiprop(hp3.optinfo)^.regs[tmpreg] do
if nrofMods > (oldNrofMods - found) then
oldNrofMods := found + nrofMods;
with ptaiprop(hp2.optinfo)^.regs[getsupreg(taicpu(hp2).oper[1]^.reg)] do
if nrofMods > (oldNrofMods - found) then
oldNrofMods := found + nrofMods;
end;
end;
end;
for regCounter2 := RS_EAX to RS_EDI do
@ -505,8 +517,9 @@ begin {CheckSequence}
for regCounter2 := RS_EAX to RS_EDI do
if (reginfo.new2OldReg[regCounter2] <> RS_INVALID) and
(regCounter2 in ptaiprop(hp3.optinfo)^.usedRegs) and
not regLoadedWithNewValue(regCounter2,false,hp3) then
include(reginfo.regsStillUsedAfterSeq,regCounter2);
not regLoadedWithNewValue(regCounter2,false,hp3) and
lastregloadremoved[regcounter2] then
found := 0;
if checkingPrevSequences then
begin
@ -836,7 +849,7 @@ var
l: longint;
{$endif replaceregdebug}
dummyregs: tregset;
tmpState: byte;
tmpState, newrstate: byte;
prevcontenttyp: byte;
memconflict: boolean;
invalsmemwrite: boolean;
@ -852,19 +865,31 @@ begin
hp.previous.next := hp;
{$endif replaceregdebug}
{ ptaiprop(p.optinfo)^.Regs[reg] := c;}
newrstate := c.rstate;
incstate(newrstate,$7f);
while (p <> endP) do
begin
if not(ptaiprop(p.optinfo)^.canberemoved) and
regreadbyinstruction(supreg,p) then
incstate(newrstate,1);
ptaiprop(p.optinfo)^.Regs[supreg] := c;
ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
getNextInstruction(p,p);
end;
tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState;
if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then
internalerror(2004101012);
dummyregs := [supreg];
repeat
newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState;
prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ;
// is this a write to memory that destroys the contents we are restoring?
memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,dummyregs,true,invalsmemwrite);
if not memconflict and not invalsmemwrite then
ptaiprop(p.optinfo)^.Regs[supreg] := c;
begin
ptaiprop(p.optinfo)^.Regs[supreg] := c;
ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
end;
until invalsmemwrite or
memconflict or
not getNextInstruction(p,p) or
@ -873,10 +898,13 @@ begin
((prevcontenttyp <> con_invalid) and
(ptaiprop(p.optinfo)^.Regs[supreg].typ = con_invalid));
if assigned(p) and
((p.typ = ait_label) or
memconflict or
invalsmemwrite) then
clearRegContentsFrom(supreg,p,p);
(p.typ <> ait_marker) then
if ((p.typ = ait_label) or
memconflict or
invalsmemwrite) then
clearRegContentsFrom(supreg,p,p)
else if (ptaiprop(p.optinfo)^.Regs[supreg].rstate = newrstate) then
incstate(ptaiprop(p.optinfo)^.Regs[supreg].rstate,20);
{$ifdef replaceregdebug}
if assigned(p) then
begin
@ -1186,24 +1214,13 @@ begin
end;
function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p,
seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean;
var returnEndP: tai): Boolean;
{ Tries to replace orgsupreg with newsupreg in all instructions coming after p }
{ until orgsupreg gets loaded with a new value. Returns true if successful, }
{ false otherwise. if successful, the contents of newsupreg are set to c, }
{ which should hold the contents of newsupreg before the current sequence }
{ started }
{ if the function returns true, returnEndP holds the last instruction }
{ where newsupreg was replaced by orgsupreg }
function canreplacereg(orgsupreg, newsupreg: tsuperregister; p: tai;
orgRegCanBeModified: boolean; var resnewregmodified, resorgregread, resremovelast: boolean; var returnendp: tai): boolean;
var
endP, hp: tai;
removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead,
stateChanged, readStateChanged: Boolean;
removeLast, sequenceEnd, tmpResult, newRegModified, orgRegRead: boolean;
begin
ReplaceReg := false;
canreplacereg := false;
tmpResult := true;
sequenceEnd := false;
newRegModified := false;
@ -1281,7 +1298,7 @@ begin
not RegModifiedByInstruction(orgsupreg,endP);
end;
end;
sequenceEnd := sequenceEnd and
canreplacereg := sequenceEnd and
(removeLast or
(orgRegCanBeModified or not(newRegModified))) and
(not(assigned(endp)) or
@ -1291,7 +1308,35 @@ begin
not(newRegModified and
(orgsupreg in ptaiprop(endp.optinfo)^.usedRegs) and
not(RegLoadedWithNewValue(orgsupreg,true,taicpu(endP))))));
if SequenceEnd then
if canreplacereg then
begin
resnewregmodified := newregmodified;
resorgregread := orgregread;
resremovelast := removelast;
returnendp := endp;
end;
end;
function ReplaceReg(asml: TAAsmOutput; orgsupreg, newsupreg: tsuperregister; p,
seqstart: tai; const c: TContent; orgRegCanBeModified: Boolean;
var returnEndP: tai): Boolean;
{ Tries to replace orgsupreg with newsupreg in all instructions coming after p }
{ until orgsupreg gets loaded with a new value. Returns true if successful, }
{ false otherwise. if successful, the contents of newsupreg are set to c, }
{ which should hold the contents of newsupreg before the current sequence }
{ started }
{ if the function returns true, returnEndP holds the last instruction }
{ where newsupreg was replaced by orgsupreg }
var
endP, hp: tai;
removeLast, sequenceEnd, newRegModified, orgRegRead,
stateChanged, readStateChanged: Boolean;
begin
replacereg := false;
if canreplacereg(orgsupreg,newsupreg,p,orgregcanbemodified,newregmodified, orgregread, removelast,endp) then
begin
{$ifdef replaceregdebug}
hp := tai_comment.Create(strpnew(
@ -1424,7 +1469,7 @@ procedure removePrevNotUsedLoad(p: tai; supreg: tsuperregister; check: boolean);
{ (e.g. when you have a "mov 8(%ebp),%eax", you can be sure the previous }
{ value of %eax isn't used anymore later on) }
var
hp1: tai;
hp1, next, beforestartmod: tai;
begin
if getLastInstruction(p,hp1) then
with ptaiprop(hp1.optinfo)^.regs[supreg] do
@ -1435,7 +1480,17 @@ begin
(not(regInInstruction(supreg,p)) and
(not(supreg in ptaiprop(hp1.optinfo)^.usedRegs) or
findRegDealloc(supreg,p)))) then
ptaiprop(startMod.optinfo)^.canBeRemoved := true;
begin
ptaiprop(startMod.optinfo)^.canBeRemoved := true;
getnextinstruction(p,next);
{ give the register that was modified by this instruction again }
{ the contents it had before this instruction }
if getlastinstruction(startmod,beforestartmod) then
RestoreRegContentsTo(supreg,ptaiprop(beforestartmod.optinfo)^.regs[supreg],
startmod,p)
else
ClearRegContentsFrom(supreg,startmod,hp1);
end;
end;
@ -2122,7 +2177,18 @@ end.
{
$Log$
Revision 1.69 2004-10-31 21:45:03 peter
Revision 1.70 2004-12-18 15:16:10 jonas
* fixed tracking of usage of flags register
* fixed destroying of "memwrite"'s
* fixed checking of entire sequences in all cases (previously this was
only guaranteed if the new sequence was longer than the old one, and
not if vice versa)
* fixed wrong removal of sequences if a register load was already
completely removed in the previous sequence (because in that case,
that register has to be removed and renamed in the new sequence as
well before removing the new sequence)
Revision 1.69 2004/10/31 21:45:03 peter
* generic tlocation
* move tlocation to cgutils

View File

@ -70,7 +70,6 @@ type
toptreginfo = Record
NewRegsEncountered, OldRegsEncountered: TRegSet;
RegsLoadedForRef: TRegSet;
regsStillUsedAfterSeq: TRegSet;
lastReload: array[RS_EAX..RS_ESP] of tai;
New2OldReg: TRegArray;
end;
@ -2574,7 +2573,8 @@ begin
{ DestroyReg(curprop, RS_EAX, true);}
AddInstr2RegContents({$ifdef statedebug}list,{$endif}
taicpu(p), RS_EAX);
DestroyReg(curprop, RS_EDX, true)
DestroyReg(curprop, RS_EDX, true);
LastFlagsChangeProp := curprop;
end;
A_IMUL:
begin
@ -2601,6 +2601,7 @@ begin
else
AddInstr2OpContents({$ifdef statedebug}list,{$endif}
taicpu(p), taicpu(p).oper[2]^);
LastFlagsChangeProp := curprop;
end;
A_LEA:
begin
@ -2791,7 +2792,18 @@ end.
{
$Log$
Revision 1.76 2004-12-18 14:07:35 jonas
Revision 1.77 2004-12-18 15:16:10 jonas
* fixed tracking of usage of flags register
* fixed destroying of "memwrite"'s
* fixed checking of entire sequences in all cases (previously this was
only guaranteed if the new sequence was longer than the old one, and
not if vice versa)
* fixed wrong removal of sequences if a register load was already
completely removed in the previous sequence (because in that case,
that register has to be removed and renamed in the new sequence as
well before removing the new sequence)
Revision 1.76 2004/12/18 14:07:35 jonas
* fixed compilation with -dcsdebug -dallocregdebug
Revision 1.75 2004/12/12 10:50:34 florian