* 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 Found holds the number of instructions between StartMod and EndMod and false
is returned} is returned}
Var hp2, hp3, EndMod: Pai; Var hp2, hp3, EndMod: Pai;
TmpResult: Boolean;
RegsNotYetChecked: Set Of TRegister;
Counter: Byte; 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} Begin {CheckSequence}
Reg := Reg32(Reg); Reg := Reg32(Reg);
Found := 0; 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; 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) If (PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods = 1)
Then Counter := 1 Then Counter := 1
Else Else
For Counter := 2 to PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods Do For Counter := 2 to PPaiProp(hp3^.fileinfo.line)^.Regs[Reg].NrOfMods Do
GetNextInstruction(EndMod, EndMod); GetNextInstruction(EndMod, EndMod);
hp3 := p; hp3 := p;
RegsNotYetChecked := [R_EAX..R_EDI];
While (Found <> Counter) And While (Found <> Counter) And
InstructionsEqual(hp2, hp3) And InstructionsEqual(hp2, hp3) Do
NoChangedRegInRef(EndMod, hp3) Do
Begin 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(hp2, hp2);
GetNextInstruction(hp3, hp3); GetNextInstruction(hp3, hp3);
Inc(Found) Inc(Found)
End; End;
If (Found <> Counter) If (Found <> Counter)
Then 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 Begin
If ((Found+1) = Counter) And If ((Found+1) = Counter) And
Assigned(hp2) And Assigned(hp2) And
@ -159,9 +81,19 @@ Begin {CheckSequence}
(Pai386(hp3)^.op1t = top_ref) And (Pai386(hp3)^.op1t = top_ref) And
(Pai386(hp3)^.op2t = top_reg) And (Pai386(hp3)^.op2t = top_reg) And
(Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And (Pai386(hp2)^._operator <> Pai386(hp3)^._operator) And
RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^)) And RefsEqual(TReference(Pai386(hp2)^.op1^),TReference(Pai386(hp3)^.op1^))
NoChangedRegInRef(EndMod, hp3)
Then 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) If (Pai386(hp2)^._operator = A_MOV)
Then Then
Begin Begin
@ -392,8 +324,8 @@ End.
{ {
$Log$ $Log$
Revision 1.6 1998-09-17 21:54:21 jonas Revision 1.7 1998-09-20 17:12:35 jonas
* big error (with little consequences) corrected in NoChangedRegInRef * small fix for uncertain optimizations & more cleaning up
Revision 1.5 1998/09/16 17:59:59 jonas Revision 1.5 1998/09/16 17:59:59 jonas
* optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc * 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; Function FindLabel(L: PLabel; Var hp: Pai): Boolean;
{Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);} {Procedure FindLoHiLabels(AsmL: PAasmOutput; Var LoLab, HiLab, LabDif: Longint);}
{******************************* Constants *******************************} {******************************* Constants *******************************}
Const Const
@ -71,9 +70,7 @@ Const
{$ifdef GDB} {$ifdef GDB}
,ait_stabs, ait_stabn, ait_stab_function_name ,ait_stabs, ait_stabn, ait_stab_function_name
{$endif GDB} {$endif GDB}
{$ifdef regalloc}
,ait_regalloc, ait_regdealloc ,ait_regalloc, ait_regdealloc
{$endif regalloc}
]; ];
{the maximum number of things (registers, memory, ...) a single instruction {the maximum number of things (registers, memory, ...) a single instruction
@ -90,6 +87,14 @@ Const
Type 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} {What an instruction can change}
TChange = (C_None, TChange = (C_None,
C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI, C_REAX, C_RECX, C_REDX, C_REBX, C_RESP, C_REBP, C_RESI, C_REDI,
@ -190,7 +195,10 @@ Var
Implementation Implementation
Uses globals, systems, strings, verbose, hcodegen; Uses globals, systems, strings, verbose, hcodegen,
{$ifdef i386}
cgi386;
{$endif i386}
Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = ( Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
{MOV} (Ch: (C_Op2, C_None, C_None)), {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; {Walks through the paasmlist to find the lowest and highest label number;
Since 0.9.3: also removes unused labels} Since 0.9.3: also removes unused labels}
Var LabelFound: Boolean; Var LabelFound: Boolean;
P{, hp1}: Pai; P, hp1: Pai;
Begin Begin
LabelFound := False; LabelFound := False;
LowLabel := MaxLongint; LowLabel := MaxLongint;
@ -714,6 +722,35 @@ End;
{********************* Compare parts of Pai objects *********************} {********************* 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; Function RefsEqual(Const R1, R2: TReference): Boolean;
Begin Begin
If R1.IsIntValue If R1.IsIntValue
@ -738,6 +775,14 @@ Begin
Else IsGP32reg := False Else IsGP32reg := False
End; 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; Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
Begin {checks whether Ref contains a reference to Reg} Begin {checks whether Ref contains a reference to Reg}
Reg := Reg32(Reg); Reg := Reg32(Reg);
@ -863,14 +908,58 @@ Begin
Else s := 0 Else s := 0
End; 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); 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; Var TmpState: Longint;
Counter: TRegister;
Begin Begin
Reg := Reg32(Reg); Reg := Reg32(Reg);
NrOfInstrSinceLastMod[Reg] := 0; NrOfInstrSinceLastMod[Reg] := 0;
If (Reg >= R_EAX) And (Reg <= R_EDI) If (Reg >= R_EAX) And (Reg <= R_EDI)
Then Then
Begin
With p1^.Regs[Reg] Do With p1^.Regs[Reg] Do
Begin Begin
IncState(State); IncState(State);
@ -878,6 +967,18 @@ Begin
FillChar(p1^.Regs[Reg], SizeOf(TContent), 0); FillChar(p1^.Regs[Reg], SizeOf(TContent), 0);
State := TmpState; State := TmpState;
End; 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; End;
Function OpsEqual(typ: Longint; op1, op2: Pointer): Boolean; 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} Begin {checks whether two Pai386 instructions are equal}
InstructionsEqual := InstructionsEqual :=
Assigned(p1) And Assigned(p2) And 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
(Pai(p1)^.typ = ait_instruction) And (Pai(p1)^.typ = ait_instruction) And
(Pai386(p1)^._operator = Pai386(p2)^._operator) 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)) OpsEqual(Pai386(p1)^.op2t, Pai386(p1)^.op2, Pai386(p2)^.op2))
End; 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); Procedure DestroyRefs(p: pai; Const Ref: TReference; WhichReg: TRegister);
{destroys all registers which possibly contain a reference to Ref, WhichReg {destroys all registers which possibly contain a reference to Ref, WhichReg
@ -933,21 +1064,29 @@ Begin
Then Then
{write something to a parameter, a local or global variable, so {write something to a parameter, a local or global variable, so
* with uncertzain optimizations on: * with uncertzain optimizations on:
- destroy the contents of registers <> WhichReg whose StartMod is of - destroy the contents of registers whose contents have somewhere a
the form "mov?? (Ref), %reg". WhichReg is destroyed if it's StartMod "mov?? (Ref), %reg". WhichReg (this is the register whose contents
is of that form and NrOfMods > 1 (so if it is a pointer based on Ref) are being written to memory) is not destroyed if it's StartMod is
* with uncertzain optimizations off: 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} - also destroy registers that contain any pointer}
For Counter := R_EAX to R_EDI Do For Counter := R_EAX to R_EDI Do
With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do With PPaiProp(p^.fileinfo.line)^.Regs[Counter] Do
Begin Begin
If (typ = Con_Ref) And 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} {StarMod is always of the type ait_instruction}
(Pai386(StartMod)^.op1t = top_ref) And (Pai386(StartMod)^.op1t = top_ref) And
((RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref) And RefsEqual(TReference(Pai386(StartMod)^.op1^), Ref)
((Counter <> WhichReg) Or (NrOfMods <> 1))) Or )
(Not(cs_UncertainOpts in aktglobalswitches) And )
(NrOfMods <> 1))) )
Then DestroyReg(PPaiProp(p^.fileinfo.line), Counter) Then DestroyReg(PPaiProp(p^.fileinfo.line), Counter)
End End
Else Else
@ -999,7 +1138,11 @@ Begin
BuildLabelTable(AsmL, LTable, LoLab, LabDif); BuildLabelTable(AsmL, LTable, LoLab, LabDif);
End; 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 {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 contents for the instructions starting with p. Returns the last pai which has
been processed} been processed}
@ -1037,7 +1180,7 @@ Begin
Begin Begin
GetLastInstruction(p, hp); GetLastInstruction(p, hp);
CurProp^.Regs := PPaiProp(hp^.fileinfo.line)^.Regs; CurProp^.Regs := PPaiProp(hp^.fileinfo.line)^.Regs;
CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag CurProp^.DirFlag := PPaiProp(hp^.fileinfo.line)^.DirFlag;
End End
{$ifdef JumpAnal} {$ifdef JumpAnal}
End End
@ -1237,9 +1380,7 @@ Begin
{$ifdef GDB} {$ifdef GDB}
ait_stabs, ait_stabn, ait_stab_function_name:; ait_stabs, ait_stabn, ait_stab_function_name:;
{$endif GDB} {$endif GDB}
{$ifdef regalloc}
ait_regalloc, ait_regdealloc:; ait_regalloc, ait_regdealloc:;
{$endif regalloc}
ait_instruction: ait_instruction:
Begin Begin
InstrProp := AsmInstr[Pai386(p)^._operator]; InstrProp := AsmInstr[Pai386(p)^._operator];
@ -1263,17 +1404,17 @@ Begin
Top_Ref: Top_Ref:
Begin {destination is always a register in this case} Begin {destination is always a register in this case}
TmpReg := Reg32(TRegister(Pai386(p)^.op2)); 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 Then
Begin Begin
With CurProp^.Regs[TmpReg] Do With CurProp^.Regs[TmpReg] Do
Begin Begin
IncState(State); 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 {also store how many instructions are part of the sequence in the first
instructions PPaiProp, so it can be easily accessed from within instructions PPaiProp, so it can be easily accessed from within
CheckSequence} CheckSequence}
@ -1455,7 +1596,11 @@ End;
Function DFAPass2(AsmL: PAasmOutPut): Pai; Function DFAPass2(AsmL: PAasmOutPut): Pai;
Begin Begin
If InitDFAPass2(AsmL) If InitDFAPass2(AsmL)
Then DFAPass2 := DoDFAPass2(Pai(AsmL^.First)) Then DFAPass2 := DoDFAPass2(
{$ifdef statedebug}
asml,
{$endif statedbug}
Pai(AsmL^.First))
Else DFAPass2 := Nil; Else DFAPass2 := Nil;
End; End;
@ -1469,9 +1614,8 @@ End.
{ {
$Log$ $Log$
Revision 1.13 1998-09-17 09:42:36 peter Revision 1.14 1998-09-20 17:12:36 jonas
+ pass_2 for cg386 * small fix for uncertain optimizations & more cleaning up
* Message() -> CGMessage() for pass_1/pass_2
Revision 1.12 1998/09/16 18:00:01 jonas Revision 1.12 1998/09/16 18:00:01 jonas
* optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc * optimizer now completely dependant on GetNext/GetLast instruction, works again with -dRegAlloc