mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 07:46:00 +02:00
+ writeToMemDestroysContents() and writeDestroysContents() to support the
new features of the CSE
This commit is contained in:
parent
8eb96135c8
commit
ec5edf7be2
@ -33,61 +33,6 @@ Uses
|
|||||||
CObjects,Aasm,
|
CObjects,Aasm,
|
||||||
cpubase,cpuasm;
|
cpubase,cpuasm;
|
||||||
|
|
||||||
Type
|
|
||||||
TRegArray = Array[R_EAX..R_BL] of TRegister;
|
|
||||||
TRegSet = Set of R_EAX..R_BL;
|
|
||||||
TRegInfo = Record
|
|
||||||
NewRegsEncountered, OldRegsEncountered: TRegSet;
|
|
||||||
RegsLoadedForRef: TRegSet;
|
|
||||||
regsStillUsedAfterSeq: TRegSet;
|
|
||||||
lastReload: array[R_EAX..R_EDI] of pai;
|
|
||||||
New2OldReg: TRegArray;
|
|
||||||
End;
|
|
||||||
|
|
||||||
{possible actions on an operand: read, write or modify (= read & write)}
|
|
||||||
TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
|
|
||||||
|
|
||||||
{*********************** Procedures and Functions ************************}
|
|
||||||
|
|
||||||
Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
|
|
||||||
|
|
||||||
Function Reg32(Reg: TRegister): TRegister;
|
|
||||||
Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
|
|
||||||
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
|
||||||
Function IsGP32Reg(Reg: TRegister): Boolean;
|
|
||||||
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
|
||||||
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
|
||||||
function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
|
||||||
function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
|
||||||
function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
|
||||||
|
|
||||||
Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
|
|
||||||
Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
|
|
||||||
Procedure SkipHead(var P: Pai);
|
|
||||||
function labelCanBeSkipped(p: pai_label): boolean;
|
|
||||||
|
|
||||||
Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
|
|
||||||
Function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
|
|
||||||
hp: pai): boolean;
|
|
||||||
Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
|
|
||||||
Procedure AllocRegBetween(AsmL: PAasmOutput; Reg: TRegister; p1, p2: Pai);
|
|
||||||
|
|
||||||
Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
|
|
||||||
Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
|
|
||||||
Function OpsEqual(const o1,o2:toper): Boolean;
|
|
||||||
|
|
||||||
Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
|
|
||||||
Function DFAPass2(
|
|
||||||
{$ifdef statedebug}
|
|
||||||
AsmL: PAasmOutPut;
|
|
||||||
{$endif statedebug}
|
|
||||||
BlockStart, BlockEnd: Pai): Boolean;
|
|
||||||
Procedure ShutDownDFA;
|
|
||||||
|
|
||||||
Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean;
|
|
||||||
|
|
||||||
Procedure IncState(Var S: Byte; amount: longint);
|
|
||||||
|
|
||||||
{******************************* Constants *******************************}
|
{******************************* Constants *******************************}
|
||||||
|
|
||||||
Const
|
Const
|
||||||
@ -108,6 +53,19 @@ Const
|
|||||||
{********************************* Types *********************************}
|
{********************************* Types *********************************}
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TRegArray = Array[R_EAX..R_BL] of TRegister;
|
||||||
|
TRegSet = Set of R_EAX..R_BL;
|
||||||
|
TRegInfo = Record
|
||||||
|
NewRegsEncountered, OldRegsEncountered: TRegSet;
|
||||||
|
RegsLoadedForRef: TRegSet;
|
||||||
|
regsStillUsedAfterSeq: TRegSet;
|
||||||
|
lastReload: array[R_EAX..R_EDI] of pai;
|
||||||
|
New2OldReg: TRegArray;
|
||||||
|
End;
|
||||||
|
|
||||||
|
{possible actions on an operand: read, write or modify (= read & write)}
|
||||||
|
TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
|
||||||
|
|
||||||
{the possible states of a flag}
|
{the possible states of a flag}
|
||||||
TFlagContents = (F_Unknown, F_NotSet, F_Set);
|
TFlagContents = (F_Unknown, F_NotSet, F_Set);
|
||||||
|
|
||||||
@ -192,6 +150,54 @@ type
|
|||||||
TLabelTable = Array[0..2500000] Of TLabelTableItem;
|
TLabelTable = Array[0..2500000] Of TLabelTableItem;
|
||||||
PLabelTable = ^TLabelTable;
|
PLabelTable = ^TLabelTable;
|
||||||
|
|
||||||
|
|
||||||
|
{*********************** Procedures and Functions ************************}
|
||||||
|
|
||||||
|
Procedure InsertLLItem(AsmL: PAasmOutput; prev, foll, new_one: PLinkedList_Item);
|
||||||
|
|
||||||
|
Function Reg32(Reg: TRegister): TRegister;
|
||||||
|
Function RefsEquivalent(Const R1, R2: TReference; Var RegInfo: TRegInfo; OpAct: TOpAction): Boolean;
|
||||||
|
Function RefsEqual(Const R1, R2: TReference): Boolean;
|
||||||
|
Function IsGP32Reg(Reg: TRegister): Boolean;
|
||||||
|
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
|
||||||
|
function RegReadByInstruction(reg: TRegister; hp: pai): boolean;
|
||||||
|
function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||||
|
function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
|
||||||
|
function RegInOp(Reg: TRegister; const o:toper): Boolean;
|
||||||
|
|
||||||
|
function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
|
||||||
|
reg: tregister; const c: tcontent): boolean;
|
||||||
|
function writeDestroysContents(const op: toper; reg: tregister;
|
||||||
|
const c: tcontent): boolean;
|
||||||
|
|
||||||
|
|
||||||
|
Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
|
||||||
|
Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
|
||||||
|
Procedure SkipHead(var P: Pai);
|
||||||
|
function labelCanBeSkipped(p: pai_label): boolean;
|
||||||
|
|
||||||
|
Procedure RemoveLastDeallocForFuncRes(asmL: PAasmOutput; p: pai);
|
||||||
|
Function regLoadedWithNewValue(reg: tregister; canDependOnPrevValue: boolean;
|
||||||
|
hp: pai): boolean;
|
||||||
|
Procedure UpdateUsedRegs(Var UsedRegs: TRegSet; p: Pai);
|
||||||
|
Procedure AllocRegBetween(AsmL: PAasmOutput; Reg: TRegister; p1, p2: Pai);
|
||||||
|
|
||||||
|
Function RegsEquivalent(OldReg, NewReg: TRegister; Var RegInfo: TRegInfo; OpAct: TopAction): Boolean;
|
||||||
|
Function InstructionsEquivalent(p1, p2: Pai; Var RegInfo: TRegInfo): Boolean;
|
||||||
|
Function OpsEqual(const o1,o2:toper): Boolean;
|
||||||
|
|
||||||
|
Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
|
||||||
|
Function DFAPass2(
|
||||||
|
{$ifdef statedebug}
|
||||||
|
AsmL: PAasmOutPut;
|
||||||
|
{$endif statedebug}
|
||||||
|
BlockStart, BlockEnd: Pai): Boolean;
|
||||||
|
Procedure ShutDownDFA;
|
||||||
|
|
||||||
|
Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean;
|
||||||
|
|
||||||
|
Procedure IncState(Var S: Byte; amount: longint);
|
||||||
|
|
||||||
{******************************* Variables *******************************}
|
{******************************* Variables *******************************}
|
||||||
|
|
||||||
Var
|
Var
|
||||||
@ -1261,7 +1267,10 @@ Begin
|
|||||||
typ := con_unknown;
|
typ := con_unknown;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
typ := con_invalid;
|
if typ in [con_ref,con_invalid] then
|
||||||
|
typ := con_invalid
|
||||||
|
{ con_invalid and con_noRemoveRef = con_unknown }
|
||||||
|
else typ := con_unknown;
|
||||||
end;
|
end;
|
||||||
invalidateDepedingRegs(p1,reg);
|
invalidateDepedingRegs(p1,reg);
|
||||||
end;
|
end;
|
||||||
@ -1549,79 +1558,112 @@ Begin
|
|||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
||||||
Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichReg: TRegister);
|
function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
|
||||||
{destroys all registers which possibly contain a reference to Ref, WhichReg
|
reg: tregister; const c: tcontent): boolean;
|
||||||
is the register whose contents are being written to memory (if this proc
|
{ returns whether the contents c of reg are invalid after regWritten is }
|
||||||
is called because of a "mov?? %reg, (mem)" instruction)}
|
{ is written to ref }
|
||||||
Var RefsEq: TRefCompare;
|
var
|
||||||
Counter: TRegister;
|
refsEq: trefCompare;
|
||||||
Begin
|
begin
|
||||||
WhichReg := Reg32(WhichReg);
|
if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
|
||||||
If (Ref.base = procinfo^.FramePointer) or
|
begin
|
||||||
Assigned(Ref.Symbol) Then
|
writeToMemDestroysContents := false;
|
||||||
Begin
|
exit;
|
||||||
If (ref.index <> R_NO) or
|
end;
|
||||||
|
reg := reg32(reg);
|
||||||
|
regWritten := reg32(regWritten);
|
||||||
|
if (ref.base = procinfo^.framePointer) or
|
||||||
|
assigned(ref.symbol) Then
|
||||||
|
begin
|
||||||
|
if (ref.index <> R_NO) or
|
||||||
(assigned(ref.symbol) and
|
(assigned(ref.symbol) and
|
||||||
(ref.base <> R_NO)) then
|
(ref.base <> R_NO)) then
|
||||||
{ local/global variable or parameter which is an array }
|
{ local/global variable or parameter which is an array }
|
||||||
RefsEq := {$ifdef fpc}@{$endif}ArrayRefsEq
|
refsEq := {$ifdef fpc}@{$endif}arrayRefsEq
|
||||||
Else
|
else
|
||||||
{ local/global variable or parameter which is not an array }
|
{ local/global variable or parameter which is not an array }
|
||||||
RefsEq := {$ifdef fpc}@{$endif}RefsEqual;
|
refsEq := {$ifdef fpc}@{$endif}refsEqual;
|
||||||
|
|
||||||
{write something to a parameter, a local or global variable, so
|
{ write something to a parameter, a local or global variable, so }
|
||||||
* with uncertain optimizations on:
|
{ * with uncertain optimizations on: }
|
||||||
- destroy the contents of registers whose contents have somewhere a
|
{ - destroy the contents of registers whose contents have somewhere a }
|
||||||
"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)
|
{ pointer 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 }
|
||||||
For Counter := R_EAX to R_EDI Do
|
with c do
|
||||||
With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
|
writeToMemDestroysContents :=
|
||||||
Begin
|
(typ in [con_ref,con_noRemoveRef]) and
|
||||||
if (typ in [con_ref,con_noRemoveRef]) and
|
((not(cs_uncertainOpts in aktglobalswitches) and
|
||||||
((Not(cs_UncertainOpts in aktglobalswitches) And
|
(nrOfMods <> 1)
|
||||||
(NrOfMods <> 1)
|
) or
|
||||||
) Or
|
(refInSequence(ref,c,refsEq) and
|
||||||
(RefInSequence(Ref,PPaiProp(p^.OptInfo)^.Regs[Counter],RefsEq) And
|
((reg <> regWritten) or
|
||||||
((Counter <> WhichReg) Or
|
((nrOfMods <> 1) and
|
||||||
((NrOfMods <> 1) And
|
|
||||||
{StarMod is always of the type ait_instruction}
|
{StarMod is always of the type ait_instruction}
|
||||||
(Paicpu(StartMod)^.oper[0].typ = top_ref) And
|
(paicpu(StartMod)^.oper[0].typ = top_ref) and
|
||||||
RefsEq(Paicpu(StartMod)^.oper[0].ref^, Ref)
|
refsEq(Paicpu(StartMod)^.oper[0].ref^, ref)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Then
|
end
|
||||||
DestroyReg(PPaiProp(p^.OptInfo), Counter, false)
|
else
|
||||||
End
|
{ write something to a pointer location, so }
|
||||||
End
|
{ * with uncertain optimzations on: }
|
||||||
Else
|
{ - do not destroy registers which contain a local/global variable or }
|
||||||
{write something to a pointer location, so
|
{ a parameter, except if DestroyRefs is called because of a "movsl" }
|
||||||
* with uncertain optimzations on:
|
{ * with uncertain optimzations off: }
|
||||||
- do not destroy registers which contain a local/global variable or a
|
{ - destroy every register which contains a memory location }
|
||||||
parameter, except if DestroyRefs is called because of a "movsl"
|
with c do
|
||||||
* with uncertain optimzations off:
|
writeToMemDestroysContents :=
|
||||||
- destroy every register which contains a memory location
|
(typ in [con_ref,con_noRemoveRef]) and
|
||||||
}
|
(not(cs_UncertainOpts in aktglobalswitches) or
|
||||||
For Counter := R_EAX to R_EDI Do
|
{ for movsl }
|
||||||
With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
|
((ref.base = R_EDI) and (ref.index = R_EDI)) or
|
||||||
if (typ in [con_ref,con_noRemoveRef]) And
|
{ don't destroy if reg contains a parameter, local or global variable }
|
||||||
(Not(cs_UncertainOpts in aktglobalswitches) Or
|
not((nrOfMods = 1) and
|
||||||
{for movsl}
|
(paicpu(startMod)^.oper[0].typ = top_ref) and
|
||||||
(Ref.Base = R_EDI) Or
|
((paicpu(startMod)^.oper[0].ref^.base = procinfo^.framePointer) or
|
||||||
{don't destroy if reg contains a parameter, local or global variable}
|
assigned(paicpu(startMod)^.oper[0].ref^.symbol)
|
||||||
Not((NrOfMods = 1) And
|
|
||||||
(Paicpu(StartMod)^.oper[0].typ = top_ref) And
|
|
||||||
((Paicpu(StartMod)^.oper[0].ref^.base = procinfo^.FramePointer) Or
|
|
||||||
Assigned(Paicpu(StartMod)^.oper[0].ref^.Symbol)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
Then DestroyReg(PPaiProp(p^.OptInfo), Counter, false)
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
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 }
|
||||||
|
begin
|
||||||
|
reg := reg32(reg);
|
||||||
|
case op.typ of
|
||||||
|
top_reg:
|
||||||
|
writeDestroysContents :=
|
||||||
|
(c.typ <> con_unknown) and
|
||||||
|
sequenceDependsOnReg(c,reg,reg32(op.reg));
|
||||||
|
top_ref:
|
||||||
|
writeDestroysContents :=
|
||||||
|
writeToMemDestroysContents(R_NO,op.ref^,reg,c);
|
||||||
|
else
|
||||||
|
writeDestroysContents := false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure destroyRefs(p: pai; const ref: treference; regWritten: tregister);
|
||||||
|
{ destroys all registers which possibly contain a reference to Ref, regWritten }
|
||||||
|
{ is the register whose contents are being written to memory (if this proc }
|
||||||
|
{ is called because of a "mov?? %reg, (mem)" instruction) }
|
||||||
|
var
|
||||||
|
counter: TRegister;
|
||||||
|
begin
|
||||||
|
for counter := R_EAX to R_EDI Do
|
||||||
|
if writeToMemDestroysContents(regWritten,ref,counter,
|
||||||
|
ppaiProp(p^.optInfo)^.regs[counter]) then
|
||||||
|
destroyReg(ppaiProp(p^.optInfo), counter, false)
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Procedure DestroyAllRegs(p: PPaiProp);
|
Procedure DestroyAllRegs(p: PPaiProp);
|
||||||
@ -2184,6 +2226,7 @@ Begin
|
|||||||
ReadReg(CurProp, R_EDI);
|
ReadReg(CurProp, R_EDI);
|
||||||
FillChar(TmpRef, SizeOf(TmpRef), 0);
|
FillChar(TmpRef, SizeOf(TmpRef), 0);
|
||||||
TmpRef.Base := R_EDI;
|
TmpRef.Base := R_EDI;
|
||||||
|
tmpRef.index := R_EDI;
|
||||||
DestroyRefs(p, TmpRef, R_NO)
|
DestroyRefs(p, TmpRef, R_NO)
|
||||||
End;
|
End;
|
||||||
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:
|
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU:
|
||||||
@ -2306,7 +2349,11 @@ End.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.13 2000-09-25 09:50:30 jonas
|
Revision 1.14 2000-09-29 23:14:11 jonas
|
||||||
|
+ writeToMemDestroysContents() and writeDestroysContents() to support the
|
||||||
|
new features of the CSE
|
||||||
|
|
||||||
|
Revision 1.13 2000/09/25 09:50:30 jonas
|
||||||
- removed TP conditional code
|
- removed TP conditional code
|
||||||
|
|
||||||
Revision 1.12 2000/09/24 21:19:50 peter
|
Revision 1.12 2000/09/24 21:19:50 peter
|
||||||
|
Loading…
Reference in New Issue
Block a user