+ replace mem accesses to locations to which a reg was stored recently with that reg

This commit is contained in:
Jonas Maebe 2001-10-27 10:20:43 +00:00
parent b0e3e03f08
commit e02d95ed13
2 changed files with 177 additions and 83 deletions

View File

@ -70,6 +70,7 @@ var
tmpRef: treference;
regCounter: tregister;
opCount: byte;
dummy: boolean;
begin
modifiesConflictingMemLocation := false;
if p1.typ <> ait_instruction then
@ -81,7 +82,7 @@ begin
for regCounter := R_EAX to R_EDI do
begin
if writeToMemDestroysContents(reg32(p.oper[0].reg),p.oper[1].ref^,
regCounter,c[regCounter]) then
regCounter,c[regCounter],dummy) then
begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(reg in regsStillValid);
@ -170,7 +171,7 @@ begin
tmpRef.base := R_EDI;
tmpRef.index := R_EDI;
for regCounter := R_EAX to R_EDI do
if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter]) then
if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter],dummy) then
begin
exclude(regsStillValid,regCounter);
modifiesConflictingMemLocation := not(reg in regsStillValid);
@ -720,6 +721,16 @@ begin
{$endif replaceregdebug}
end;
procedure clearmemwrites(p: tai; reg: tregister);
var
beginmemwrite: tai;
begin
beginmemwrite := pTaiprop(p.optinfo)^.regs[reg].memwrite;
repeat
pTaiprop(p.optinfo)^.regs[reg].memwrite := nil;
until not getnextinstruction(p,p) or
(pTaiprop(p.optinfo)^.regs[reg].memwrite <> beginmemwrite);
end;
Procedure ClearRegContentsFrom(reg: TRegister; p, endP: Tai);
{ first clears the contents of reg from p till endP. Then the contents are }
@ -729,6 +740,7 @@ var
hp: Tai;
l: longint;
{$endif replaceregdebug}
regcounter: tregister;
oldStartmod: Tai;
begin
{$ifdef replaceregdebug}
@ -744,12 +756,25 @@ begin
PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown;
While (p <> endP) Do
Begin
PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown;
for regcounter := R_EAX to R_EDI do
if (regcounter <> reg) and
assigned(pTaiprop(p.optinfo)^.regs[reg].memwrite) and
reginref(regcounter,pTaiprop(p.optinfo)^.regs[reg].memwrite.oper[1].ref^) then
clearmemwrites(p,regcounter);
with PTaiProp(p.optInfo)^.Regs[reg] do
begin
typ := con_unknown;
memwrite := nil;
end;
getNextInstruction(p,p);
end;
oldStartmod := PTaiProp(p.optInfo)^.Regs[reg].startmod;
repeat
PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown;
with PTaiProp(p.optInfo)^.Regs[reg] do
begin
typ := con_unknown;
memwrite := nil;
end;
until not getNextInstruction(p,p) or
(PTaiProp(p.optInfo)^.Regs[reg].startmod <> oldStartmod);
{$ifdef replaceregdebug}
@ -1311,45 +1336,57 @@ begin
(p.opcode = A_IDIV));
end;
function memtoreg(const t: Taicpu; const ref: treference): tregister;
function memtoreg(const t: Taicpu; const ref: treference; var startp: tai): tregister;
var
hp: tai;
p: pTaiprop;
regcounter: tregister;
optimizable: boolean;
begin
if not getlastinstruction(t,hp) then
if not getlastinstruction(t,hp) or
not issimplememloc(ref) then
begin
memtoreg := R_NO;
exit;
end;
p := pTaiprop(hp.optinfo);
if isSimpleMemLoc(ref) then
optimizable := false;
for regcounter := R_EAX to R_EDI do
begin
for regcounter := R_EAX to R_EDI do
if (p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
(p^.regs[regcounter].nrofmods = 1) and
((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
(Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
(Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
(taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and
refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^) then
begin
if ((t.opsize <> S_B) or
(regcounter <> R_EDI)) and
sizescompatible(Taicpu(p^.regs[regcounter].startmod).opsize,t.opsize) then
begin
case t.opsize of
S_B,S_BW,S_BL:
memtoreg := reg32toreg8(regcounter);
S_W,S_WL:
memtoreg := reg32toreg16(regcounter);
S_L:
memtoreg := regcounter;
end;
exit;
if (assigned(p^.regs[regcounter].memwrite) and
refsequal(ref,p^.regs[regcounter].memwrite.oper[1].ref^)) then
begin
optimizable := true;
hp := p^.regs[regcounter].memwrite;
end
else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
(p^.regs[regcounter].nrofmods = 1) and
((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
(Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
(Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
(taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and
refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^)) then
begin
optimizable := true;
hp := p^.regs[regcounter].startmod;
end;
if optimizable then
if ((t.opsize <> S_B) or
(regcounter <> R_EDI)) and
sizescompatible(Taicpu(hp).opsize,t.opsize) then
begin
case t.opsize of
S_B,S_BW,S_BL:
memtoreg := reg32toreg8(regcounter);
S_W,S_WL:
memtoreg := reg32toreg16(regcounter);
S_L:
memtoreg := regcounter;
end;
end;
end;
startp := hp;
exit;
end;
end;
memtoreg := R_NO;
end;
@ -1643,14 +1680,20 @@ Begin
begin
regcounter :=
memtoreg(taicpu(p),
Taicpu(p).oper[0].ref^);
Taicpu(p).oper[0].ref^,hp5);
if regcounter <> R_NO then
begin
Taicpu(p).loadreg(0,regcounter);
allocregbetween(asml,reg32(regcounter),
pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
p);
end;
if (taicpu(p).opcode = A_MOV) and
(taicpu(p).oper[1].typ = top_reg) and
(taicpu(p).oper[1].reg = regcounter) then
pTaiProp(p.optinfo)^.canberemoved := true
else
begin
Taicpu(p).loadreg(0,regcounter);
regcounter := reg32(regcounter);
allocregbetween(asml,regcounter,hp5,p);
incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
updatestate(regcounter,p);
end;
end;
end;
{ at first, only try optimizations of large blocks, because doing }
@ -1715,13 +1758,14 @@ Begin
begin
regcounter :=
memtoreg(taicpu(p),
Taicpu(p).oper[0].ref^);
Taicpu(p).oper[0].ref^,hp5);
if regcounter <> R_NO then
begin
Taicpu(p).loadreg(0,regcounter);
allocregbetween(asml,reg32(regcounter),
pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
p);
regcounter := reg32(regcounter);
allocregbetween(asml,regcounter,hp5,p);
incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
updatestate(regcounter,p);
end;
end;
Ch_MOp1:
@ -1730,7 +1774,7 @@ Begin
begin
regcounter :=
memtoreg(taicpu(p),
Taicpu(p).oper[0].ref^);
Taicpu(p).oper[0].ref^,hp5);
if (regcounter <> R_NO) (* and
(not getNextInstruction(p,hp1) or
(RegLoadedWithNewValue(reg32(regcounter),false,hp1) or
@ -1744,11 +1788,13 @@ Begin
new(pTaiprop(hp1.optinfo));
pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
insertllitem(asml,p,p.next,hp1);
incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1);
updatestate(reg32(regcounter),hp1);
hp1 := Tai_Marker.Create(NoPropInfoStart);
insertllitem(asml,p,p.next,hp1);
Taicpu(p).loadreg(0,regcounter);
allocregbetween(asml,reg32(regcounter),
pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
regcounter := reg32(regcounter);
allocregbetween(asml,regcounter,hp5,
tai(p.next.next));
end;
end;
@ -1759,13 +1805,14 @@ Begin
begin
regcounter :=
memtoreg(taicpu(p),
Taicpu(p).oper[1].ref^);
Taicpu(p).oper[1].ref^,hp5);
if regcounter <> R_NO then
begin
Taicpu(p).loadreg(1,regcounter);
allocregbetween(asml,reg32(regcounter),
pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
p);
regcounter := reg32(regcounter);
allocregbetween(asml,regcounter,hp5,p);
incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
updatestate(regcounter,p);
end;
end;
Ch_MOp2:
@ -1780,7 +1827,7 @@ Begin
begin
regcounter :=
memtoreg(taicpu(p),
Taicpu(p).oper[1].ref^);
Taicpu(p).oper[1].ref^,hp5);
if (regcounter <> R_NO) (* and
(not getNextInstruction(p,hp1) or
(RegLoadedWithNewValue(reg32(regcounter),false,hp1) or
@ -1794,11 +1841,13 @@ Begin
new(pTaiprop(hp1.optinfo));
pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
insertllitem(asml,p,p.next,hp1);
incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1);
updatestate(reg32(regcounter),hp1);
hp1 := Tai_Marker.Create(NoPropInfoStart);
insertllitem(asml,p,p.next,hp1);
Taicpu(p).loadreg(1,regcounter);
allocregbetween(asml,reg32(regcounter),
pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
regcounter := reg32(regcounter);
allocregbetween(asml,regcounter,hp5,
tai(p.next.next));
end;
end;
@ -1904,7 +1953,10 @@ End.
{
$Log$
Revision 1.20 2001-10-14 11:50:21 jonas
Revision 1.21 2001-10-27 10:20:43 jonas
+ replace mem accesses to locations to which a reg was stored recently with that reg
Revision 1.20 2001/10/14 11:50:21 jonas
+ also replace mem references in modify operands with regs
Revision 1.19 2001/10/12 13:58:05 jonas

View File

@ -73,6 +73,7 @@ type
{start and end of block instructions that defines the
content of this register.}
StartMod: Tai;
MemWrite: Taicpu;
{how many instructions starting with StarMod does the block consist of}
NrOfMods: Byte;
{the type of the content of the register: unknown, memory, constant}
@ -170,7 +171,7 @@ function instrWritesFlags(p: Tai): boolean;
function instrReadsFlags(p: Tai): boolean;
function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
reg: tregister; const c: tcontent): boolean;
reg: tregister; const c: tcontent; var invalsmemwrite: boolean): boolean;
function writeToRegDestroysContents(destReg: tregister; reg: tregister;
const c: tcontent): boolean;
function writeDestroysContents(const op: toper; reg: tregister;
@ -1328,12 +1329,17 @@ begin
for counter := R_EAX to R_EDI Do
if counter <> reg then
with p1^.regs[counter] Do
if (typ in [con_ref,con_noRemoveRef]) and
sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then
if typ in [con_ref,con_invalid] then
typ := con_invalid
{ con_invalid and con_noRemoveRef = con_unknown }
else typ := con_unknown;
begin
if (typ in [con_ref,con_noRemoveRef]) and
sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then
if typ in [con_ref,con_invalid] then
typ := con_invalid
{ con_invalid and con_noRemoveRef = con_unknown }
else typ := con_unknown;
if assigned(memwrite) and
regInRef(counter,memwrite.oper[1].ref^) then
memwrite := nil;
end;
end;
Procedure DestroyReg(p1: PTaiProp; Reg: TRegister; doIncState:Boolean);
@ -1364,6 +1370,7 @@ Begin
typ := con_invalid
{ con_invalid and con_noRemoveRef = con_unknown }
else typ := con_unknown;
memwrite := nil;
end;
invalidateDependingRegs(p1,reg);
end;
@ -1737,17 +1744,12 @@ begin
end;
function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
reg: tregister; const c: tcontent): boolean;
reg: tregister; const c: tcontent; var invalsmemwrite: boolean): boolean;
{ returns whether the contents c of reg are invalid after regWritten is }
{ is written to ref }
var
refsEq: trefCompare;
begin
if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
begin
writeToMemDestroysContents := false;
exit;
end;
reg := reg32(reg);
regWritten := reg32(regWritten);
if isSimpleRef(ref) then
@ -1760,6 +1762,16 @@ begin
else
{ local/global variable or parameter which is not an array }
refsEq := {$ifdef fpc}@{$endif}refsEqual;
invalsmemwrite :=
assigned(c.memwrite) and
((not(cs_uncertainOpts in aktglobalswitches) and
containsPointerRef(c.memwrite)) or
refsEq(c.memwrite.oper[1].ref^,ref));
if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
begin
writeToMemDestroysContents := false;
exit;
end;
{ write something to a parameter, a local or global variable, so }
{ * with uncertain optimizations on: }
@ -1785,7 +1797,7 @@ begin
)
)
)
)
);
end
else
{ write something to a pointer location, so }
@ -1794,15 +1806,26 @@ begin
{ a parameter, except if DestroyRefs is called because of a "movsl" }
{ * with uncertain optimzations off: }
{ - destroy every register which contains a memory location }
with c do
writeToMemDestroysContents :=
(typ in [con_ref,con_noRemoveRef]) and
begin
invalsmemwrite :=
assigned(c.memwrite) and
(not(cs_UncertainOpts in aktglobalswitches) or
{ for movsl }
((ref.base = R_EDI) and (ref.index = R_EDI)) or
{ don't destroy if reg contains a parameter, local or global variable }
containsPointerLoad(c)
)
containsPointerRef(c.memwrite));
if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
begin
writeToMemDestroysContents := false;
exit;
end;
with c do
writeToMemDestroysContents :=
(typ in [con_ref,con_noRemoveRef]) and
(not(cs_UncertainOpts in aktglobalswitches) or
{ for movsl }
((ref.base = R_EDI) and (ref.index = R_EDI)) or
{ don't destroy if reg contains a parameter, local or global variable }
containsPointerLoad(c)
);
end;
end;
function writeToRegDestroysContents(destReg: tregister; reg: tregister;
@ -1819,6 +1842,8 @@ function writeDestroysContents(const op: toper; reg: tregister;
const c: tcontent): boolean;
{ returns whether the contents c of reg are invalid after regWritten is }
{ is written to op }
var
dummy: boolean;
begin
reg := reg32(reg);
case op.typ of
@ -1827,7 +1852,7 @@ begin
writeToRegDestroysContents(op.reg,reg,c);
top_ref:
writeDestroysContents :=
writeToMemDestroysContents(R_NO,op.ref^,reg,c);
writeToMemDestroysContents(R_NO,op.ref^,reg,c,dummy);
else
writeDestroysContents := false;
end;
@ -1839,11 +1864,16 @@ procedure destroyRefs(p: Tai; const ref: treference; regWritten: tregister);
{ is called because of a "mov?? %reg, (mem)" instruction) }
var
counter: TRegister;
destroymemwrite: boolean;
begin
for counter := R_EAX to R_EDI Do
if writeToMemDestroysContents(regWritten,ref,counter,
pTaiProp(p.optInfo)^.regs[counter]) then
destroyReg(pTaiProp(p.optInfo), counter, false)
begin
if writeToMemDestroysContents(regWritten,ref,counter,
pTaiProp(p.optInfo)^.regs[counter],destroymemwrite) then
destroyReg(pTaiProp(p.optInfo), counter, false)
else if destroymemwrite then
pTaiProp(p.optinfo)^.regs[counter].MemWrite := nil;
end;
End;
Procedure DestroyAllRegs(p: PTaiProp);
@ -1853,6 +1883,7 @@ Begin {initializes/desrtoys all registers}
Begin
ReadReg(p, Counter);
DestroyReg(p, Counter, true);
p^.regs[counter].MemWrite := nil;
End;
p^.DirFlag := F_Unknown;
End;
@ -1914,6 +1945,7 @@ Begin
PTaiProp(Tai(StartMod).OptInfo)^.Regs[Reg].NrOfMods := NrOfMods;
NrOfInstrSinceLastMod[Reg] := 0;
invalidateDependingRegs(p.optinfo,reg);
pTaiprop(p.optinfo)^.regs[reg].memwrite := nil;
{$ifdef StateDebug}
hp := Tai_asm_comment.Create(strpnew(att_reg2str[reg]+': '+tostr(PTaiProp(p.optinfo)^.Regs[reg].WState)
+ ' -- ' + tostr(PTaiProp(p.optinfo)^.Regs[reg].nrofmods))));
@ -2237,6 +2269,7 @@ Begin
{ that depended on the previous value of }
{ this register }
invalidateDependingRegs(curprop,tmpreg);
curprop^.regs[tmpreg].memwrite := nil;
end;
end
else
@ -2260,11 +2293,17 @@ Begin
{$endif StateDebug}
End;
Top_Ref:
{ can only be if oper[0] = top_reg }
Begin
ReadReg(CurProp, Taicpu(p).oper[0].reg);
ReadRef(CurProp, Taicpu(p).oper[1].ref);
DestroyRefs(p, Taicpu(p).oper[1].ref^, Taicpu(p).oper[0].reg);
if taicpu(p).oper[0].typ = top_reg then
begin
ReadReg(CurProp, Taicpu(p).oper[0].reg);
DestroyRefs(p, Taicpu(p).oper[1].ref^, Taicpu(p).oper[0].reg);
pTaiProp(p.optinfo)^.regs[reg32(Taicpu(p).oper[0].reg)].memwrite :=
Taicpu(p);
end
else
DestroyRefs(p, Taicpu(p).oper[1].ref^, R_NO);
End;
End;
top_symbol,Top_Const:
@ -2552,7 +2591,10 @@ End.
{
$Log$
Revision 1.22 2001-10-12 13:58:05 jonas
Revision 1.23 2001-10-27 10:20:43 jonas
+ replace mem accesses to locations to which a reg was stored recently with that reg
Revision 1.22 2001/10/12 13:58:05 jonas
+ memory references are now replaced by register reads in "regular"
instructions (e.g. "addl ref1,%eax" will be replaced by "addl %ebx,%eax"
if %ebx contains ref1). Previously only complete load sequences were