mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-12 22:49:20 +02:00
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:
parent
8f0c7e6788
commit
b5a390c026
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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: }
|
||||
|
@ -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
20
tests/webtbs/tw5094.pp
Normal 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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user