|
@@ -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);
|
|
|
|
-{destroys all registers which possibly contain a reference to Ref, WhichReg
|
|
|
|
- is the register whose contents are being written to memory (if this proc
|
|
|
|
- is called because of a "mov?? %reg, (mem)" instruction)}
|
|
|
|
-Var RefsEq: TRefCompare;
|
|
|
|
- Counter: TRegister;
|
|
|
|
-Begin
|
|
|
|
- WhichReg := Reg32(WhichReg);
|
|
|
|
- If (Ref.base = procinfo^.FramePointer) or
|
|
|
|
- Assigned(Ref.Symbol) Then
|
|
|
|
- Begin
|
|
|
|
- If (ref.index <> R_NO) or
|
|
|
|
|
|
+function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
|
|
|
|
+ reg: tregister; const c: tcontent): 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 (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 }
|
|
|
|
- RefsEq := {$ifdef fpc}@{$endif}ArrayRefsEq
|
|
|
|
- Else
|
|
|
|
- { local/global variable or parameter which is not an array }
|
|
|
|
- RefsEq := {$ifdef fpc}@{$endif}RefsEqual;
|
|
|
|
-
|
|
|
|
-{write something to a parameter, a local or global variable, so
|
|
|
|
- * with uncertain optimizations on:
|
|
|
|
- - destroy the contents of registers whose contents have somewhere a
|
|
|
|
- "mov?? (Ref), %reg". WhichReg (this is the register whose contents
|
|
|
|
- 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
|
|
|
|
- pointer based on Ref)
|
|
|
|
- * with uncertain optimizations off:
|
|
|
|
- - also destroy registers that contain any pointer}
|
|
|
|
- For Counter := R_EAX to R_EDI Do
|
|
|
|
- With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
|
|
|
|
- Begin
|
|
|
|
- if (typ in [con_ref,con_noRemoveRef]) and
|
|
|
|
- ((Not(cs_UncertainOpts in aktglobalswitches) And
|
|
|
|
- (NrOfMods <> 1)
|
|
|
|
- ) Or
|
|
|
|
- (RefInSequence(Ref,PPaiProp(p^.OptInfo)^.Regs[Counter],RefsEq) And
|
|
|
|
- ((Counter <> WhichReg) Or
|
|
|
|
- ((NrOfMods <> 1) And
|
|
|
|
- {StarMod is always of the type ait_instruction}
|
|
|
|
- (Paicpu(StartMod)^.oper[0].typ = top_ref) And
|
|
|
|
- RefsEq(Paicpu(StartMod)^.oper[0].ref^, Ref)
|
|
|
|
- )
|
|
|
|
- )
|
|
|
|
- )
|
|
|
|
- )
|
|
|
|
- Then
|
|
|
|
- DestroyReg(PPaiProp(p^.OptInfo), Counter, false)
|
|
|
|
- End
|
|
|
|
- End
|
|
|
|
- Else
|
|
|
|
-{write something to a pointer location, so
|
|
|
|
- * with uncertain optimzations on:
|
|
|
|
- - do not destroy registers which contain a local/global variable or a
|
|
|
|
- parameter, except if DestroyRefs is called because of a "movsl"
|
|
|
|
- * with uncertain optimzations off:
|
|
|
|
- - destroy every register which contains a memory location
|
|
|
|
- }
|
|
|
|
- For Counter := R_EAX to R_EDI Do
|
|
|
|
- With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
|
|
|
|
- if (typ in [con_ref,con_noRemoveRef]) And
|
|
|
|
- (Not(cs_UncertainOpts in aktglobalswitches) Or
|
|
|
|
- {for movsl}
|
|
|
|
- (Ref.Base = R_EDI) Or
|
|
|
|
- {don't destroy if reg contains a parameter, local or global variable}
|
|
|
|
- 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)
|
|
|
|
- )
|
|
|
|
|
|
+ { local/global variable or parameter which is an array }
|
|
|
|
+ refsEq := {$ifdef fpc}@{$endif}arrayRefsEq
|
|
|
|
+ else
|
|
|
|
+ { local/global variable or parameter which is not an array }
|
|
|
|
+ refsEq := {$ifdef fpc}@{$endif}refsEqual;
|
|
|
|
+
|
|
|
|
+ { write something to a parameter, a local or global variable, so }
|
|
|
|
+ { * with uncertain optimizations on: }
|
|
|
|
+ { - destroy the contents of registers whose contents have somewhere a }
|
|
|
|
+ { "mov?? (Ref), %reg". WhichReg (this is the register whose contents }
|
|
|
|
+ { 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 }
|
|
|
|
+ { pointer based on Ref) }
|
|
|
|
+ { * with uncertain optimizations off: }
|
|
|
|
+ { - also destroy registers that contain any pointer }
|
|
|
|
+ with c do
|
|
|
|
+ writeToMemDestroysContents :=
|
|
|
|
+ (typ in [con_ref,con_noRemoveRef]) and
|
|
|
|
+ ((not(cs_uncertainOpts in aktglobalswitches) and
|
|
|
|
+ (nrOfMods <> 1)
|
|
|
|
+ ) or
|
|
|
|
+ (refInSequence(ref,c,refsEq) and
|
|
|
|
+ ((reg <> regWritten) or
|
|
|
|
+ ((nrOfMods <> 1) and
|
|
|
|
+ {StarMod is always of the type ait_instruction}
|
|
|
|
+ (paicpu(StartMod)^.oper[0].typ = top_ref) and
|
|
|
|
+ refsEq(Paicpu(StartMod)^.oper[0].ref^, ref)
|
|
)
|
|
)
|
|
- )
|
|
|
|
- Then DestroyReg(PPaiProp(p^.OptInfo), Counter, false)
|
|
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ { write something to a pointer location, so }
|
|
|
|
+ { * with uncertain optimzations on: }
|
|
|
|
+ { - do not destroy registers which contain a local/global variable or }
|
|
|
|
+ { 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
|
|
|
|
+ (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 }
|
|
|
|
+ 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)
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+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
|