Merged revisions 3329,3480,3644 via svnmerge from

svn+ssh://jonas@svn.freepascal.org/FPC/svn/fpc/trunk

........
r3329 | jonas | 2006-04-24 13:12:17 +0200 (Mon, 24 Apr 2006) | 5 lines

  * when restoring a register's previous contents after it's been replaced
    completely, there were some missing checks to make certain these
    previous contents didn't conflict with memory operations in the new
    sequence

........
r3480 | jonas | 2006-05-11 18:46:58 +0200 (Thu, 11 May 2006) | 4 lines

  * if while we are restoring the contents of a register, we encounter an
    operation which changes a register, clear the contents of all registers
    which depend on this register

........
r3644 | jonas | 2006-05-23 19:17:23 +0200 (Tue, 23 May 2006) | 4 lines

  * fixed web bug #5094. Renaming registers is now done sequentially instead
    of all at the same time, because otherwise circular renamings could
    cause errors

........

git-svn-id: branches/fixes_2_0@3645 -
This commit is contained in:
Jonas Maebe 2006-05-23 18:00:11 +00:00
parent 8f0c7e6788
commit b5a390c026
4 changed files with 135 additions and 67 deletions

1
.gitattributes vendored
View File

@ -6488,6 +6488,7 @@ tests/webtbs/tw4950.pp svneol=native#text/plain
tests/webtbs/tw4999.pp svneol=native#text/plain
tests/webtbs/tw5036.pp svneol=native#text/plain
tests/webtbs/tw5082.pp -text svneol=unset#text/plain
tests/webtbs/tw5094.pp -text
tests/webtbs/tw6435.pp svneol=native#text/plain
tests/webtbs/tw6735.pp svneol=native#text/plain
tests/webtbs/tw6960.pp svneol=native#text/plain

View File

@ -842,6 +842,7 @@ var
{$endif replaceregdebug}
regcounter: tsuperregister;
oldStartmod: tai;
regstoclear: tregset;
begin
{$ifdef replaceregdebug}
l := random(1000);
@ -850,26 +851,43 @@ begin
insertllitem(asml,p.previous,p,hp);
{$endif replaceregdebug}
ptaiprop(p.optinfo)^.Regs[supreg].typ := con_unknown;
regstoclear := [supreg];
while (p <> endP) do
begin
for regcounter := RS_EAX to RS_EDI do
if (regcounter <> supreg) and
assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
clearmemwrites(p,regcounter);
with ptaiprop(p.optinfo)^.Regs[supreg] do
begin
typ := con_unknown;
memwrite := nil;
if (regcounter <> supreg) and
assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
clearmemwrites(p,regcounter);
{ needs double loop to cheack for each dependency combination? }
if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
include(regstoclear,regcounter);
if regcounter in regstoclear then
with ptaiprop(p.optinfo)^.Regs[regcounter] do
begin
typ := con_unknown;
memwrite := nil;
end;
end;
getNextInstruction(p,p);
end;
oldStartmod := ptaiprop(p.optinfo)^.Regs[supreg].startmod;
repeat
with ptaiprop(p.optinfo)^.Regs[supreg] do
for regcounter := RS_EAX to RS_EDI do
begin
typ := con_unknown;
memwrite := nil;
{ needs double loop to cheack for each dependency combination? }
if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
include(regstoclear,regcounter);
with ptaiprop(p.optinfo)^.Regs[supreg] do
if regcounter in regstoclear then
begin
typ := con_unknown;
memwrite := nil;
end;
end;
until not getNextInstruction(p,p) or
(ptaiprop(p.optinfo)^.Regs[supreg].startmod <> oldStartmod);
@ -889,7 +907,8 @@ var
l: longint;
{$endif replaceregdebug}
hp: tai;
dummyregs: tregset;
validregs, prevvalidregs: tregset;
regcounter: tsuperregister;
tmpState, newrstate: byte;
prevcontenttyp: byte;
memconflict: boolean;
@ -904,15 +923,49 @@ begin
{ ptaiprop(p.optinfo)^.Regs[reg] := c;}
newrstate := c.rstate;
incstate(newrstate,$7f);
while (p <> endP) do
memconflict := false;
invalsmemwrite := false;
validregs := [RS_EAX..RS_EDI];
prevvalidregs := validregs;
while (p <> endP) and
not(memconflict) and
not(invalsmemwrite) 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;
// is this a write to memory that destroys the contents we are restoring?
memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
if (validregs <> prevvalidregs) then
begin
prevvalidregs := validregs >< prevvalidregs;
for regcounter := RS_EAX to RS_EDI do
if regcounter in prevvalidregs then
clearRegContentsFrom(asml,regcounter,p,endP);
end;
prevvalidregs := validregs;
if (not memconflict and not invalsmemwrite) then
begin
ptaiprop(p.optinfo)^.Regs[supreg] := c;
ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
end
else
begin
clearRegContentsFrom(asml,supreg,p,endP);
{$ifdef replaceregdebug}
if assigned(p) then
begin
hp := tai_comment.Create(strpnew(
'stopping restoring of '+std_regname(newreg(R_INTREGISTER,supreg,R_SUBWHOLE))+'because memory conflict... '+tostr(l)));
insertllitem(asml,p,p.next,hp);
end;
{$endif replaceregdebug}
exit
end;
getNextInstruction(p,p);
end;
tmpState := ptaiprop(p.optinfo)^.Regs[supreg].wState;
if (newrstate = ptaiprop(p.optinfo)^.Regs[supreg].rState) then
begin
@ -922,13 +975,20 @@ begin
if (ptaiprop(hp.optinfo)^.regs[supreg].rstate = ptaiprop(p.optinfo)^.regs[supreg].rstate) then
internalerror(2004122710);
end;
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
memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
if (validregs <> prevvalidregs) then
begin
prevvalidregs := validregs >< prevvalidregs;
for regcounter := RS_EAX to RS_EDI do
if regcounter in prevvalidregs then
clearRegContentsFrom(asml,regcounter,p,p);
end;
prevvalidregs := validregs;
if (not memconflict and not invalsmemwrite) then
begin
ptaiprop(p.optinfo)^.Regs[supreg] := c;
ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
@ -1671,59 +1731,45 @@ begin
(reginfo.new2oldreg[regcounter] <> regcounter) then
begin
getLastInstruction(curseqend,hp);
if (curprev <> prevseqstart) or
{not(regCounter in rg.usableregsint + [RS_EDI,RS_ESI]) or}
not(regCounter in [RS_EAX,RS_EBX,RS_ECX,RS_EDX,RS_EDI,RS_ESI]) or
not ReplaceReg(asml,reginfo.new2oldreg[regcounter],
regCounter,hp,curseqstart,
ptaiprop(prevseqstart.optinfo)^.Regs[regCounter],true,hp2) then
begin
opc := A_MOV;
insertpos := prevseq_next;
if assigned(reguses[regcounter]) then
if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
opc := A_XCHG
else
insertpos := tai(reguses[regcounter].next)
else
if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
insertpos := regloads[reginfo.new2oldreg[regcounter]];
hp := Tai_Marker.Create(NoPropInfoStart);
InsertLLItem(asml, insertpos.previous,insertpos, hp);
hp2 := taicpu.Op_Reg_Reg(opc, S_L,
{old reg new reg}
newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
regloads[regcounter] := hp2;
reguses[reginfo.new2oldreg[regcounter]] := hp2;
new(ptaiprop(hp2.optinfo));
ptaiprop(hp2.optinfo)^ := ptaiprop(insertpos.optinfo)^;
ptaiprop(hp2.optinfo)^.canBeRemoved := false;
InsertLLItem(asml, insertpos.previous, insertpos, hp2);
hp := Tai_Marker.Create(NoPropInfoEnd);
InsertLLItem(asml, insertpos.previous, insertpos, hp);
{ adjusts states in previous instruction so that it will }
{ definitely be different from the previous or next state }
incstate(ptaiprop(hp2.optinfo)^.
regs[reginfo.new2oldreg[regcounter]].rstate,20);
incstate(ptaiprop(hp2.optinfo)^.
regs[regCounter].wstate,20);
updateState(reginfo.new2oldreg[regcounter],hp2);
updateState(regcounter,hp2);
end
opc := A_MOV;
insertpos := prevseq_next;
if assigned(reguses[regcounter]) then
if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
opc := A_XCHG
else
insertpos := tai(reguses[regcounter].next)
else
if assigned(regloads[reginfo.new2oldreg[regcounter]]) then
insertpos := regloads[reginfo.new2oldreg[regcounter]];
hp := Tai_Marker.Create(NoPropInfoStart);
InsertLLItem(asml, insertpos.previous,insertpos, hp);
hp2 := taicpu.Op_Reg_Reg(opc, S_L,
{old reg new reg}
newreg(R_INTREGISTER,reginfo.new2oldreg[regcounter],R_SUBWHOLE), newreg(R_INTREGISTER,regcounter,R_SUBWHOLE));
if (opc = A_XCHG) and
(taicpu(regloads[reginfo.new2oldreg[regcounter]]).opcode <> A_XCHG) then
begin
// replace the new register with the old register in the
// sequence itself as well so later comparisons get the
// correct knowledge about which registers are used
hp2 := curseqstart;
// curseqend = instruction following last instruction of this
// sequence
while hp2 <> curseqend do
begin
doreplacereg(taicpu(hp2),regcounter,reginfo.new2oldreg[regcounter]);
getnextinstruction(hp2,hp2);
end;
asml.remove(regloads[reginfo.new2oldreg[regcounter]]);
regloads[reginfo.new2oldreg[regcounter]].free;
regloads[reginfo.new2oldreg[regcounter]] := hp2;
reguses[regcounter] := hp2;
end;
regloads[regcounter] := hp2;
reguses[reginfo.new2oldreg[regcounter]] := hp2;
new(ptaiprop(hp2.optinfo));
ptaiprop(hp2.optinfo)^ := ptaiprop(insertpos.optinfo)^;
ptaiprop(hp2.optinfo)^.canBeRemoved := false;
InsertLLItem(asml, insertpos.previous, insertpos, hp2);
hp := Tai_Marker.Create(NoPropInfoEnd);
InsertLLItem(asml, insertpos.previous, insertpos, hp);
{ adjusts states in previous instruction so that it will }
{ definitely be different from the previous or next state }
incstate(ptaiprop(hp2.optinfo)^.
regs[reginfo.new2oldreg[regcounter]].rstate,20);
incstate(ptaiprop(hp2.optinfo)^.
regs[regCounter].wstate,20);
updateState(reginfo.new2oldreg[regcounter],hp2);
updateState(regcounter,hp2);
end
else
{ imagine the following code: }

View File

@ -186,6 +186,7 @@ function writeToRegDestroysContents(destReg, supreg: tsuperregister;
function writeDestroysContents(const op: toper; supreg: tsuperregister; size: tcgsize;
const c: tcontent; var memwritedestroyed: boolean): boolean;
function sequenceDependsonReg(const Content: TContent; seqreg: tsuperregister; supreg: tsuperregister): Boolean;
function GetNextInstruction(Current: tai; var Next: tai): Boolean;
function GetLastInstruction(Current: tai; var Last: tai): Boolean;

20
tests/webtbs/tw5094.pp Normal file
View File

@ -0,0 +1,20 @@
{ %OPT=-O-2 }
function B(n, k: Integer):Integer;
var
i: Integer;
begin
if k > n-k then
k := n-k;
B := 1;
for i := n-k+1 to n do
B := B * i;
for i := 2 to k do
B := B div i;
end;
begin
if B(0,1) <> 1 then
halt(1); { Should write 1; fpc -O1 binom.pas writes 0 }
end.