* small fix for uncertain optimizations & more cleaning up

This commit is contained in:
Jonas Maebe 1998-09-20 17:12:35 +00:00
parent 0e770798da
commit fccf4109e0
2 changed files with 206 additions and 130 deletions

View File

@ -44,108 +44,30 @@ Function CheckSequence(p: Pai; Reg: TRegister; Var Found: Longint): Boolean;
Found holds the number of instructions between StartMod and EndMod and false
is returned}
Var hp2, hp3, EndMod: Pai;
TmpResult: Boolean;
RegsNotYetChecked: Set Of TRegister;
Counter: Byte;
Function NoChangedRegInRef(oldp, newp: Pai): Boolean;
Var TmpP: Pai;
{checks if the first operator of newp is a reference and in that case checks
whether that reference includes regs that have been changed since oldp. This
to avoid wrong optimizations like
movl 8(%epb), %eax movl 8(%epb), %eax
movl 12(%epb), %edx movl 12(%epb), %edx
movl (%eax,%edx,1), %edi movl (%eax,%edx,1), %edi
pushl %edi being converted to pushl %edi
movl 8(%epb), %eax movl 16(%ebp), %edx
movl 16(%epb), %edx pushl %edi
movl (%eax,%edx,1), %edi
pushl %edi
because first is checked whether %eax isn't changed (it isn't) and
consequently all instructions containg %eax are removed}
Begin
TmpResult := True;
If (Pai(NewP)^.typ = ait_instruction) Then
Case Pai386(NewP)^.op1t Of
Top_Reg:
If (Reg32(TRegister(Pai386(NewP)^.op1)) in RegsNotYetChecked) Then
Begin
RegsNotYetChecked := RegsNotYetChecked - [Reg32(TRegister(Pai386(NewP)^.op1))];
TmpP := NewP;
While GetLastInstruction(TmpP, TmpP) And
PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do;
TmpResult := Assigned(TmpP) And
RegsSameContent(oldp, TmpP, Reg32(TRegister(Pai386(Newp)^.op1)))
End;
Top_Ref:
With TReference(Pai386(NewP)^.op1^) Do
Begin
If (Base in RegsNotYetChecked) And
(Base <> R_NO) Then
Begin
RegsNotYetChecked := RegsNotYetChecked - [Base];
TmpP := NewP;
While GetLastInstruction(TmpP, TmpP) And
PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do;
TmpResult := Assigned(TmpP) And
RegsSameContent(oldp, TmpP, Base)
End;
If TmpResult And
(Index <> R_NO) And
(Index in RegsNotYetChecked) Then
Begin
RegsNotYetChecked := RegsNotYetChecked - [Index];
TmpP := NewP;
While GetLastInstruction(TmpP, TmpP) And
PPaiProp(TmpP^.fileinfo.Line)^.CanBeRemoved Do;
TmpResult := Assigned(TmpP) And
RegsSameContent(oldp, TmpP, Index);
End;
End;
End;
NoChangedRegInRef := TmpResult;
End;
Begin {CheckSequence}
Reg := Reg32(Reg);
Found := 0;
GetLastInstruction(p, hp3);
hp3 := p;
While GetLastInstruction(hp3, hp3) And
PPAiProp(hp3^.fileinfo.line)^.CanBeRemoved Do;
hp2 := PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].StartMod;
EndMod := PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].StartMod;
EndMod := hp2;
If (PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods = 1)
Then Counter := 1
Else
For Counter := 2 to PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods Do
GetNextInstruction(EndMod, EndMod);
hp3 := p;
RegsNotYetChecked := [R_EAX..R_EDI];
While (Found <> Counter) And
InstructionsEqual(hp2, hp3) And
NoChangedRegInRef(EndMod, hp3) Do
InstructionsEqual(hp2, hp3) Do
Begin
If (hp2^.typ = ait_instruction) And
(Pai386(hp2)^._operator in [a_mov, a_movsx, a_movzx]) And
(Pai386(hp2)^.op2t = top_reg)
Then RegsNotYetChecked := RegsNotYetChecked -
[Reg32(TRegister(Pai386(hp2)^.op2))];
GetNextInstruction(hp2, hp2);
GetNextInstruction(hp3, hp3);
Inc(Found)
End;
If (Found <> Counter)
Then
{hack to be able to optimize
mov (mem), reg
mov (reg), reg
mov (reg), reg [*]
test reg, reg and the oposite (where the marked instructions are
jne l1 switched)
mov (mem), reg
mov (reg), reg
movzx (reg), reg [*]}
Begin
If ((Found+1) = Counter) And
Assigned(hp2) And
@ -159,9 +81,19 @@ Begin {CheckSequence}
(Pai386(hp3)^.op1t = top_ref) And
(Pai386(hp3)^.op2t = top_reg) And
(Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And
NoChangedRegInRef(EndMod, hp3)
RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^))
Then
{hack to be able to optimize
mov (mem), reg
mov (reg), reg
mov (reg), reg [*]
test reg, reg and the oposite (where the marked instructions are
jne l1 switched)
mov (mem), reg
mov (reg), reg
movzx (reg), reg [*]}
If (Pai386(hp2)^._operator = A_MOV)
Then
Begin
@ -392,8 +324,8 @@ End.
{
$Log$
Revision 1.6 1998-09-17 21:54:21 jonas
* big error (with little consequences) corrected in NoChangedRegInRef
Revision 1.7 1998-09-20 17:12:35 jonas
* small fix for uncertain optimizations & more cleaning up
Revision 1.5 1998/09/16 17:59:59 jonas
* optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc

View File

@ -59,7 +59,6 @@ Procedure ShutDownDFA;
Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
{Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);}
{******************************* Constants *******************************}
Const
@ -71,9 +70,7 @@ Const
{$ifdef GDB}
,ait_stabs, ait_stabn, ait_stab_function_name
{$endif GDB}
{$ifdef regalloc}
,ait_regalloc, ait_regdealloc
{$endif regalloc}
];
{the maximum number of things (registers, memory, ...) a single instruction
@ -90,6 +87,14 @@ Const
Type
TRegArray = Array[R_EAX..R_EDI] of TRegister;
TRegSet = Set of TRegister;
TRegInfo = Record
RegsEncountered: TRegSet;
SubstRegs: TRegArray;
End;
{What an instruction can change}
TChange = (C_None,
C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI,
@ -190,7 +195,10 @@ Var
Implementation
Uses globals, systems, strings, verbose, hcodegen;
Uses globals, systems, strings, verbose, hcodegen,
{$ifdef i386}
cgi386;
{$endif i386}
Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
{MOV} (Ch: (C_Op2, C_None, C_None)),
@ -588,7 +596,7 @@ Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LowLabel, HighLabel, LabelDif: L
{Walks through the paasmlist to find the lowest and highest label number;
Since 0.9.3: also removes unused labels}
Var LabelFound: Boolean;
P{, hp1}: Pai;
P, hp1: Pai;
Begin
LabelFound := False;
LowLabel := MaxLongint;
@ -714,6 +722,35 @@ End;
{********************* Compare parts of Pai objects *********************}
Function RegsEquivalent(Reg1, Reg2: TRegister; Var RegInfo: TRegInfo): Boolean;
Begin
With RegInfo Do
If Not(Reg1 in RegsEncountered) Then
Begin
RegsEncountered := RegsEncountered + [Reg1];
SubstRegs[Reg1] := Reg2;
RegsEquivalent := True
End
Else RegsEquivalent := Reg1 = SubstRegs[Reg2];
End;
Function RefsEquivalent(Const R1, R2: TReference; var RegInfo: TRegInfo): Boolean;
Begin
If R1.IsIntValue
Then RefsEquivalent := R2.IsIntValue and (R1.Offset = R2.Offset)
Else If (R1.Offset = R2.Offset) And
RegsEquivalent(R1.Base, R2.Base, RegInfo) And
RegsEquivalent(R1.Index, R2.Index, RegInfo) And
(R1.Segment = R2.Segment) And (R1.ScaleFactor = R2.ScaleFactor)
Then
Begin
If Assigned(R1.Symbol)
Then RefsEquivalent := Assigned(R2.Symbol) And (R1.Symbol^=R2.Symbol^)
Else RefsEquivalent := Not(Assigned(R2.Symbol));
End
Else RefsEquivalent := False;
End;
Function RefsEqual(Const R1, R2: TReference): Boolean;
Begin
If R1.IsIntValue
@ -738,6 +775,14 @@ Begin
Else IsGP32reg := False
End;
Function SubstRegInRef(Reg: TRegister; Const Ref: TReference; var RegInfo: TRegInfo): Boolean;
Begin
Reg := Reg32(Reg);
With RegInfo Do
SubstRegInRef := RegsEquivalent(Reg, SubstRegs[Ref.Base], RegInfo) And
RegsEquivalent(Reg, SubstRegs[Ref.Base], RegInfo);
End;
Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
Begin {checks whether Ref contains a reference to Reg}
Reg := Reg32(Reg);
@ -863,21 +908,77 @@ Begin
Else s := 0
End;
Function RegInSequence(Reg: TRegister; Const Content: TContent): Boolean;
{checks the whole sequence of Content (so StartMod and and the next NrOfMods
Pai objects) to see whether Reg is used somewhere, without it being loaded
with something else first}
Var p: Pai;
Counter: Byte;
TmpResult: Boolean;
RegsChecked: TRegSet;
Begin
RegsChecked := [];
p := Content.StartMod;
TmpResult := False;
Counter := 1;
While Not(TmpResult) And
(Counter <= Content.NrOfMods) Do
Begin
If (p^.typ = ait_instruction) and
(Pai386(p)^._operator in [A_MOV, A_MOVZX, A_MOVSX])
Then
If (Pai386(p)^.op1t = top_ref)
Then
With TReference(Pai386(p)^.op1^) Do
If (Base = ProcInfo.FramePointer) And
(Index = R_NO)
Then RegsChecked := RegsChecked + [Reg32(TRegister(Pai386(p)^.op2))]
Else
Begin
If (Base = Reg) And
Not(Base In RegsChecked)
Then TmpResult := True;
If Not(TmpResult) And
(Index = Reg) And
Not(Index In RegsChecked)
Then TmpResult := True;
End;
Inc(Counter);
GetNextInstruction(p,p)
End;
RegInSequence := TmpResult
End;
Procedure DestroyReg(p1: PPaiProp; Reg: TRegister);
{Destroys the contents of the register Reg in the PPaiProp of P}
{Destroys the contents of the register Reg in the PPaiProp p1, as well as the
contents of registers are loaded with a memory location based on Reg}
Var TmpState: Longint;
Counter: TRegister;
Begin
Reg := Reg32(Reg);
NrOfInstrSinceLastMod[Reg] := 0;
If (Reg >= R_EAX) And (Reg <= R_EDI)
Then
With p1^.Regs[Reg] Do
Begin
IncState(State);
TmpState := State;
FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
State := TmpState;
End;
Begin
With p1^.Regs[Reg] Do
Begin
IncState(State);
TmpState := State;
FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
State := TmpState;
End;
For Counter := R_EAX to R_EDI Do
With p1^.Regs[Counter] Do
If (Typ = Con_Ref) And
RegInSequence(Reg, p1^.Regs[Counter])
Then
Begin
IncState(State);
TmpState := State;
FillChar(p1^.Regs[Counter], SizeOf(TContent), 0);
State := TmpState;
End;
End;
End;
Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean;
@ -903,13 +1004,6 @@ Function InstructionsEqual(p1, p2: Pai): Boolean;
Begin {checks whether two Pai386 instructions are equal}
InstructionsEqual :=
Assigned(p1) And Assigned(p2) And
{ $ifdef regalloc
((((Pai(p1)^.typ = ait_regalloc) And
(Pai(p2)^.typ = ait_regalloc)) Or
((Pai(p1)^.typ = ait_regdealloc) And
(Pai(p2)^.typ = ait_regdealloc))) And
(PaiRegAlloc(p1)^.reg = PaiRegAlloc(p2)^.reg)) Or
endif regalloc}
((Pai(p1)^.typ = ait_instruction) And
(Pai(p1)^.typ = ait_instruction) And
(Pai386(p1)^._operator = Pai386(p2)^._operator) And
@ -919,6 +1013,43 @@ Begin {checks whether two Pai386 instructions are equal}
OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2))
End;
Function RefInInstruction(Const Ref: TReference; p: Pai): Boolean;
{checks whehter Ref is used in P}
Var TmpResult: Boolean;
Begin
TmpResult := False;
If (p^.typ = ait_instruction) Then
Begin
If (Pai386(p)^.op1t = Top_Ref)
Then TmpResult := RefsEqual(Ref, TReference(Pai386(p)^.op1^));
If Not(TmpResult) And
(Pai386(p)^.op2t = Top_Ref)
Then TmpResult := RefsEqual(Ref, TReference(Pai386(p)^.op2^));
End;
RefInInstruction := TmpResult;
End;
Function RefInSequence(Const Ref: TReference; Content: TContent): Boolean;
{checks the whole sequence of Content (so StartMod and and the next NrOfMods
Pai objects) to see whether Ref is used somewhere}
Var p: Pai;
Counter: Byte;
TmpResult: Boolean;
Begin
p := Content.StartMod;
TmpResult := False;
Counter := 1;
While Not(TmpResult) And
(Counter <= Content.NrOfMods) Do
Begin
If (p^.typ = ait_instruction) And
RefInInstruction(Ref, p)
Then TmpResult := True;
Inc(Counter);
GetNextInstruction(p,p)
End;
RefInSequence := TmpResult
End;
Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichReg: TRegister);
{destroys all registers which possibly contain a reference to Ref, WhichReg
@ -933,21 +1064,29 @@ Begin
Then
{write something to a parameter, a local or global variable, so
* with uncertzain optimizations on:
- destroy the contents of registers <> WhichReg whose StartMod is of
the form "mov?? (Ref), %reg". WhichReg is destroyed if it's StartMod
is of that form and NrOfMods > 1 (so if it is a pointer based on Ref)
* with uncertzain optimizations off:
- 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^.fileinfo.line)^.Regs[Counter] Do
Begin
If (typ = Con_Ref) And
(Not(cs_UncertainOpts in aktglobalswitches) And
(NrOfMods <> 1)
) Or
(RefInSequence(Ref,PPaiProp(p^.fileinfo.line)^.Regs[Counter]) And
((Counter <> WhichReg) Or
((NrOfMods = 1) And
{StarMod is always of the type ait_instruction}
(Pai386(StartMod)^.op1t = top_ref) And
((RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) And
((Counter <> WhichReg) Or (NrOfMods <> 1))) Or
(Not(cs_UncertainOpts in aktglobalswitches) And
(NrOfMods <> 1)))
(Pai386(StartMod)^.op1t = top_ref) And
RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref)
)
)
)
Then DestroyReg(PPaiProp(p^.fileinfo.line), Counter)
End
Else
@ -999,7 +1138,11 @@ Begin
BuildLabelTable(AsmL, LTable, LoLab, LabDif);
End;
Function DoDFAPass2(First: Pai): Pai;
Function DoDFAPass2(
{$Ifdef StateDebug}
AsmL: PAasmOutput;
{$endif statedebug}
First: Pai): Pai;
{Analyzes the Data Flow of an assembler list. Starts creating the reg
contents for the instructions starting with p. Returns the last pai which has
been processed}
@ -1037,7 +1180,7 @@ Begin
Begin
GetLastInstruction(p, hp);
CurProp^.Regs := PPaiProp(hp^.fileinfo.line)^.Regs;
CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag
CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag;
End
{$ifdef JumpAnal}
End
@ -1237,9 +1380,7 @@ Begin
{$ifdef GDB}
ait_stabs, ait_stabn, ait_stab_function_name:;
{$endif GDB}
{$ifdef regalloc}
ait_regalloc, ait_regdealloc:;
{$endif regalloc}
ait_instruction:
Begin
InstrProp := AsmInstr[Pai386(p)^._operator];
@ -1263,17 +1404,17 @@ Begin
Top_Ref:
Begin {destination is always a register in this case}
TmpReg := Reg32(TRegister(Pai386(p)^.op2));
If (RegInRef(TmpReg, TReference(Pai386(p)^.op1^)))
{$ifdef StateDebug}
hp := new(pai_asm_comment,init(strpnew(att_reg2str[TmpReg]+': '+tostr(CurProp^.Regs[TmpReg].State))));
InsertLLItem(AsmL, p, p^.next, hp);
{$endif SteDebug}
If RegInRef(TmpReg, TReference(Pai386(p)^.op1^)) And
(CurProp^.Regs[TmpReg].Typ = Con_Ref)
Then
Begin
With CurProp^.Regs[TmpReg] Do
Begin
IncState(State);
If (typ <> Con_Ref) Then
Begin
typ := Con_Ref;
StartMod := p;
End;
{also store how many instructions are part of the sequence in the first
instructions PPaiProp, so it can be easily accessed from within
CheckSequence}
@ -1455,7 +1596,11 @@ End;
Function DFAPass2(AsmL: PAasmOutPut): Pai;
Begin
If InitDFAPass2(AsmL)
Then DFAPass2 := DoDFAPass2(Pai(AsmL^.First))
Then DFAPass2 := DoDFAPass2(
{$ifdef statedebug}
asml,
{$endif statedbug}
Pai(AsmL^.First))
Else DFAPass2 := Nil;
End;
@ -1469,9 +1614,8 @@ End.
{
$Log$
Revision 1.13 1998-09-17 09:42:36 peter
+ pass_2 for cg386
* Message() -> CGMessage() for pass_1/pass_2
Revision 1.14 1998-09-20 17:12:36 jonas
* small fix for uncertain optimizations & more cleaning up
Revision 1.12 1998/09/16 18:00:01 jonas
* optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc