Browse Source

* writing to a position in an array now only destroys registers
containing a reference pointing somewhere in that array (since my last
fix, it behaved like a write to a pointer location)

Jonas Maebe 26 years ago
parent
commit
e62d58ea51
1 changed files with 93 additions and 56 deletions
  1. 93 56
      compiler/daopt386.pas

+ 93 - 56
compiler/daopt386.pas

@@ -240,6 +240,8 @@ Implementation
 Uses
   globals, systems, strings, verbose, hcodegen;
 
+Type TRefCompare = function(const r1, r2: TReference): Boolean;
+
 Const AsmInstr: Array[tasmop] Of TAsmInstrucProp = (
   {A_<NONE>} (Ch: (C_All, C_None, C_None)), { new }
   {A_LOCK} (Ch: (C_None, C_None, C_None)),
@@ -1584,7 +1586,34 @@ Begin {checks whether two Paicpu instructions are equal}
 End;
 *)
 
-Function RefInInstruction(Const Ref: TReference; p: Pai): Boolean;
+Procedure ReadReg(p: PPaiProp; Reg: TRegister);
+Begin
+  Reg := Reg32(Reg);
+  If Reg in [R_EAX..R_EDI] Then
+    IncState(p^.Regs[Reg].RState)
+End;
+
+
+Procedure ReadRef(p: PPaiProp; Ref: PReference);
+Begin
+  If Ref^.Base <> R_NO Then
+    ReadReg(p, Ref^.Base);
+  If Ref^.Index <> R_NO Then
+    ReadReg(p, Ref^.Index);
+End;
+
+Procedure ReadOp(P: PPaiProp;const o:toper);
+Begin
+  Case o.typ Of
+    top_reg: ReadReg(P, o.reg);
+    top_ref: ReadRef(P, o.ref);
+    top_symbol : ;
+  End;
+End;
+
+
+Function RefInInstruction(Const Ref: TReference; p: Pai;
+           RefsEq: TRefCompare): Boolean;
 {checks whehter Ref is used in P}
 Var TmpResult: Boolean;
 Begin
@@ -1592,14 +1621,17 @@ Begin
   If (p^.typ = ait_instruction) Then
     Begin
       If (Paicpu(p)^.oper[0].typ = Top_Ref) Then
-        TmpResult := RefsEqual(Ref, Paicpu(p)^.oper[0].ref^);
+        TmpResult := RefsEq(Ref, Paicpu(p)^.oper[0].ref^);
       If Not(TmpResult) And (Paicpu(p)^.oper[1].typ = Top_Ref) Then
-        TmpResult := RefsEqual(Ref, Paicpu(p)^.oper[1].ref^);
+        TmpResult := RefsEq(Ref, Paicpu(p)^.oper[1].ref^);
+      If Not(TmpResult) And (Paicpu(p)^.oper[2].typ = Top_Ref) Then
+        TmpResult := RefsEq(Ref, Paicpu(p)^.oper[2].ref^);
     End;
   RefInInstruction := TmpResult;
 End;
 
-Function RefInSequence(Const Ref: TReference; Content: TContent): Boolean;
+Function RefInSequence(Const Ref: TReference; Content: TContent;
+           RefsEq: TRefCompare): 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;
@@ -1613,7 +1645,7 @@ Begin
         (Counter <= Content.NrOfMods) Do
     Begin
       If (p^.typ = ait_instruction) And
-         RefInInstruction(Ref, p)
+         RefInInstruction(Ref, p, RefsEq)
         Then TmpResult := True;
       Inc(Counter);
       GetNextInstruction(p,p)
@@ -1621,18 +1653,34 @@ Begin
   RefInSequence := TmpResult
 End;
 
+Function 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 DestroyRefs(p: pai; 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;
+Var RefsEq: TRefCompare;
+    Counter: TRegister;
 Begin
   WhichReg := Reg32(WhichReg);
-  If (Ref.Index = R_NO) And
-     ((Ref.base = procinfo^.FramePointer) Or
-      (Assigned(Ref.Symbol) And
-       (Ref.base = R_NO)))
-    Then
+  If (Ref.base = procinfo^.FramePointer) or
+      Assigned(Ref.Symbol) Then
+    Begin
+      If (Ref.Index = R_NO) And
+         (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
@@ -1649,12 +1697,12 @@ Begin
                ((Not(cs_UncertainOpts in aktglobalswitches) And
                  (NrOfMods <> 1)
                 ) Or
-                (RefInSequence(Ref,PPaiProp(p^.OptInfo)^.Regs[Counter]) And
+                (RefInSequence(Ref,PPaiProp(p^.OptInfo)^.Regs[Counter],RefsEq) And
                  ((Counter <> WhichReg) Or
                   ((NrOfMods <> 1) And
  {StarMod is always of the type ait_instruction}
                    (Paicpu(StartMod)^.oper[0].typ = top_ref) And
-                   RefsEqual(Paicpu(StartMod)^.oper[0].ref^, Ref)
+                   RefsEq(Paicpu(StartMod)^.oper[0].ref^, Ref)
                   )
                  )
                 )
@@ -1662,7 +1710,8 @@ Begin
               Then
                 DestroyReg(PPaiProp(p^.OptInfo), Counter)
           End
-    Else
+    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
@@ -1670,28 +1719,31 @@ Begin
    * with uncertain optimzations off:
       - destroy every register which contains a memory location
       }
-      For Counter := R_EAX to R_EDI Do
-        With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
-        If (typ = Con_Ref) And
-           (Not(cs_UncertainOpts in aktglobalswitches) Or
-        {for movsl}
-            (Ref.Base = R_EDI) Or
-        {don't destroy if reg contains a parameter, local or global variable}
-            Not((NrOfMods = 1) And
-                (Paicpu(StartMod)^.oper[0].typ = top_ref) And
-                ((Paicpu(StartMod)^.oper[0].ref^.base = procinfo^.FramePointer) Or
-                  Assigned(Paicpu(StartMod)^.oper[0].ref^.Symbol)
-                )
-               )
-           )
-          Then DestroyReg(PPaiProp(p^.OptInfo), Counter)
+    For Counter := R_EAX to R_EDI Do
+      With PPaiProp(p^.OptInfo)^.Regs[Counter] Do
+      If (typ = Con_Ref) And
+         (Not(cs_UncertainOpts in aktglobalswitches) Or
+      {for movsl}
+          (Ref.Base = R_EDI) Or
+      {don't destroy if reg contains a parameter, local or global variable}
+          Not((NrOfMods = 1) And
+              (Paicpu(StartMod)^.oper[0].typ = top_ref) And
+              ((Paicpu(StartMod)^.oper[0].ref^.base = procinfo^.FramePointer) Or
+                Assigned(Paicpu(StartMod)^.oper[0].ref^.Symbol)
+              )
+             )
+         )
+        Then DestroyReg(PPaiProp(p^.OptInfo), Counter)
 End;
 
 Procedure DestroyAllRegs(p: PPaiProp);
 Var Counter: TRegister;
 Begin {initializes/desrtoys all registers}
   For Counter := R_EAX To R_EDI Do
-    DestroyReg(p, Counter);
+    Begin
+      ReadReg(p, Counter);
+      DestroyReg(p, Counter);
+    End;
   p^.DirFlag := F_Unknown;
 End;
 
@@ -1699,35 +1751,15 @@ Procedure DestroyOp(PaiObj: Pai; const o:Toper);
 Begin
   Case o.typ Of
     top_reg: DestroyReg(PPaiProp(PaiObj^.OptInfo), o.reg);
-    top_ref: DestroyRefs(PaiObj, o.ref^, R_NO);
+    top_ref:
+      Begin
+        ReadRef(PPaiProp(PaiObj^.OptInfo), o.ref);
+        DestroyRefs(PaiObj, o.ref^, R_NO);
+      End;
     top_symbol:;
   End;
 End;
 
-Procedure ReadReg(p: PPaiProp; Reg: TRegister);
-Begin
-  Reg := Reg32(Reg);
-  If Reg in [R_EAX..R_EDI] Then
-    IncState(p^.Regs[Reg32(Reg)].RState)
-End;
-
-Procedure ReadRef(p: PPaiProp; Ref: PReference);
-Begin
-  If Ref^.Base <> R_NO Then
-    ReadReg(p, Ref^.Base);
-  If Ref^.Index <> R_NO Then
-    ReadReg(p, Ref^.Index);
-End;
-
-Procedure ReadOp(P: PPaiProp;const o:toper);
-Begin
-  Case o.typ Of
-    top_reg: ReadReg(P, o.reg);
-    top_ref: ReadRef(P, o.ref);
-    top_symbol : ;
-  End;
-End;
-
 Function DFAPass1(AsmL: PAasmOutput; BlockStart: Pai): Pai;
 {gathers the RegAlloc data... still need to think about where to store it to
  avoid global vars}
@@ -2351,7 +2383,12 @@ End.
 
 {
  $Log$
- Revision 1.60  1999-09-27 23:44:50  peter
+ Revision 1.61  1999-09-29 13:49:53  jonas
+   * writing to a position in an array now only destroys registers
+     containing a reference pointing somewhere in that array (since my last
+     fix, it behaved like a write to a pointer location)
+
+ Revision 1.60  1999/09/27 23:44:50  peter
    * procinfo is now a pointer
    * support for result setting in sub procedure