Преглед на файлове

* small fix for uncertain optimizations & more cleaning up

Jonas Maebe преди 27 години
родител
ревизия
fccf4109e0
променени са 2 файла, в които са добавени 206 реда и са изтрити 130 реда
  1. 19 87
      compiler/csopt386.pas
  2. 187 43
      compiler/daopt386.pas

+ 19 - 87
compiler/csopt386.pas

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

+ 187 - 43
compiler/daopt386.pas

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