2
0
Эх сурвалжийг харах

* InstrSinceLastMod parameter added to destroy/modify methods

Jonas Maebe 26 жил өмнө
parent
commit
aa5615a2e1
1 өөрчлөгдсөн 0 нэмэгдсэн , 1204 устгасан
  1. 0 1204
      compiler/new/aoptobj.pas

+ 0 - 1204
compiler/new/aoptobj.pas

@@ -1,1204 +0,0 @@
-{
-    $Id$
-    Copyright (c) 1999 by Jonas Maebe, member of the Free Pascal
-    Development Team
-
-    This unit contains the processor independent assembler optimizer
-    object.
-
-    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 Cobjects, cpubase, aoptcpub;
-
-{***************** Constants *****************}
-
-Const
-
-{ ait_* types which don't result in executable code or which don't influence }
-{ the way the program runs/behaves                                           }
-
-  SkipInstr = [ait_comment, ait_align, ait_symbol
-{$ifdef GDB}
-  ,ait_stabs, ait_stabn, ait_stab_function_name
-{$endif GDB}
-  ,ait_regalloc, ait_tempalloc
-  ];
-
-{Possible register content types}
-  con_Unknown = 0;
-  con_ref = 1;
-  con_const = 2;
-
-{***************** Types ****************}
-
-Type
-
-  TRegArray = Array[LoReg..HiReg] of TRegister;
-  TRegSet = Set of LoReg..HiReg;
-  PRegInfo = ^TReginfo;
-
- { info about the equivalence of registers when comparing two code sequences}
-  TRegInfo = Object
-                { registers encountered in the new and old sequence }
-                NewRegsEncountered, OldRegsEncountered,
-                { registers which only have been loaded for use as base or }
-                { index in a reference later on                            }
-                RegsLoadedForRef: TRegSet;
-                { to which register in the old sequence corresponds every }
-                { register in the new sequence                            }
-                New2OldReg: TRegArray;
-
-                Constructor init;
-                { clear all information store in the object }
-                Procedure Clear;
-                { the contents of OldReg in the old sequence are now being }
-                { loaded into NewReg in the new sequence                   }
-                Procedure AddReg(OldReg, NewReg: TRegister); Virtual;
-                { the contents of OldOp in the old sequence are now being   }
-                { loaded into NewOp in the new sequence. It is assumed that }
-                { OldOp and NewOp are equivalent                            }
-                Procedure AddOp(const OldOp, NewOp:Toper);
-                { check if a register in the old sequence (OldReg) can be  }
-                { equivalent to a register in the new sequence (NewReg) if }
-                { the operation OpAct is performed on it. The RegInfo is   }
-                { updated (not necessary to call AddReg afterwards         }
-                Function RegsEquivalent(OldReg, NewReg: TRegister;
-                           OpAct: TopAction): Boolean;
-                { check if a reference in the old sequence (OldRef) can be  }
-                { equivalent to a reference in the new sequence (NewRef) if }
-                { the operation OpAct is performed on it. The RegInfo is    }
-                { updated (not necessary to call AddOp afterwards           }
-                Function RefsEquivalent(Const OldRef, NewRef: TReference;
-                           OpAct: TOpAction): Boolean;
-                { check if an operand in the old sequence (OldOp) can be  }
-                { equivalent to an operand in the new sequence (NewOp) if }
-                { the operation OpAct is performed on it. The RegInfo is  }
-                { updated (not necessary to call AddOp afterwards         }
-                Function OpsEquivalent(const OldOp, NewOp: toper;
-                           OpAct: TopAction): Boolean;
-                { check if an instruction in the old sequence (OldP) can be }
-                { equivalent to an instruction in the new sequence (Newp)   }
-                { The RegInfo is  updated                                   }
-                Function InstructionsEquivalent(OldP, NewP: Pai): Boolean;
-              End;
-
-
-{ possible actions on an operand: read, write or modify (= read & write) }
-  TOpAction = (OpAct_Read, OpAct_Write, OpAct_Modify, OpAct_Unknown);
-
-{ the properties of a cpu instruction }
-  TAsmInstrucProp = Record
-                      { what it changes }
-                      Ch: Array[1..MaxCh] of TChange;
-                    End;
-
-{ Object to hold on information on which regiters are in use and which not }
-  TUsedRegs = Object
-                Constructor init;
-                Constructor InitWithValue(_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;
-
- { 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;
-
-{ Contents of the integer registers }
-
-  TRegContent = Array[LoGPReg..HiGPReg] Of TContent;
-
-  PPaiProp = ^TPaiProp;
-
-{ 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 }
-  TPaiProp = Object
-               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;
-
-               { destroy the contents of a register, as well as those whose }
-               { contents are based on those of that register               }
-               Procedure DestroyReg(Reg: TRegister; var NrOfInstrSinceLastMod:
-                                      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);
-               { 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);
-               { destroy the contetns of all registers }
-               Procedure DestroyAllRegs;
-{$ifdef arithopt}
-               { a register's contents are modified, but not destroyed }
-               { (the new value depends on the old one)                }
-               Procedure ModifyReg(reg: TRegister);
-               { an operand's contents are modified, but not destroyed }
-               { (the new value depends on the old one)                }
-               Procedure ModifyOp(const oper: TOper);
-{$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 GetRegContentKind(Reg: TRegister): Byte;
-
-               Destructor Done;
-
-               Private
-
-               Procedure IncState(Reg: TRegister);
-
-             End;
-
-  { the number of instructions that we have encountered since the last }
-  { modification of a register                                         }
-  TInstrSinceLastMod = Array[LoGPReg..HiGPReg] Of Byte;
-
-  TLabelTableItem = Record
-                      PaiObj: Pai;
-{$IfDef JumpAnal}
-                      InstrNr: Longint;
-                      RefsFound: Word;
-                      JmpsProcessed: Word
-{$EndIf JumpAnal}
-                    End;
-
-  TLabelTable = Array[0..2500000] Of TLabelTableItem;
-  PLabelTable = ^TLabelTable;
-  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: PLableTable;
-  End;
-
-
-{***** General optimizer object, used to derive others from *****}
-
-Type TAOptObj = Object
-       { 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(AsmL: PAasmOutput; prev, foll, new_one:
-                   PLinkedList_Item);
-
-       { returns true if register Reg is used by instruction p1 }
-       Function RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
-       { returns true if register Reg is used in the reference Ref }
-       Function RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
-       { returns whether the reference Ref is used somewhere in the loading }
-       { sequence Constent                                                  }
-       Function TAOptObj.RefInSequence(Const Ref: TReference;
-                                         Content: TContent): Boolean;
-       { returns whether the instruction P reads from and/or writes to Reg }
-       Function TAOptObj.RefInInstruction(Const Ref: TReference; p: Pai): Boolean;
-       { returns true if the instruction p1 modifies the register Reg }
-       Function RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
-
-       { gets the next Pai object after current that contains info relevant }
-       { to the optimizer in p1. If there is none, it returns false and     }
-       { sets p1 to nil                                                     }
-       Function GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
-       { gets the previous Pai object after current that contains info  }
-       { relevant to the optimizer in last. If there is none, it retuns }
-       { false and sets last to nil                                     }
-       Function GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
-       { If P is a Pai object releveant to the optimizer, it is left  }
-       { unchanged. If it is not relevant tot he optimizer, the first }
-       { object after P that is relevant is stored in P               }
-       Procedure SkipHead(var P: 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 }
-
-       { returns the maximum width component of Reg. Only has to be }
-       { overridden for the 80x86 (afaik)                           }
-       Function RegMaxSize(Reg: TRegister): TRegister; Virtual;
-       { returns true if Reg1 and Reg2 are of the samae width. Only has to }
-       { overridden for the 80x86 (afaik)                                  }
-       Function RegsSameSize(Reg1, Reg2: TRegister): Boolean; Virtual;
-       { returns whether P is a load instruction (load contents from a }
-       { memory location or (register) variable into a register)       }
-       Function IsLoadInstr(p: pai): Boolean; Virtual;
-       { returns whether P is a store instruction (store contents from a }
-       { register to a memory location or to a (register) variable)      }
-       Function IsStoreInstr(p: pai): Boolean; Virtual;
-       { returns whether the instruction P reads from register Reg }
-       Function RegReadByInstr(Reg: TRegister; p: Pai); Virtual;
-       { convert a TChange value into the corresponding register }
-       Function TCh2Reg(Ch: TChange): TRegister; Virtual;
-     End;
-
-{***************** Implementation *****************}
-
-Implementation
-
-{*********************** TReginfo ***********************}
-
-Constructor TRegInfo.Init;
-Begin
-  Clear;
-End;
-
-Constructor TRegInfo.Init;
-Begin
-  RegsLoadedForRef   := [];
-  NewRegsEncountered := [ProcInfo.FramePointer, R_ESP];
-  OldRegsEncountered := [ProcInfo.FramePointer, R_ESP];
-  New2OldReg[ProcInfo.FramePointer] := ProcInfo.FramePointer;
-  New2OldReg[R_ESP] := R_ESP;
-End;
-
-Procedure TRegInfo.AddReg(OldReg, NewReg: TRegister);
-{ updates the ???RegsEncountered and ???2???Reg fields of RegInfo. Assumes  }
-{ that OldReg and NewReg have the same size (has to be chcked in advance    }
-{ with RegsSameSize) and that neither equals R_NO                           }
-{ has to be overridden for architectures like the 80x86 when not all GP     }
-{ regs are of the same size                                                 }
-Begin
-  NewRegsEncountered := NewRegsEncountered + [NewReg];
-  OldRegsEncountered := OldRegsEncountered + [OldReg];
-  New2OldReg[NewReg] := OldReg;
-End;
-
-Procedure TRegInfo.AddOp(const OldOp, NewOp:Toper);
-Begin
-  Case OldOp.typ Of
-    Top_Reg:
-      If (OldOp.reg <> R_NO) Then
-        AddReg(OldOp.reg, NewOp.reg);
-    Top_Ref:
-      Begin
-        If OldOp.ref^.base <> R_NO Then
-          AddReg(OldOp.ref^.base, NewOp.ref^.base);
-{$ifdef RefsHaveIndexReg}
-        If OldOp.ref^.index <> R_NO Then
-          AddReg(OldOp.ref^.index, NewOp.ref^.index);
-{$endif RefsHaveIndexReg}
-      End;
-  End;
-End;
-
-Function TRegInfo.RegsEquivalent(OldReg, NewReg: TRegister;
-           OPAct: TOpAction): Boolean;
-Begin
-  If Not((OldReg = R_NO) Or (NewReg = R_NO)) Then
-    If RegsSameSize(OldReg, NewReg) Then
-{here we always check for the 32 bit component, because it is possible that
- the 8 bit component has not been set, event though NewReg already has been
- processed. This happens if it has been compared with a register that doesn't
- have an 8 bit component (such as EDI). In that case the 8 bit component is
- still set to R_NO and the comparison in the Else-part will fail}
-      If (RegMaxSize(OldReg) in OldRegsEncountered) Then
-        If (RegMaxSize(NewReg) in NewRegsEncountered) Then
-          RegsEquivalent := (OldReg = New2OldReg[NewReg])
-
- { If we haven't encountered the new register yet, but we have encountered the
-   old one already, the new one can only be correct if it's being written to
-   (and consequently the old one is also being written to), otherwise
-
-   movl -8(%ebp), %eax        and         movl -8(%ebp), %eax
-   movl (%eax), %eax                      movl (%edx), %edx
-
-   are considered equivalent}
-
-        Else
-          If (OpAct = OpAct_Write) Then
-            Begin
-              AddReg(OldReg, NewReg);
-              RegsEquivalent := True
-            End
-          Else Regsequivalent := False
-      Else
-        If Not(RegMaxSize(NewReg) in NewRegsEncountered) Then
-          Begin
-            AddReg(OldReg, NewReg);
-            RegsEquivalent := True
-          End
-        Else RegsEquivalent := False
-    Else RegsEquivalent := False
-  Else RegsEquivalent := OldReg = NewReg
-End;
-
-Function TRegInfo.RefsEquivalent(Const OldRef, NewRef: TReference;
-           OpAct: TOpAction): Boolean;
-Begin
-  If OldRef.is_immediate Then
-    RefsEquivalent := NewRef.is_immediate and (OldRef.Offset = NewRef.Offset)
-  Else
-    RefsEquivalent := (OldRef.Offset+OldRef.OffsetFixup =
-                         NewRef.Offset+NewRef.OffsetFixup) And
-                      RegsEquivalent(OldRef.Base, NewRef.Base, OpAct)
-{$ifdef RefsHaveindex}
-                      And RegsEquivalent(OldRef.Index, NewRef.Index, OpAct)
-{$endif RefsHaveIndex}
-{$ifdef RefsHaveScale}
-                      And (OldRef.ScaleFactor = NewRef.ScaleFactor)
-{$endif RefsHaveScale}
-                      And (OldRef.Symbol = NewRef.Symbol)
-{$ifdef RefsHaveSegment}
-                      And (OldRef.Segment = NewRef.Segment)
-{$endif RefsHaveSegment}
-                      ;
-End;
-
-Function TRegInfo.OpsEquivalent(const OldOp, NewOp: toper; OpAct: TopAction):
-           Boolean;
-Begin {checks whether the two ops are equivalent}
-  OpsEquivalent := False;
-  if OldOp.typ=NewOp.typ then
-    Case OldOp.typ Of
-      Top_Const: OpsEquivalent := OldOp.value = NewOp.value;
-      Top_Reg:
-        OpsEquivalent := RegsEquivalent(OldOp.reg,NewOp.reg, OpAct);
-      Top_Ref:
-        OpsEquivalent := RefsEquivalent(OldOp.ref^, NewOp.ref^, OpAct);
-      Top_None:
-        OpsEquivalent := True
-    End;
-End;
-
-Function TRegInfo.InstructionsEquivalent(OldP, NewP: Pai): Boolean;
-{ checks whether two PInstr instructions are equal                     }
-Var Count: TNatInt;
-    TmpResult: Boolean;
-Begin
-  If Assigned(OldP) And Assigned(NewP) And
-     (Pai(OldP)^.typ = ait_instruction) And
-     (Pai(NewP)^.typ = ait_instruction) And
-     (PInstr(OldP)^.opcode = PInstr(NewP)^.opcode) And
-     (PInstr(OldP)^.oper[0].typ = PInstr(NewP)^.oper[0].typ) And
-     (PInstr(OldP)^.oper[1].typ = PInstr(NewP)^.oper[1].typ) And
-     (PInstr(OldP)^.oper[2].typ = PInstr(NewP)^.oper[2].typ)
-    Then
-{ both instructions have the same structure:                                }
-{ "<operator> <operand of type1>, <operand of type 2>"                      }
-      If IsLoadInstr(OldP) {then also NewP = loadinstr} Then
-        If Not(RegInRef(PInstr(OldP)^.oper[LoadDst].reg,
-                 PInstr(OldP)^.oper[LoadSrc].ref^)) Then
-{ the "old" instruction is a load of a register with a new value, not with  }
-{ a value based on the contents of this register (so no "mov (reg), reg")   }
-          If Not(RegInRef(PInstr(NewP)^.oper[LoadDst].reg,
-                          PInstr(NewP)^.oper[LoadSrc].ref^)) And
-             RefsEqual(PInstr(OldP)^.oper[LoadSrc].ref^,
-                       PInstr(NewP)^.oper[LoadSrc].ref^)
-            Then
-{ the "new" instruction is also a load of a register with a new value, and  }
-{ this value is fetched from the same memory location                       }
-              Begin
-                With PInstr(NewP)^.oper[LoadSrc].ref^ Do
-                  Begin
-                    If Not(Base in [ProcInfo.FramePointer, R_NO, StackPtr])
-{ it won't do any harm if the register is already in RegsLoadedForRef       }
-                      Then RegsLoadedForRef := RegsLoadedForRef + [Base];
-{$ifdef RefsHaveIndex}
-                    If Not(Index in [ProcInfo.FramePointer, R_NO, R_StackPtr])
-                      Then RegsLoadedForRef := RegsLoadedForRef + [Index];
-{$endif RefsHaveIndex}
-                  End;
-{ add the registers from the reference (.oper[Src]) to the RegInfo, all     }
-{ registers from the reference are the same in the old and in the new       }
-{ instruction sequence                                                      }
-                AddOp(PInstr(OldP)^.oper[Src], PInstr(OldP)^.oper[Src]);
-{ the registers from .oper[Dest] have to be equivalent, but not necessarily }
-{ equal                                                                     }
-                InstructionsEquivalent :=
-                  RegsEquivalent(PInstr(OldP)^.oper[Dest].reg,
-                                 PInstr(NewP)^.oper[Dest].reg, OpAct_Write);
-              End
-{ the registers are loaded with values from different memory locations. If  }
-{ this were allowed, the instructions "mov -4(%esi),%eax" and               }
-{  "mov -4(%ebp),%eax" would be considered equivalent                       }
-            Else InstructionsEquivalent := False
-        Else
-{ load register with a value based on the current value of this register    }
-          Begin
-            With PInstr(NewP)^.oper[0].ref^ Do
-{ Assume the registers occurring in the reference have only been loaded with }
-{ the value they contain now to calculate an address (so the value they have }
-{ now, won't be stored to memory later on)}
-              Begin
-                If Not(Base in [ProcInfo.FramePointer,
-                                RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg),
-                                R_NO,StackPtr])
-{ It won't do any harm if the register is already in RegsLoadedForRef        }
-                  Then
-                    Begin
-                      RegsLoadedForRef := RegsLoadedForRef + [Base];
-{$ifdef csdebug}
-                      Writeln(att_reg2str[base], ' added');
-{$endif csdebug}
-                    end;
-{$Ifdef RefsHaveIndex}
-                If Not(Index in [ProcInfo.FramePointer,
-                                 RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg),
-                                 R_NO,StackPtr])
-                  Then
-                    Begin
-                      RegsLoadedForRef := RegsLoadedForRef + [Index];
-{$ifdef csdebug}
-                      Writeln(att_reg2str[index], ' added');
-{$endif csdebug}
-                    end;
-{$endif RefsHaveIndex}
-              End;
-
-{ now, remove the destination register of the load from the                 }
-{ RegsLoadedForReg, since if it's loaded with a new value, it certainly     }
-{ will still be used later on                                               }
-            If Not(RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg) In
-                [ProcInfo.FramePointer,R_NO,StackPtr])
-              Then
-                Begin
-                  RegsLoadedForRef := RegsLoadedForRef -
-                    [RegMaxSize(PInstr(NewP)^.oper[LoadDst].reg)];
-{$ifdef csdebug}
-                  Writeln(att_reg2str[Reg32(Pai386(NewP)^.oper[1].reg)], ' removed');
-{$endif csdebug}
-                end;
-            InstructionsEquivalent :=
-               OpsEquivalent(PInstr(OldP)^.oper[LoadSrc],
-                             PInstr(NewP)^.oper[LoadSrc], OpAct_Read) And
-               OpsEquivalent(PInstr(OldP)^.oper[LoadDst],
-                             PInstr(NewP)^.oper[LoadDst], OpAct_Write)
-          End
-      Else
- {an instruction that's not a load instruction}
-       Begin
-         Count := 0;
-         TmpResult := true;
-         Repeat
-           TmpResult :=
-             OpsEquivalent(PInstr(OldP)^.oper[Count], PInstr(NewP)^.oper[Count],
-                           OpAct_Unknown);
-           Inc(Count)
-         Until (Count = MaxOps) or not(TmpResult);
-         InstructionsEquivalent := TmpResult
-       End
-{ the instructions haven't even got the same structure, so they're certainly }
-{ not equivalent                                                             }
-    Else InstructionsEquivalent := False;
-End;
-
-{*************************** TUsedRegs ***************************}
-
-Constructor TUsedRegs.init;
-Begin
-  UsedRegs := [];
-End;
-
-Constructor TUsedRegisters.InitWithValue(Const _RegSet: TRegSet);
-Begin
-  RegSet := _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;
-
-{*************************** TPaiProp ***************************}
-
-Constructor TPaiProp.Init;
-Begin
-  UsedRegs.Init;
-  CondRegs.init;
-{  DirFlag: TFlagContents; I386 specific}
-End;
-
-Procedure TPaiProp.DestroyReg(Reg: TRegister; var NrOfInstrSinceLastMod:
-                                                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 := Reg32(Reg);
-  NrOfInstrSinceLastMod[Reg] := 0;
-  If (Reg >= R_EAX) And (Reg <= R_EDI)
-    Then
-      Begin
-        With Regs[Reg] Do
-          Begin
-            IncState(WState);
-            TmpWState := WState;
-            TmpRState := RState;
-            FillChar(Regs[Reg], SizeOf(TContent), 0);
-            WState := TmpWState;
-            RState := TmpRState;
-          End;
-        For Counter := R_EAX to R_EDI Do
-          With Regs[Counter] Do
-            If (Typ = Con_Ref) And
-               RegInSequence(Reg, Regs[Counter])
-              Then
-                Begin
-                  IncState(WState);
-                  TmpWState := WState;
-                  TmpRState := RState;
-                  FillChar(Regs[Counter], SizeOf(TContent), 0);
-                  WState := TmpWState;
-                  RState := TmpRState;
-                End;
-       End;
-End;
-
-Procedure TPaiProp.DestroyRefs(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 Counter: TRegister;
-Begin
-  WhichReg := RegMaxSize(WhichReg);
-  If ((Ref.base = ProcInfo.FramePointer) And
-{$ifdef refsHaveIndex}
-      (Ref.Index = R_NO)
-{$endif refsHaveIndex}
-      ) 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)
-          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)
-End;
-
-Procedure TPaiProp.DestroyAllRegs;
-Var Counter: TRegister;
-Begin {initializes/desrtoys all registers}
-  For Counter := R_EAX To R_EDI Do
-    DestroyReg(Counter);
-  CondRegs.Init;
-{ FPURegs.Init; }
-End;
-
-Procedure TPaiProp.DestroyOp(const o:Toper);
-Begin
-  Case o.typ Of
-    top_reg: DestroyReg(o.reg);
-    top_ref: DestroyRefs(o.ref^, R_NO);
-    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 NrOfInstrSinceLastMod:
-                               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, NrOfInstrSinceLastMod);
-End;
-
-Procedure TPaiProp.ModifyOp(const oper: TOper);
-Begin
-  If oper.typ = top_reg Then
-    ModifyReg(RegMaxSize(oper.reg))
-  Else
-    Begin
-      ReadOp(oper);
-      DestroyOp(oper);
-    End
-End;
-{$endif arithopt}
-
-Procedure TPaiProp.IncWState(Reg: TRegister);{$ifdef fpc} inline;{$endif fpc}
-Begin
-  IncState(Regs[Reg].WState);
-End;
-
-Procedure TPaiProp.IncRState(Reg: TRegister);{$ifdef fpc} inline;{$endif fpc}
-Begin
-  IncState(Regs[Reg].RState);
-End;
-
-Procedure TPaiProp.IncState(Var s: TStateInt); {$ifdef fpc} inline;{$endif fpc}
-Begin
-  If s <> $ff Then Inc(s)
-  Else s := 0
-End;
-
-Function TPaiProp.GetWState(Reg: TRegister): TStateInt;
-Begin
-  GetWState := Regs[Reg].WState
-End;
-
-Function TPaiProp.GetRState(Reg: TRegister): TStateInt;
-Begin
-  GetRState := Regs[Reg].RState
-End;
-
-Function TPaiProp.GetRegContentKind(Reg: TRegister): Byte;
-Begin
-  GetRegContentKind := Regs[Reg].typ
-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(AsmL: PAasmOutput; 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;
-            new_one^.fileinfo := foll^.fileinfo
-          End
-      End
-    Else AsmL^.Concat(new_one)
-  Else If Assigned(Foll) Then AsmL^.Insert(new_one)
-End;
-
-Function TAOptObj.RegInInstruction(Reg: TRegister; p1: Pai): Boolean;
-Var Count: TNatInt;
-    TmpResult: Boolean;
-Begin
-  TmpResult := False;
-  Count := 0;
-  If (p1^.typ = ait_instruction) Then
-    Repeat
-      TmpResult := RegInOp(Reg, PInstr(p1)^.oper[Count]);
-      Inc(Count)
-    Until (Count = MaxOps) or TmpResult;
-  RegInInstruction := TmpResult
-End;
-
-Function TAOptObj.RegInOp(Reg: TRegister; const op: toper): Boolean;
-Begin
-  Case op.typ Of
-    Top_Reg: RegInOp := Reg = op.reg;
-    Top_Ref: RegInOp := RegInRef(Reg, op.ref^)
-    Else RegInOp := False
-  End
-End;
-
-Function TAOptObj.RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
-Var hp: Pai;
-Begin
-  If GetLastInstruction(p1, hp)
-    Then
-      RegModifiedByInstruction :=
-        PPAiProp(p1^.OptInfo)^.Regs[Reg].WState <>
-          PPAiProp(hp^.OptInfo)^.Regs[Reg].WState
-    Else RegModifiedByInstruction := True;
-End;
-
-Function TAOptObj.GetNextInstruction(Current: Pai; Var Next: Pai): Boolean;
-Begin
-  Repeat
-    Current := Pai(Current^.Next);
-    While Assigned(Current) And
-          ((Current^.typ In SkipInstr) or
-           ((Current^.typ = ait_label) And
-            Not(Pai_Label(Current)^.l^.is_used))) Do
-      Current := Pai(Current^.Next);
-    If Assigned(Current) And
-       (Current^.typ = ait_Marker) And
-       (Pai_Marker(Current)^.Kind = NoPropInfoStart) Then
-      Begin
-        While Assigned(Current) And
-              ((Current^.typ <> ait_Marker) Or
-               (Pai_Marker(Current)^.Kind <> NoPropInfoEnd)) Do
-          Current := Pai(Current^.Next);
-      End;
-  Until Not(Assigned(Current)) Or
-        (Current^.typ <> ait_Marker) Or
-        (Pai_Marker(Current)^.Kind <> NoPropInfoEnd);
-  Next := Current;
-  If Assigned(Current) And
-     Not((Current^.typ In SkipInstr) or
-         ((Current^.typ = ait_label) And
-          Not(Pai_Label(Current)^.l^.is_used)))
-    Then GetNextInstruction := True
-    Else
-      Begin
-        Next := Nil;
-        GetNextInstruction := False;
-      End;
-End;
-
-Function TAOptObj.GetLastInstruction(Current: Pai; Var Last: Pai): Boolean;
-Begin
-  Repeat
-    Current := Pai(Current^.previous);
-    While Assigned(Current) And
-          (((Current^.typ = ait_Marker) And
-            Not(Pai_Marker(Current)^.Kind in [AsmBlockEnd,NoPropInfoEnd])) or
-           (Current^.typ In SkipInstr) or
-           ((Current^.typ = ait_label) And
-             Not(Pai_Label(Current)^.l^.is_used))) Do
-      Current := Pai(Current^.previous);
-    If Assigned(Current) And
-       (Current^.typ = ait_Marker) And
-       (Pai_Marker(Current)^.Kind = NoPropInfoEnd) Then
-      Begin
-        While Assigned(Current) And
-              ((Current^.typ <> ait_Marker) Or
-               (Pai_Marker(Current)^.Kind <> NoPropInfoStart)) Do
-          Current := Pai(Current^.previous);
-      End;
-  Until Not(Assigned(Current)) Or
-        (Current^.typ <> ait_Marker) Or
-        (Pai_Marker(Current)^.Kind <> NoPropInfoStart);
-  If Not(Assigned(Current)) or
-     (Current^.typ In SkipInstr) or
-     ((Current^.typ = ait_label) And
-      Not(Pai_Label(Current)^.l^.is_used)) or
-     ((Current^.typ = ait_Marker) And
-      (Pai_Marker(Current)^.Kind = AsmBlockEnd))
-    Then
-      Begin
-        Last := Nil;
-        GetLastInstruction := False
-      End
-    Else
-      Begin
-        Last := Current;
-        GetLastInstruction := True;
-      End;
-End;
-
-Procedure TAOptObj.SkipHead(var P: Pai);
-{ skips Pai objects at the start of a block that don't do anything }
-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
-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;
-
-Function TAOptObj.RefsEqual(Const R1, R2: TReference): Boolean;
-Begin
-  If R1.is_immediate Then
-    RefsEqual := R2.is_immediate and (R1.Offset = R2.Offset)
-  Else
-    RefsEqual := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup)
-                 And (R1.Base = R2.Base)
-{$ifdef RefsHaveindex}
-                 And (R1.Index = R2.Index)
-{$endif RefsHaveindex}
-{$ifdef RefsHaveScale}
-                 And (R1.ScaleFactor = R2.ScaleFactor)
-{$endif RefsHaveScale}
-                 And (R1.Symbol = R2.Symbol)
-{$ifdef RefsHaveSegment}
-                 And (R1.Segment = R2.Segment)
-{$endif RefsHaveSegment}
-                 ;
-
-Function TAOptObj.RegInRef(Reg: TRegister; Const Ref: TReference): Boolean;
-Begin
-  Reg := RegMaxSize(Reg);
-  RegInRef := (Ref.Base = Reg)
-{$ifdef RefsHaveIndexReg}
-  Or (Ref.Index = Reg)
-{$endif RefsHaveIndexReg}
-End;
-
-Function TAOptObj.RegModifiedByInstruction(Reg: TRegister; p1: Pai): Boolean;
-Var hp: Pai;
-Begin
-  If GetLastInstruction(p1, hp)
-    Then
-      RegModifiedByInstruction :=
-        PPAiProp(p1^.OptInfo)^.GetWState <>
-          PPAiProp(hp^.OptInfo)^.GetWState
-    Else RegModifiedByInstruction := True;
-End;
-
-Function TAOptObj.RefInInstruction(Const Ref: TReference; p: Pai): Boolean;
-Var Count: TNatInt;
-    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 TAOptObj.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;
-
-Function TAOptObj.RegMaxSize(Reg: TRegister): TRegister;
-Begin
-  RegMaxSize := Reg
-End;
-
-Function TAOptObj.RegsSameSize(Reg1, Reg2: TRegister): Boolean;
-Begin
-  RegsSameSize := True
-End;
-
-Function TAOptObj.IsLoadInstr(p: pai): Boolean;
-Begin
-  Abstract
-End;
-
-Function TAOptObj.RegReadByInstr(Reg: TRegister; p: Pai);
-Begin
-  Abstract
-End;
-
-Function TAOptObj.IsStoreInstr(p: pai): Boolean;
-Begin
-  Abstract
-End;
-
-Function TAOptObj.TCh2Reg(Ch: TChange): TRegister;
-Begin
-  Abstract
-End;
-
-End.
-
-{
- $Log$
- 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
-
-}