From 167f8d654f7d89e592aa729d5c4d9ee0fa0fd5db Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Wed, 29 Sep 1999 13:50:34 +0000 Subject: [PATCH] * fixes from daopt386.pas integrated --- compiler/new/aoptobj.pas | 1584 +++++++++++++++++++------------------- 1 file changed, 809 insertions(+), 775 deletions(-) diff --git a/compiler/new/aoptobj.pas b/compiler/new/aoptobj.pas index f4c4c8017b..a88112ca4a 100644 --- a/compiler/new/aoptobj.pas +++ b/compiler/new/aoptobj.pas @@ -1,778 +1,812 @@ -{ - $Id$ - Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal - Development Team - - This unit contains the processor independent assembler optimizer - object, base for the dataflow analyzer, peepholeoptimizer and - common subexpression elimination objects. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - **************************************************************************** -} -Unit AoptObj; - -{ general, processor independent objects for use by the assembler optimizer } - -Interface - -uses aasm, Cobjects, cpuinfo, cpubase, aoptbase, aoptcpub; - -{ ************************************************************************* } -{ ********************************* Constants ***************************** } -{ ************************************************************************* } - -Const - -{Possible register content types} - con_Unknown = 0; - con_ref = 1; - con_const = 2; - -{***************** Types ****************} - -Type - -{ ************************************************************************* } -{ ************************* Some general type definitions ***************** } -{ ************************************************************************* } - TRegArray = Array[LoReg..HiReg] of TRegister; - TRegSet = Set of LoReg..HiReg; -{ possible actions on an operand: read, write or modify (= read & write) } - TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown); - -{ ************************************************************************* } -{ * Object to hold information on which regiters are in use and which not * } -{ ************************************************************************* } - TUsedRegs = Object - Constructor init; - Constructor InitWithValue(Const _RegSet: TRegSet); - { update the info with the pairegalloc objects coming after } - { p } - Procedure Update(p: Pai); - { is Reg currently in use } - Function IsUsed(Reg: TRegister): Boolean; - { get all the currently used registers } - Function GetUsedRegs: TRegSet; - Destructor Done; - - Private - - UsedRegs: TRegSet; - End; - -{ ************************************************************************* } -{ ******************* Contents of the integer registers ******************* } -{ ************************************************************************* } - - { size of the integer that holds the state number of a register. Can be any } - { integer type, so it can be changed to reduce the size of the TContent } - { structure or to improve alignment } - TStateInt = Byte; - - TContent = Packed Record - { start and end of block instructions that defines the } - { content of this register. If Typ = con_const, then } - { Longint(StartMod) = value of the constant) } - StartMod: pai; - { starts at 0, gets increased everytime the register is } - { written to } - WState: TStateInt; - { starts at 0, gets increased everytime the register is read } - { from } - RState: TStateInt; - { how many instructions starting with StarMod does the block } - { consist of } - NrOfMods: Byte; - { the type of the content of the register: unknown, memory } - { (variable) or constant } - Typ: Byte; - End; - - TRegContent = Array[LoGPReg..HiGPReg] Of TContent; - -{ ************************************************************************** } -{ information object with the contents of every register. Every Pai object } -{ gets one of these assigned: a pointer to it is stored in the OptInfo field } -{ ************************************************************************** } - - PPaiProp = ^TPaiProp; - - TPaiProp = Object(TAoptBaseCpu) - Regs: TRegContent; - { info about allocation of general purpose integer registers } - UsedRegs: TUsedRegs; - { info about the conditional registers } - CondRegs: TCondRegs; - { can this instruction be removed? } - CanBeRemoved: Boolean; - - Constructor init; - - { checks the whole sequence of which (so regs[which].StartMod and and } - { the next NrOfMods Pai objects) to see whether Reg is used somewhere, } - { without it being loaded with something else first } - Function RegInSequence(Reg, which: TRegister): Boolean; - { destroy the contents of a register, as well as those whose contents } - { are based on those of that register } - Procedure DestroyReg(Reg: TRegister; var InstrSinceLastMod: - TInstrSinceLastMod); - { if the contents of WhichReg (can be R_NO in case of a constant) are } - { written to memory at the location Ref, the contents of the registers } - { that depend on Ref have to be destroyed } - Procedure DestroyRefs(Const Ref: TReference; WhichReg: TRegister; var - InstrSinceLastMod: TInstrSinceLastMod); - - { an instruction reads from operand o } - Procedure ReadOp(const o:toper); - { an instruction reads from reference Ref } - Procedure ReadRef(Ref: PReference); - { an instruction reads from register Reg } - Procedure ReadReg(Reg: TRegister); - - { an instruction writes/modifies operand o and this has special } - { side-effects or modifies the contents in such a way that we can't } - { simply add this instruction to the sequence of instructions that } - { describe the contents of the operand, so destroy it } - Procedure DestroyOp(const o:Toper; var InstrSinceLastMod: - TInstrSinceLastMod); - { destroy the contents of all registers } - Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod); -{$ifdef arithopt} - { a register's contents are modified, but not destroyed (the new value } - { depends on the old one) } - Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod: - TInstrSinceLastMod); - { an operand's contents are modified, but not destroyed (the new value } - { depends on the old one) } - Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod: - TInstrSinceLastMod); -{$endif arithopt} - - { increase the write state of a register (call every time a register is } - { written to) } - Procedure IncWState(Reg: TRegister); - { increase the read state of a register (call every time a register is } - { read from) } - Procedure IncRState(Reg: TRegister); - { get the write state of a register } - Function GetWState(Reg: TRegister): TStateInt; - { get the read state of a register } - Function GetRState(Reg: TRegister): TStateInt; - - { get the type of contents of a register } - Function GetRegContentType(Reg: TRegister): Byte; - - Destructor Done; - - Private - - Procedure IncState(var s: TStateInt); - - { returns whether the reference Ref is used somewhere in the loading } - { sequence Content } - Function RefInSequence(Const Ref: TReference; Content: TContent): Boolean; - - { returns whether the instruction P reads from and/or writes } - { to Reg } - Function RefInInstruction(Const Ref: TReference; p: Pai): Boolean; - End; - -{ ************************************************************************* } -{ ************************ Label information ****************************** } -{ ************************************************************************* } - TLabelTableItem = Record - PaiObj: Pai; - End; - -{$ifndef TP} - TLabelTable = Array[0..2500000] Of TLabelTableItem; -{$else TP} - TLabelTable = Array[0..(65520 div sizeof(TLabelTableItem))] Of TLabelTableItem; -{$endif TP} - PLabelTable = ^TLabelTable; - PLabelInfo = ^TLabelInfo; - TLabelInfo = Record - { the highest and lowest label number occurring in the current code } - { fragment } - LowLabel, HighLabel: AWord; - LabelDif: AWord; - { table that contains the addresses of the Pai_Label objects associated } - { with each label number } - LabelTable: PLabelTable; - End; - -{ ************************************************************************* } -{ ********** General optimizer object, used to derive others from ********* } -{ ************************************************************************* } - - TAOptObj = Object(TAoptBaseCpu) - { the PAasmOutput list this optimizer instance works on } - AsmL: PAasmOutput; - - { The labelinfo record contains the addresses of the Pai objects } - { that are labels, how many labels there are and the min and max } - { label numbers } - LabelInfo: PLabelInfo; - - { Start and end of the block that is currently being optimized } - BlockStart, BlockEnd: Pai; - - { _AsmL is the PAasmOutpout list that has to be optimized, } - { _BlockStart and _BlockEnd the start and the end of the block } - { that has to be optimized and _LabelInfo a pointer to a } - { TLabelInfo record } - Constructor Init(_AsmL: PAasmOutput; _BlockStart, _BlockEnd: Pai; - _LabelInfo: PLabelInfo); - - { processor independent methods } - - { returns true if the label L is found between hp and the next } - { instruction } - Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean; - - { inserts new_one between prev and foll in AsmL } - Procedure InsertLLItem(prev, foll, new_one: PLinkedList_Item); - - - { If P is a Pai object releveant to the optimizer, P is returned } - { If it is not relevant tot he optimizer, the first object after P } - { that is relevant is returned } - Function SkipHead(P: Pai): Pai; - - { returns true if the operands o1 and o2 are completely equal } - Function OpsEqual(const o1,o2:toper): Boolean; - - { Returns true if a ait_alloc object for Reg is found in the block } - { of Pai's starting with StartPai and ending with the next "real" } - { instruction } - Function FindRegAlloc(Reg: TRegister; StartPai: Pai): Boolean; - - { processor dependent methods } - - End; - - -{ ***************************** Implementation **************************** } - -Implementation - -uses hcodegen, globtype, globals, tainst; - -{ ************************************************************************* } -{ ******************************** TUsedRegs ****************************** } -{ ************************************************************************* } - -Constructor TUsedRegs.init; -Begin - UsedRegs := []; -End; - -Constructor TUsedRegs.InitWithValue(Const _RegSet: TRegSet); -Begin - UsedRegs := _RegSet; -End; - -Procedure TUsedRegs.Update(p: Pai); -{updates UsedRegs with the RegAlloc Information coming after P} -Begin - Repeat - While Assigned(p) And - ((p^.typ in (SkipInstr - [ait_RegAlloc])) or - ((p^.typ = ait_label) And - Not(Pai_Label(p)^.l^.is_used))) Do - p := Pai(p^.next); - While Assigned(p) And - (p^.typ=ait_RegAlloc) Do - Begin - if pairegalloc(p)^.allocation then - UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg] - else - UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg]; - p := pai(p^.next); - End; - Until Not(Assigned(p)) Or - (Not(p^.typ in SkipInstr) And - Not((p^.typ = ait_label) And - Not(Pai_Label(p)^.l^.is_used))); -End; - -Function TUsedRegs.IsUsed(Reg: TRegister): Boolean; -Begin - IsUsed := Reg in UsedRegs -End; - -Function TUsedRegs.GetUsedRegs: TRegSet; -Begin - GetUsedRegs := UsedRegs; -End; - -Destructor TUsedRegs.Done; {$ifdef inl} inline; {$endif inl} -Begin -end; - -{ ************************************************************************* } -{ **************************** TPaiProp *********************************** } -{ ************************************************************************* } - -Constructor TPaiProp.Init; -Begin - UsedRegs.Init; - CondRegs.init; -{ DirFlag: TFlagContents; I386 specific} -End; - -Function TPaiProp.RegInSequence(Reg, which: TRegister): Boolean; -Var p: Pai; - RegsChecked: TRegSet; - content: TContent; - Counter: Byte; - TmpResult: Boolean; -Begin - RegsChecked := []; - content := regs[which]; - p := content.StartMod; - TmpResult := False; - Counter := 1; - While Not(TmpResult) And - (Counter <= Content.NrOfMods) Do - Begin - If IsLoadMemReg(p) Then - With PInstr(p)^.oper[LoadSrc].ref^ Do - If (Base = ProcInfo.FramePointer) -{$ifdef RefsHaveIndexReg} - And (Index = R_NO) -{$endif RefsHaveIndexReg} Then - Begin - RegsChecked := RegsChecked + - [RegMaxSize(PInstr(p)^.oper[LoadDst].reg)]; - If Reg = RegMaxSize(PInstr(p)^.oper[LoadDst].reg) Then - Break; - End - Else - Begin - If (Base = Reg) And - Not(Base In RegsChecked) - Then TmpResult := True; -{$ifdef RefsHaveIndexReg} - If Not(TmpResult) And - (Index = Reg) And - Not(Index In RegsChecked) - Then TmpResult := True; -{$Endif RefsHaveIndexReg} - End - Else TmpResult := RegInInstruction(Reg, p); - Inc(Counter); - GetNextInstruction(p,p) - End; - RegInSequence := TmpResult -End; - - -Procedure TPaiProp.DestroyReg(Reg: TRegister; var InstrSinceLastMod: - TInstrSinceLastMod); -{ 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 TmpWState, TmpRState: Byte; - Counter: TRegister; -Begin - Reg := RegMaxSize(Reg); - If (Reg in [R_EAX..R_EDI]) Then - For Counter := R_EAX to R_EDI Do - With Regs[Counter] Do - If (Counter = reg) Or - ((Typ = Con_Ref) And - RegInSequence(Reg, Counter)) Then - Begin - InstrSinceLastMod[Counter] := 0; - IncWState(Counter); - TmpWState := GetWState(Counter); - TmpRState := GetRState(Counter); - FillChar(Regs[Counter], SizeOf(TContent), 0); - WState := TmpWState; - RState := TmpRState - End -End; - -Procedure TPaiProp.DestroyRefs(Const Ref: TReference; WhichReg: TRegister; - var InstrSinceLastMod: TInstrSinceLastMod); -{ 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 Counter: TRegister; -Begin - WhichReg := RegMaxSize(WhichReg); - If ((Ref.base = ProcInfo.FramePointer) -{$ifdef refsHaveIndexReg} - And (Ref.Index = R_NO -{$endif refsHaveIndexReg} - ) Or - Assigned(Ref.Symbol) - Then -{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 or value based on Ref) - * with uncertain optimizations off: - - also destroy registers that contain any pointer} - For Counter := LoGPReg to HiGPReg Do - With Regs[Counter] Do - Begin - If (typ = Con_Ref) And - ((Not(cs_UncertainOpts in aktglobalswitches) And - (NrOfMods <> 1) - ) Or - (RefInSequence(Ref,Regs[Counter]) And - ((Counter <> WhichReg) Or - ((NrOfMods <> 1) And - {StarMod is always of the type ait_instruction} - (PInstr(StartMod)^.oper[0].typ = top_ref) And - RefsEqual(PInstr(StartMod)^.oper[0].ref^, Ref) - ) - ) - ) - ) - Then - DestroyReg(Counter, InstrSinceLastMod) - 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 := LoGPReg to HiGPReg Do - With Regs[Counter] Do - If (typ = Con_Ref) And - (Not(cs_UncertainOpts in aktglobalswitches) Or -{$ifdef i386} - {for movsl} - (Ref.Base = R_EDI) Or -{$endif} - {don't destroy if reg contains a parameter, local or global variable} - Not((NrOfMods = 1) And - (PInstr(StartMod)^.oper[0].typ = top_ref) And - ((PInstr(StartMod)^.oper[0].ref^.base = ProcInfo.FramePointer) Or - Assigned(PInstr(StartMod)^.oper[0].ref^.Symbol) - ) - ) - ) - Then DestroyReg(Counter, InstrSinceLastMod) -End; - -Procedure TPaiProp.DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod); -Var Counter: TRegister; -Begin {initializes/desrtoys all registers} - For Counter := R_EAX To R_EDI Do - DestroyReg(Counter, InstrSinceLastMod); - CondRegs.Init; -{ FPURegs.Init; } -End; - -Procedure TPaiProp.DestroyOp(const o:Toper; var InstrSinceLastMod: - TInstrSinceLastMod); -Begin - Case o.typ Of - top_reg: DestroyReg(o.reg, InstrSinceLastMod); - top_ref: DestroyRefs(o.ref^, R_NO, InstrSinceLastMod); - top_symbol:; - End; -End; - -Procedure TPaiProp.ReadReg(Reg: TRegister); -Begin - Reg := RegMaxSize(Reg); - If Reg in General_Registers Then - IncRState(RegMaxSize(Reg)) -End; - -Procedure TPaiProp.ReadRef(Ref: PReference); -Begin - If Ref^.Base <> R_NO Then - ReadReg(Ref^.Base); - If Ref^.Index <> R_NO Then - ReadReg(Ref^.Index); -End; - -Procedure TPaiProp.ReadOp(const o:toper); -Begin - Case o.typ Of - top_reg: ReadReg(o.reg); - top_ref: ReadRef(o.ref); - top_symbol : ; - End; -End; - -{$ifdef arithopt} -Procedure TPaiProp.ModifyReg(reg: TRegister; Var InstrSinceLastMod: - TInstrSinceLastMod); -Begin - With Regs[reg] Do - If (Typ = Con_Ref) - Then - Begin - IncState(WState); - {also store how many instructions are part of the sequence in the first - instructions PPaiProp, so it can be easily accessed from within - CheckSequence} - Inc(NrOfMods, NrOfInstrSinceLastMod[Reg]); - PPaiProp(StartMod^.OptInfo)^.Regs[Reg].NrOfMods := NrOfMods; - NrOfInstrSinceLastMod[Reg] := 0; - End - Else - DestroyReg(Reg, InstrSinceLastMod); -End; - -Procedure TPaiProp.ModifyOp(const oper: TOper; var InstrSinceLastMod: - TInstrSinceLastMod); -Begin - If oper.typ = top_reg Then - ModifyReg(RegMaxSize(oper.reg)) - Else - Begin - ReadOp(oper); - DestroyOp(oper, InstrSinceLastMod); - End -End; -{$endif arithopt} - -Procedure TPaiProp.IncWState(Reg: TRegister);{$ifdef inl} inline;{$endif inl} -Begin - IncState(Regs[Reg].WState); -End; - -Procedure TPaiProp.IncRState(Reg: TRegister);{$ifdef inl} inline;{$endif inl} -Begin - IncState(Regs[Reg].RState); -End; - -Function TPaiProp.GetWState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl} -Begin - GetWState := Regs[Reg].WState -End; - -Function TPaiProp.GetRState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl} -Begin - GetRState := Regs[Reg].RState -End; - -Function TPaiProp.GetRegContentType(Reg: TRegister): Byte; {$ifdef inl} inline;{$endif inl} -Begin - GetRegContentType := Regs[Reg].typ -End; - -Destructor TPaiProp.Done; -Begin - UsedRegs.Done; - CondRegs.Done; -{ DirFlag: TFlagContents; I386 specific} -End; -{ ************************ private TPaiProp stuff ************************* } - -Procedure TPaiProp.IncState(Var s: TStateInt); {$ifdef inl} inline;{$endif inl} -Begin - If s <> High(TStateInt) Then Inc(s) - Else s := 0 -End; - -Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Pai): Boolean; -Var Count: AWord; - TmpResult: Boolean; -Begin - TmpResult := False; - If (p^.typ = ait_instruction) Then - Begin - Count := 0; - Repeat - If (PInstr(p)^.oper[Count].typ = Top_Ref) Then - TmpResult := RefsEqual(Ref, PInstr(p)^.oper[Count].ref^); - Inc(Count); - Until (Count = MaxOps) or TmpResult; - End; - RefInInstruction := TmpResult; -End; - -Function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent): - Boolean; -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; - -{ ************************************************************************* } -{ ***************************** TAoptObj ********************************** } -{ ************************************************************************* } - -Constructor TAoptObj.Init(_AsmL: PAasmOutput; _BlockStart, _BlockEnd: Pai; - _LabelInfo: PLabelInfo); -Begin - AsmL := _AsmL; - BlockStart := _BlockStart; - BlockEnd := _BlockEnd; - LabelInfo := _LabelInfo -End; - -Function TAOptObj.FindLabel(L: PasmLabel; Var hp: Pai): Boolean; -Var TempP: Pai; -Begin - TempP := hp; - While Assigned(TempP) and - (TempP^.typ In SkipInstr + [ait_label]) Do - If (TempP^.typ <> ait_Label) Or - (pai_label(TempP)^.l <> L) - Then GetNextInstruction(TempP, TempP) - Else - Begin - hp := TempP; - FindLabel := True; - exit - End; - FindLabel := False; -End; - -Procedure TAOptObj.InsertLLItem(prev, foll, new_one: PLinkedList_Item); -Begin - If Assigned(prev) Then - If Assigned(foll) Then - Begin - If Assigned(new_one) Then - Begin - new_one^.previous := prev; - new_one^.next := foll; - prev^.next := new_one; - foll^.previous := new_one; - Pai(new_one)^.fileinfo := Pai(foll)^.fileinfo - End - End - Else AsmL^.Concat(new_one) - Else If Assigned(Foll) Then AsmL^.Insert(new_one) -End; - - -Function TAOptObj.SkipHead(P: Pai): Pai; -Var OldP: Pai; -Begin - Repeat - OldP := P; - If (P^.typ in SkipInstr) Or - ((P^.typ = ait_marker) And - (Pai_Marker(P)^.Kind = AsmBlockEnd)) Then - GetNextInstruction(P, P) - Else If ((P^.Typ = Ait_Marker) And - (Pai_Marker(P)^.Kind = NoPropInfoStart)) Then - { a marker of the type NoPropInfoStart can't be the first instruction of a } - { paasmoutput list } - GetNextInstruction(Pai(P^.Previous),P); - If (P^.Typ = Ait_Marker) And - (Pai_Marker(P)^.Kind = AsmBlockStart) Then - Begin - P := Pai(P^.Next); - While (P^.typ <> Ait_Marker) Or - (Pai_Marker(P)^.Kind <> AsmBlockEnd) Do - P := Pai(P^.Next) - End; - Until P = OldP; - SkipHead := P; -End; - -Function TAOptObj.OpsEqual(const o1,o2:toper): Boolean; -Begin - if o1.typ=o2.typ then - Case o1.typ Of - Top_Reg : - OpsEqual:=o1.reg=o2.reg; - Top_Ref : - OpsEqual := RefsEqual(o1.ref^, o2.ref^); - Top_Const : - OpsEqual:=o1.val=o2.val; - Top_Symbol : - OpsEqual:=(o1.sym=o2.sym) and (o1.symofs=o2.symofs); - Top_None : - OpsEqual := True - else OpsEqual := False - End; -End; - -Function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Pai): Boolean; -Begin - FindRegAlloc:=False; - Repeat - While Assigned(StartPai) And - ((StartPai^.typ in (SkipInstr - [ait_regAlloc])) Or - ((StartPai^.typ = ait_label) and - Not(Pai_Label(StartPai)^.l^.Is_Used))) Do - StartPai := Pai(StartPai^.Next); - If Assigned(StartPai) And - (StartPai^.typ = ait_regAlloc) and (PairegAlloc(StartPai)^.allocation) Then - Begin - if PairegAlloc(StartPai)^.Reg = Reg then - begin - FindRegAlloc:=true; - exit; - end; - StartPai := Pai(StartPai^.Next); - End - else - exit; - Until false; -End; - -End. - -{ +{ + $Id$ + Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal + Development Team + + This unit contains the processor independent assembler optimizer + object, base for the dataflow analyzer, peepholeoptimizer and + common subexpression elimination objects. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + **************************************************************************** +} +Unit AoptObj; + +{ general, processor independent objects for use by the assembler optimizer } + +Interface + +uses aasm, Cobjects, cpuinfo, cpubase, aoptbase, aoptcpub; + +{ ************************************************************************* } +{ ********************************* Constants ***************************** } +{ ************************************************************************* } + +Const + +{Possible register content types} + con_Unknown = 0; + con_ref = 1; + con_const = 2; + +{***************** Types ****************} + +Type + +{ ************************************************************************* } +{ ************************* Some general type definitions ***************** } +{ ************************************************************************* } + TRefCompare = Function(const r1, r2: TReference): Boolean; + TRegArray = Array[LoReg..HiReg] of TRegister; + TRegSet = Set of LoReg..HiReg; +{ possible actions on an operand: read, write or modify (= read & write) } + TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown); + +{ ************************************************************************* } +{ * Object to hold information on which regiters are in use and which not * } +{ ************************************************************************* } + TUsedRegs = Object + Constructor init; + Constructor InitWithValue(Const _RegSet: TRegSet); + { update the info with the pairegalloc objects coming after } + { p } + Procedure Update(p: Pai); + { is Reg currently in use } + Function IsUsed(Reg: TRegister): Boolean; + { get all the currently used registers } + Function GetUsedRegs: TRegSet; + Destructor Done; + + Private + + UsedRegs: TRegSet; + End; + +{ ************************************************************************* } +{ ******************* Contents of the integer registers ******************* } +{ ************************************************************************* } + + { size of the integer that holds the state number of a register. Can be any } + { integer type, so it can be changed to reduce the size of the TContent } + { structure or to improve alignment } + TStateInt = Byte; + + TContent = Packed Record + { start and end of block instructions that defines the } + { content of this register. If Typ = con_const, then } + { Longint(StartMod) = value of the constant) } + StartMod: pai; + { starts at 0, gets increased everytime the register is } + { written to } + WState: TStateInt; + { starts at 0, gets increased everytime the register is read } + { from } + RState: TStateInt; + { how many instructions starting with StarMod does the block } + { consist of } + NrOfMods: Byte; + { the type of the content of the register: unknown, memory } + { (variable) or constant } + Typ: Byte; + End; + + TRegContent = Array[LoGPReg..HiGPReg] Of TContent; + +{ ************************************************************************** } +{ information object with the contents of every register. Every Pai object } +{ gets one of these assigned: a pointer to it is stored in the OptInfo field } +{ ************************************************************************** } + + PPaiProp = ^TPaiProp; + + TPaiProp = Object(TAoptBaseCpu) + Regs: TRegContent; + { info about allocation of general purpose integer registers } + UsedRegs: TUsedRegs; + { info about the conditional registers } + CondRegs: TCondRegs; + { can this instruction be removed? } + CanBeRemoved: Boolean; + + Constructor init; + + { checks the whole sequence of which (so regs[which].StartMod and and } + { the next NrOfMods Pai objects) to see whether Reg is used somewhere, } + { without it being loaded with something else first } + Function RegInSequence(Reg, which: TRegister): Boolean; + { destroy the contents of a register, as well as those whose contents } + { are based on those of that register } + Procedure DestroyReg(Reg: TRegister; var InstrSinceLastMod: + TInstrSinceLastMod); + { if the contents of WhichReg (can be R_NO in case of a constant) are } + { written to memory at the location Ref, the contents of the registers } + { that depend on Ref have to be destroyed } + Procedure DestroyRefs(Const Ref: TReference; WhichReg: TRegister; var + InstrSinceLastMod: TInstrSinceLastMod); + + { an instruction reads from operand o } + Procedure ReadOp(const o:toper); + { an instruction reads from reference Ref } + Procedure ReadRef(Ref: PReference); + { an instruction reads from register Reg } + Procedure ReadReg(Reg: TRegister); + + { an instruction writes/modifies operand o and this has special } + { side-effects or modifies the contents in such a way that we can't } + { simply add this instruction to the sequence of instructions that } + { describe the contents of the operand, so destroy it } + Procedure DestroyOp(const o:Toper; var InstrSinceLastMod: + TInstrSinceLastMod); + { destroy the contents of all registers } + Procedure DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod); +{$ifdef arithopt} + { a register's contents are modified, but not destroyed (the new value } + { depends on the old one) } + Procedure ModifyReg(reg: TRegister; var InstrSinceLastMod: + TInstrSinceLastMod); + { an operand's contents are modified, but not destroyed (the new value } + { depends on the old one) } + Procedure ModifyOp(const oper: TOper; var InstrSinceLastMod: + TInstrSinceLastMod); +{$endif arithopt} + + { increase the write state of a register (call every time a register is } + { written to) } + Procedure IncWState(Reg: TRegister); + { increase the read state of a register (call every time a register is } + { read from) } + Procedure IncRState(Reg: TRegister); + { get the write state of a register } + Function GetWState(Reg: TRegister): TStateInt; + { get the read state of a register } + Function GetRState(Reg: TRegister): TStateInt; + + { get the type of contents of a register } + Function GetRegContentType(Reg: TRegister): Byte; + + Destructor Done; + + Private + + Procedure IncState(var s: TStateInt); + + { returns whether the reference Ref is used somewhere in the loading } + { sequence Content } + Function RefInSequence(Const Ref: TReference; Content: TContent; + RefsEq: TRefCompare): Boolean; + + { returns whether the instruction P reads from and/or writes } + { to Reg } + Function RefInInstruction(Const Ref: TReference; p: Pai; + RefsEq: TRefCompare): Boolean; + + { returns whether two references with at least one pointing to an array } + { may point to the same memory location } + Function ArrayRefsEq(const r1, r2: TReference): Boolean; + + End; + +{ ************************************************************************* } +{ ************************ Label information ****************************** } +{ ************************************************************************* } + TLabelTableItem = Record + PaiObj: Pai; + End; + +{$ifndef TP} + TLabelTable = Array[0..2500000] Of TLabelTableItem; +{$else TP} + TLabelTable = Array[0..(65520 div sizeof(TLabelTableItem))] Of TLabelTableItem; +{$endif TP} + PLabelTable = ^TLabelTable; + PLabelInfo = ^TLabelInfo; + TLabelInfo = Record + { the highest and lowest label number occurring in the current code } + { fragment } + LowLabel, HighLabel: AWord; + LabelDif: AWord; + { table that contains the addresses of the Pai_Label objects associated } + { with each label number } + LabelTable: PLabelTable; + End; + +{ ************************************************************************* } +{ ********** General optimizer object, used to derive others from ********* } +{ ************************************************************************* } + + TAOptObj = Object(TAoptBaseCpu) + { the PAasmOutput list this optimizer instance works on } + AsmL: PAasmOutput; + + { The labelinfo record contains the addresses of the Pai objects } + { that are labels, how many labels there are and the min and max } + { label numbers } + LabelInfo: PLabelInfo; + + { Start and end of the block that is currently being optimized } + BlockStart, BlockEnd: Pai; + + { _AsmL is the PAasmOutpout list that has to be optimized, } + { _BlockStart and _BlockEnd the start and the end of the block } + { that has to be optimized and _LabelInfo a pointer to a } + { TLabelInfo record } + Constructor Init(_AsmL: PAasmOutput; _BlockStart, _BlockEnd: Pai; + _LabelInfo: PLabelInfo); + + { processor independent methods } + + { returns true if the label L is found between hp and the next } + { instruction } + Function FindLabel(L: PasmLabel; Var hp: Pai): Boolean; + + { inserts new_one between prev and foll in AsmL } + Procedure InsertLLItem(prev, foll, new_one: PLinkedList_Item); + + + { If P is a Pai object releveant to the optimizer, P is returned } + { If it is not relevant tot he optimizer, the first object after P } + { that is relevant is returned } + Function SkipHead(P: Pai): Pai; + + { returns true if the operands o1 and o2 are completely equal } + Function OpsEqual(const o1,o2:toper): Boolean; + + { Returns true if a ait_alloc object for Reg is found in the block } + { of Pai's starting with StartPai and ending with the next "real" } + { instruction } + Function FindRegAlloc(Reg: TRegister; StartPai: Pai): Boolean; + + { processor dependent methods } + + End; + + +{ ***************************** Implementation **************************** } + +Implementation + +uses hcodegen, globtype, globals, tainst; + +{ ************************************************************************* } +{ ******************************** TUsedRegs ****************************** } +{ ************************************************************************* } + +Constructor TUsedRegs.init; +Begin + UsedRegs := []; +End; + +Constructor TUsedRegs.InitWithValue(Const _RegSet: TRegSet); +Begin + UsedRegs := _RegSet; +End; + +Procedure TUsedRegs.Update(p: Pai); +{updates UsedRegs with the RegAlloc Information coming after P} +Begin + Repeat + While Assigned(p) And + ((p^.typ in (SkipInstr - [ait_RegAlloc])) or + ((p^.typ = ait_label) And + Not(Pai_Label(p)^.l^.is_used))) Do + p := Pai(p^.next); + While Assigned(p) And + (p^.typ=ait_RegAlloc) Do + Begin + if pairegalloc(p)^.allocation then + UsedRegs := UsedRegs + [PaiRegAlloc(p)^.Reg] + else + UsedRegs := UsedRegs - [PaiRegAlloc(p)^.Reg]; + p := pai(p^.next); + End; + Until Not(Assigned(p)) Or + (Not(p^.typ in SkipInstr) And + Not((p^.typ = ait_label) And + Not(Pai_Label(p)^.l^.is_used))); +End; + +Function TUsedRegs.IsUsed(Reg: TRegister): Boolean; +Begin + IsUsed := Reg in UsedRegs +End; + +Function TUsedRegs.GetUsedRegs: TRegSet; +Begin + GetUsedRegs := UsedRegs; +End; + +Destructor TUsedRegs.Done; {$ifdef inl} inline; {$endif inl} +Begin +end; + +{ ************************************************************************* } +{ **************************** TPaiProp *********************************** } +{ ************************************************************************* } + +Constructor TPaiProp.Init; +Begin + UsedRegs.Init; + CondRegs.init; +{ DirFlag: TFlagContents; I386 specific} +End; + +Function TPaiProp.RegInSequence(Reg, which: TRegister): Boolean; +Var p: Pai; + RegsChecked: TRegSet; + content: TContent; + Counter: Byte; + TmpResult: Boolean; +Begin + RegsChecked := []; + content := regs[which]; + p := content.StartMod; + TmpResult := False; + Counter := 1; + While Not(TmpResult) And + (Counter <= Content.NrOfMods) Do + Begin + If IsLoadMemReg(p) Then + With PInstr(p)^.oper[LoadSrc].ref^ Do + If (Base = ProcInfo.FramePointer) +{$ifdef RefsHaveIndexReg} + And (Index = R_NO) +{$endif RefsHaveIndexReg} Then + Begin + RegsChecked := RegsChecked + + [RegMaxSize(PInstr(p)^.oper[LoadDst].reg)]; + If Reg = RegMaxSize(PInstr(p)^.oper[LoadDst].reg) Then + Break; + End + Else + Begin + If (Base = Reg) And + Not(Base In RegsChecked) + Then TmpResult := True; +{$ifdef RefsHaveIndexReg} + If Not(TmpResult) And + (Index = Reg) And + Not(Index In RegsChecked) + Then TmpResult := True; +{$Endif RefsHaveIndexReg} + End + Else TmpResult := RegInInstruction(Reg, p); + Inc(Counter); + GetNextInstruction(p,p) + End; + RegInSequence := TmpResult +End; + + +Procedure TPaiProp.DestroyReg(Reg: TRegister; var InstrSinceLastMod: + TInstrSinceLastMod); +{ 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 TmpWState, TmpRState: Byte; + Counter: TRegister; +Begin + Reg := RegMaxSize(Reg); + If (Reg in [R_EAX..R_EDI]) Then + For Counter := R_EAX to R_EDI Do + With Regs[Counter] Do + If (Counter = reg) Or + ((Typ = Con_Ref) And + RegInSequence(Reg, Counter)) Then + Begin + InstrSinceLastMod[Counter] := 0; + IncWState(Counter); + TmpWState := GetWState(Counter); + TmpRState := GetRState(Counter); + FillChar(Regs[Counter], SizeOf(TContent), 0); + WState := TmpWState; + RState := TmpRState + End +End; + +Function TPaiProp.ArrayRefsEq(const r1, r2: TReference): Boolean; +Begin + ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And + (R1.Segment = R2.Segment) And (R1.Base = R2.Base) And + (R1.Symbol=R2.Symbol); +End; + +Procedure TPaiProp.DestroyRefs(Const Ref: TReference; WhichReg: TRegister; + var InstrSinceLastMod: TInstrSinceLastMod); +{ 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 := RegMaxSize(WhichReg); + If (Ref.base = procinfo^.FramePointer) or + Assigned(Ref.Symbol) Then + Begin + If +{$ifdef refsHaveIndexReg} + (Ref.Index = R_NO) And +{$endif refsHaveIndexReg} + (Not(Assigned(Ref.Symbol)) or + (Ref.base = R_NO)) Then + { local variable which is not an array } + RefsEq := {$ifdef fpc}@{$endif}RefsEqual + Else + { local variable which is an array } + RefsEq := {$ifdef fpc}@{$endif}ArrayRefsEq; +{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 or value based on Ref) + * with uncertain optimizations off: + - also destroy registers that contain any pointer} + For Counter := LoGPReg to HiGPReg Do + With Regs[Counter] Do + Begin + If (typ = Con_Ref) And + ((Not(cs_UncertainOpts in aktglobalswitches) And + (NrOfMods <> 1) + ) Or + (RefInSequence(Ref,Regs[Counter], RefsEq) And + ((Counter <> WhichReg) Or + ((NrOfMods <> 1) And + {StarMod is always of the type ait_instruction} + (PInstr(StartMod)^.oper[0].typ = top_ref) And + RefsEq(PInstr(StartMod)^.oper[0].ref^, Ref) + ) + ) + ) + ) + Then + DestroyReg(Counter, InstrSinceLastMod) + 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 := LoGPReg to HiGPReg Do + With Regs[Counter] Do + If (typ = Con_Ref) And + (Not(cs_UncertainOpts in aktglobalswitches) Or +{$ifdef i386} + {for movsl} + (Ref.Base = R_EDI) Or +{$endif} + {don't destroy if reg contains a parameter, local or global variable} + Not((NrOfMods = 1) And + (PInstr(StartMod)^.oper[0].typ = top_ref) And + ((PInstr(StartMod)^.oper[0].ref^.base = ProcInfo.FramePointer) Or + Assigned(PInstr(StartMod)^.oper[0].ref^.Symbol) + ) + ) + ) + Then DestroyReg(Counter, InstrSinceLastMod) +End; + +Procedure TPaiProp.DestroyAllRegs(var InstrSinceLastMod: TInstrSinceLastMod); +Var Counter: TRegister; +Begin {initializes/desrtoys all registers} + For Counter := R_EAX To R_EDI Do + Begin + ReadReg(Counter); + DestroyReg(Counter, InstrSinceLastMod); + End; + CondRegs.Init; +{ FPURegs.Init; } +End; + +Procedure TPaiProp.DestroyOp(const o:Toper; var InstrSinceLastMod: + TInstrSinceLastMod); +Begin + Case o.typ Of + top_reg: DestroyReg(o.reg, InstrSinceLastMod); + top_ref: + Begin + ReadRef(o.ref^); + DestroyRefs(o.ref^, R_NO, InstrSinceLastMod); + End; + top_symbol:; + End; +End; + +Procedure TPaiProp.ReadReg(Reg: TRegister); +Begin + Reg := RegMaxSize(Reg); + If Reg in General_Registers Then + IncRState(RegMaxSize(Reg)) +End; + +Procedure TPaiProp.ReadRef(Ref: PReference); +Begin + If Ref^.Base <> R_NO Then + ReadReg(Ref^.Base); + If Ref^.Index <> R_NO Then + ReadReg(Ref^.Index); +End; + +Procedure TPaiProp.ReadOp(const o:toper); +Begin + Case o.typ Of + top_reg: ReadReg(o.reg); + top_ref: ReadRef(o.ref); + top_symbol : ; + End; +End; + +{$ifdef arithopt} +Procedure TPaiProp.ModifyReg(reg: TRegister; Var InstrSinceLastMod: + TInstrSinceLastMod); +Begin + With Regs[reg] Do + If (Typ = Con_Ref) + Then + Begin + IncState(WState); + {also store how many instructions are part of the sequence in the first + instructions PPaiProp, so it can be easily accessed from within + CheckSequence} + Inc(NrOfMods, NrOfInstrSinceLastMod[Reg]); + PPaiProp(StartMod^.OptInfo)^.Regs[Reg].NrOfMods := NrOfMods; + NrOfInstrSinceLastMod[Reg] := 0; + End + Else + DestroyReg(Reg, InstrSinceLastMod); +End; + +Procedure TPaiProp.ModifyOp(const oper: TOper; var InstrSinceLastMod: + TInstrSinceLastMod); +Begin + If oper.typ = top_reg Then + ModifyReg(RegMaxSize(oper.reg)) + Else + Begin + ReadOp(oper); + DestroyOp(oper, InstrSinceLastMod); + End +End; +{$endif arithopt} + +Procedure TPaiProp.IncWState(Reg: TRegister);{$ifdef inl} inline;{$endif inl} +Begin + IncState(Regs[Reg].WState); +End; + +Procedure TPaiProp.IncRState(Reg: TRegister);{$ifdef inl} inline;{$endif inl} +Begin + IncState(Regs[Reg].RState); +End; + +Function TPaiProp.GetWState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl} +Begin + GetWState := Regs[Reg].WState +End; + +Function TPaiProp.GetRState(Reg: TRegister): TStateInt; {$ifdef inl} inline;{$endif inl} +Begin + GetRState := Regs[Reg].RState +End; + +Function TPaiProp.GetRegContentType(Reg: TRegister): Byte; {$ifdef inl} inline;{$endif inl} +Begin + GetRegContentType := Regs[Reg].typ +End; + +Destructor TPaiProp.Done; +Begin + UsedRegs.Done; + CondRegs.Done; +{ DirFlag: TFlagContents; I386 specific} +End; +{ ************************ private TPaiProp stuff ************************* } + +Procedure TPaiProp.IncState(Var s: TStateInt); {$ifdef inl} inline;{$endif inl} +Begin + If s <> High(TStateInt) Then Inc(s) + Else s := 0 +End; + +Function TPaiProp.RefInInstruction(Const Ref: TReference; p: Pai; + RefsEq: TRefCompare): Boolean; +Var Count: AWord; + TmpResult: Boolean; +Begin + TmpResult := False; + If (p^.typ = ait_instruction) Then + Begin + Count := 0; + Repeat + If (PInstr(p)^.oper[Count].typ = Top_Ref) Then + TmpResult := RefsEq(Ref, PInstr(p)^.oper[Count].ref^); + Inc(Count); + Until (Count = MaxOps) or TmpResult; + End; + RefInInstruction := TmpResult; +End; + +Function TPaiProp.RefInSequence(Const Ref: TReference; Content: TContent; + RefsEq: TRefCompare): Boolean; +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; + +{ ************************************************************************* } +{ ***************************** TAoptObj ********************************** } +{ ************************************************************************* } + +Constructor TAoptObj.Init(_AsmL: PAasmOutput; _BlockStart, _BlockEnd: Pai; + _LabelInfo: PLabelInfo); +Begin + AsmL := _AsmL; + BlockStart := _BlockStart; + BlockEnd := _BlockEnd; + LabelInfo := _LabelInfo +End; + +Function TAOptObj.FindLabel(L: PasmLabel; Var hp: Pai): Boolean; +Var TempP: Pai; +Begin + TempP := hp; + While Assigned(TempP) and + (TempP^.typ In SkipInstr + [ait_label]) Do + If (TempP^.typ <> ait_Label) Or + (pai_label(TempP)^.l <> L) + Then GetNextInstruction(TempP, TempP) + Else + Begin + hp := TempP; + FindLabel := True; + exit + End; + FindLabel := False; +End; + +Procedure TAOptObj.InsertLLItem(prev, foll, new_one: PLinkedList_Item); +Begin + If Assigned(prev) Then + If Assigned(foll) Then + Begin + If Assigned(new_one) Then + Begin + new_one^.previous := prev; + new_one^.next := foll; + prev^.next := new_one; + foll^.previous := new_one; + Pai(new_one)^.fileinfo := Pai(foll)^.fileinfo + End + End + Else AsmL^.Concat(new_one) + Else If Assigned(Foll) Then AsmL^.Insert(new_one) +End; + + +Function TAOptObj.SkipHead(P: Pai): Pai; +Var OldP: Pai; +Begin + Repeat + OldP := P; + If (P^.typ in SkipInstr) Or + ((P^.typ = ait_marker) And + (Pai_Marker(P)^.Kind = AsmBlockEnd)) Then + GetNextInstruction(P, P) + Else If ((P^.Typ = Ait_Marker) And + (Pai_Marker(P)^.Kind = NoPropInfoStart)) Then + { a marker of the type NoPropInfoStart can't be the first instruction of a } + { paasmoutput list } + GetNextInstruction(Pai(P^.Previous),P); + If (P^.Typ = Ait_Marker) And + (Pai_Marker(P)^.Kind = AsmBlockStart) Then + Begin + P := Pai(P^.Next); + While (P^.typ <> Ait_Marker) Or + (Pai_Marker(P)^.Kind <> AsmBlockEnd) Do + P := Pai(P^.Next) + End; + Until P = OldP; + SkipHead := P; +End; + +Function TAOptObj.OpsEqual(const o1,o2:toper): Boolean; +Begin + if o1.typ=o2.typ then + Case o1.typ Of + Top_Reg : + OpsEqual:=o1.reg=o2.reg; + Top_Ref : + OpsEqual := RefsEqual(o1.ref^, o2.ref^); + Top_Const : + OpsEqual:=o1.val=o2.val; + Top_Symbol : + OpsEqual:=(o1.sym=o2.sym) and (o1.symofs=o2.symofs); + Top_None : + OpsEqual := True + else OpsEqual := False + End; +End; + +Function TAOptObj.FindRegAlloc(Reg: TRegister; StartPai: Pai): Boolean; +Begin + FindRegAlloc:=False; + Repeat + While Assigned(StartPai) And + ((StartPai^.typ in (SkipInstr - [ait_regAlloc])) Or + ((StartPai^.typ = ait_label) and + Not(Pai_Label(StartPai)^.l^.Is_Used))) Do + StartPai := Pai(StartPai^.Next); + If Assigned(StartPai) And + (StartPai^.typ = ait_regAlloc) and (PairegAlloc(StartPai)^.allocation) Then + Begin + if PairegAlloc(StartPai)^.Reg = Reg then + begin + FindRegAlloc:=true; + exit; + end; + StartPai := Pai(StartPai^.Next); + End + else + exit; + Until false; +End; + +End. + +{ $Log$ - Revision 1.5 1999-08-26 14:50:52 jonas + Revision 1.6 1999-09-29 13:50:34 jonas + * fixes from daopt386.pas integrated + + Revision 1.5 1999/08/26 14:50:52 jonas * fixed small type in TP conditional - - Revision 1.4 1999/08/18 14:32:22 jonas - + compilable! - + dataflow analyzer finished - + start of CSE units - + aoptbase which contains a base object for all optimizer objects - * some constants and type definitions moved around to avoid circular - dependencies - * moved some methods from base objects to specialized objects because - they're not used anywhere else - - Revision 1.2 1999/08/09 14:07:24 jonas - commit.msg - - Revision 1.1 1999/08/08 13:24:50 jonas - + added copyright header/GNU license info - * made the assembler optimizer almost completely OOP - * some code style clean up and extra comments - * moved from the new/aopt to the /new and /new/i386 dirs - + + Revision 1.4 1999/08/18 14:32:22 jonas + + compilable! + + dataflow analyzer finished + + start of CSE units + + aoptbase which contains a base object for all optimizer objects + * some constants and type definitions moved around to avoid circular + dependencies + * moved some methods from base objects to specialized objects because + they're not used anywhere else + + Revision 1.2 1999/08/09 14:07:24 jonas + commit.msg + + Revision 1.1 1999/08/08 13:24:50 jonas + + added copyright header/GNU license info + * made the assembler optimizer almost completely OOP + * some code style clean up and extra comments + * moved from the new/aopt to the /new and /new/i386 dirs + } \ No newline at end of file