mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 23:49:22 +02:00
* fixed bug in arrayRefsEq
* object/class fields are now handled the same as local/global vars and parameters (ie. a write to a local var can now never destroy a class field)
This commit is contained in:
parent
5be6c35518
commit
767ecef9bb
@ -1593,10 +1593,65 @@ Begin
|
|||||||
ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
|
ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
|
||||||
(R1.Segment = R2.Segment) And
|
(R1.Segment = R2.Segment) And
|
||||||
(R1.Symbol=R2.Symbol) And
|
(R1.Symbol=R2.Symbol) And
|
||||||
((Assigned(R1.Symbol)) Or
|
(R1.Base = R2.Base)
|
||||||
(R1.Base = R2.Base))
|
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
function isSimpleRef(const ref: treference): boolean;
|
||||||
|
{ returns true if ref is reference to a local or global variable, to a }
|
||||||
|
{ parameter or to an object field (this includes arrays). Returns false }
|
||||||
|
{ otherwise. }
|
||||||
|
begin
|
||||||
|
isSimpleRef :=
|
||||||
|
assigned(ref.symbol) or
|
||||||
|
(ref.base = procinfo^.framepointer) or
|
||||||
|
(assigned(procinfo^._class) and
|
||||||
|
(ref.base = R_ESI));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function containsPointerRef(p: pai): boolean;
|
||||||
|
{ checks if an instruction contains a reference which is a pointer location }
|
||||||
|
var
|
||||||
|
hp: paicpu;
|
||||||
|
count: longint;
|
||||||
|
begin
|
||||||
|
containsPointerRef := false;
|
||||||
|
if p^.typ <> ait_instruction then
|
||||||
|
exit;
|
||||||
|
hp := paicpu(p);
|
||||||
|
for count := 0 to high(hp^.ops) do
|
||||||
|
begin
|
||||||
|
case hp^.oper[count].typ of
|
||||||
|
top_ref:
|
||||||
|
if not isSimpleRef(hp^.oper[count].ref^) then
|
||||||
|
begin
|
||||||
|
containsPointerRef := true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
top_none:
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function containsPointerLoad(c: tcontent): boolean;
|
||||||
|
{ checks whether the contents of a register contain a pointer reference }
|
||||||
|
var
|
||||||
|
p: pai;
|
||||||
|
count: longint;
|
||||||
|
begin
|
||||||
|
containsPointerLoad := false;
|
||||||
|
p := c.startmod;
|
||||||
|
for count := c.nrOfMods downto 1 do
|
||||||
|
begin
|
||||||
|
if containsPointerRef(p) then
|
||||||
|
begin
|
||||||
|
containsPointerLoad := true;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
getnextinstruction(p,p);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
|
function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
|
||||||
reg: tregister; const c: tcontent): boolean;
|
reg: tregister; const c: tcontent): boolean;
|
||||||
@ -1612,8 +1667,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
reg := reg32(reg);
|
reg := reg32(reg);
|
||||||
regWritten := reg32(regWritten);
|
regWritten := reg32(regWritten);
|
||||||
if (ref.base = procinfo^.framePointer) or
|
if isSimpleRef(ref) then
|
||||||
assigned(ref.symbol) Then
|
|
||||||
begin
|
begin
|
||||||
if (ref.index <> R_NO) or
|
if (ref.index <> R_NO) or
|
||||||
(assigned(ref.symbol) and
|
(assigned(ref.symbol) and
|
||||||
@ -1630,14 +1684,14 @@ begin
|
|||||||
{ "mov?? (Ref), %reg". WhichReg (this is the register whose contents }
|
{ "mov?? (Ref), %reg". WhichReg (this is the register whose contents }
|
||||||
{ are being written to memory) is not destroyed if it's StartMod is }
|
{ are being written to memory) is not destroyed if it's StartMod is }
|
||||||
{ of that form and NrOfMods = 1 (so if it holds ref, but is not a }
|
{ of that form and NrOfMods = 1 (so if it holds ref, but is not a }
|
||||||
{ pointer based on Ref) }
|
{ expression based on Ref) }
|
||||||
{ * with uncertain optimizations off: }
|
{ * with uncertain optimizations off: }
|
||||||
{ - also destroy registers that contain any pointer }
|
{ - also destroy registers that contain any pointer }
|
||||||
with c do
|
with c do
|
||||||
writeToMemDestroysContents :=
|
writeToMemDestroysContents :=
|
||||||
(typ in [con_ref,con_noRemoveRef]) and
|
(typ in [con_ref,con_noRemoveRef]) and
|
||||||
((not(cs_uncertainOpts in aktglobalswitches) and
|
((not(cs_uncertainOpts in aktglobalswitches) and
|
||||||
(nrOfMods <> 1)
|
containsPointerLoad(c)
|
||||||
) or
|
) or
|
||||||
(refInSequence(ref,c,refsEq) and
|
(refInSequence(ref,c,refsEq) and
|
||||||
((reg <> regWritten) or
|
((reg <> regWritten) or
|
||||||
@ -1662,15 +1716,10 @@ begin
|
|||||||
(typ in [con_ref,con_noRemoveRef]) and
|
(typ in [con_ref,con_noRemoveRef]) and
|
||||||
(not(cs_UncertainOpts in aktglobalswitches) or
|
(not(cs_UncertainOpts in aktglobalswitches) or
|
||||||
{ for movsl }
|
{ for movsl }
|
||||||
((ref.base = R_EDI) and (ref.index = R_EDI)) or
|
((ref.base = R_EDI) and (ref.index = R_EDI)) or
|
||||||
{ don't destroy if reg contains a parameter, local or global variable }
|
{ don't destroy if reg contains a parameter, local or global variable }
|
||||||
not((nrOfMods = 1) and
|
containsPointerLoad(c)
|
||||||
(paicpu(startMod)^.oper[0].typ = top_ref) and
|
)
|
||||||
((paicpu(startMod)^.oper[0].ref^.base = procinfo^.framePointer) or
|
|
||||||
assigned(paicpu(startMod)^.oper[0].ref^.symbol)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function writeToRegDestroysContents(destReg: tregister; reg: tregister;
|
function writeToRegDestroysContents(destReg: tregister; reg: tregister;
|
||||||
@ -2387,7 +2436,13 @@ End.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.3 2000-10-24 10:40:53 jonas
|
Revision 1.4 2000-11-03 18:06:26 jonas
|
||||||
|
* fixed bug in arrayRefsEq
|
||||||
|
* object/class fields are now handled the same as local/global vars and
|
||||||
|
parameters (ie. a write to a local var can now never destroy a class
|
||||||
|
field)
|
||||||
|
|
||||||
|
Revision 1.3 2000/10/24 10:40:53 jonas
|
||||||
+ register renaming ("fixes" bug1088)
|
+ register renaming ("fixes" bug1088)
|
||||||
* changed command line options meanings for optimizer:
|
* changed command line options meanings for optimizer:
|
||||||
O2 now means peepholopts, CSE and register renaming in 1 pass
|
O2 now means peepholopts, CSE and register renaming in 1 pass
|
||||||
|
Loading…
Reference in New Issue
Block a user