Browse Source

* fixed bug in arrayRefsEq
* object/class fields are now handled the same as local/global vars and
parameters (ie. a write to a local var can now never destroy a class
field)

Jonas Maebe 25 years ago
parent
commit
767ecef9bb
1 changed files with 71 additions and 16 deletions
  1. 71 16
      compiler/i386/daopt386.pas

+ 71 - 16
compiler/i386/daopt386.pas

@@ -728,7 +728,7 @@ Begin
                AddReg2RegInfo(OldReg, NewReg, RegInfo);
                RegsEquivalent := True
              End
-           Else RegsEquivalent := False 
+           Else RegsEquivalent := False
     Else RegsEquivalent := False
   Else RegsEquivalent := OldReg = NewReg
 End;
@@ -1593,10 +1593,65 @@ Begin
   ArrayRefsEq := (R1.Offset+R1.OffsetFixup = R2.Offset+R2.OffsetFixup) And
                  (R1.Segment = R2.Segment) And
                  (R1.Symbol=R2.Symbol) And
-                 ((Assigned(R1.Symbol)) Or
-                  (R1.Base = R2.Base))
+                 (R1.Base = R2.Base)
 End;
 
+function isSimpleRef(const ref: treference): boolean;
+{ returns true if ref is reference to a local or global variable, to a  }
+{ parameter or to an object field (this includes arrays). Returns false }
+{ otherwise.                                                            }
+begin
+  isSimpleRef :=
+    assigned(ref.symbol) or
+    (ref.base = procinfo^.framepointer) or
+    (assigned(procinfo^._class) and
+     (ref.base = R_ESI));
+end;
+
+function containsPointerRef(p: pai): boolean;
+{ checks if an instruction contains a reference which is a pointer location }
+var
+  hp: paicpu;
+  count: longint;
+begin
+  containsPointerRef := false;
+  if p^.typ <> ait_instruction then
+    exit;
+  hp := paicpu(p);
+  for count := 0 to high(hp^.ops) do
+    begin
+      case hp^.oper[count].typ of
+        top_ref:
+          if not isSimpleRef(hp^.oper[count].ref^) then
+            begin
+              containsPointerRef := true;
+              exit;
+            end;
+        top_none:
+          exit;
+      end;
+    end;
+end;
+
+
+function containsPointerLoad(c: tcontent): boolean;
+{ checks whether the contents of a register contain a pointer reference }
+var
+  p: pai;
+  count: longint;
+begin
+  containsPointerLoad := false;
+  p := c.startmod;
+  for count := c.nrOfMods downto 1 do
+    begin
+      if containsPointerRef(p) then
+        begin
+          containsPointerLoad := true;
+          exit;
+        end;
+      getnextinstruction(p,p);
+    end;
+end;
 
 function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
   reg: tregister; const c: tcontent): boolean;
@@ -1612,8 +1667,7 @@ begin
     end;
   reg := reg32(reg);
   regWritten := reg32(regWritten);
-  if (ref.base = procinfo^.framePointer) or
-      assigned(ref.symbol) Then
+  if isSimpleRef(ref) then
     begin
       if (ref.index <> R_NO) or
          (assigned(ref.symbol) and
@@ -1630,14 +1684,14 @@ begin
      {      "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)                                              }
+     {      expression based on Ref)                                           }
      {  * with uncertain optimizations off:                                    }
      {    - also destroy registers that contain any pointer                    }
       with c do
         writeToMemDestroysContents :=
           (typ in [con_ref,con_noRemoveRef]) and
           ((not(cs_uncertainOpts in aktglobalswitches) and
-            (nrOfMods <> 1)
+            containsPointerLoad(c)
            ) or
            (refInSequence(ref,c,refsEq) and
             ((reg <> regWritten) or
@@ -1662,15 +1716,10 @@ begin
         (typ in [con_ref,con_noRemoveRef]) and
         (not(cs_UncertainOpts in aktglobalswitches) or
        { for movsl }
-        ((ref.base = R_EDI) and (ref.index = R_EDI)) or
+         ((ref.base = R_EDI) and (ref.index = 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)
-            )
-           )
-       )
+         containsPointerLoad(c)
+        )
 end;
 
 function writeToRegDestroysContents(destReg: tregister; reg: tregister;
@@ -2387,7 +2436,13 @@ End.
 
 {
   $Log$
-  Revision 1.3  2000-10-24 10:40:53  jonas
+  Revision 1.4  2000-11-03 18:06:26  jonas
+    * fixed bug in arrayRefsEq
+    * object/class fields are now handled the same as local/global vars and
+      parameters (ie. a write to a local var can now never destroy a class
+      field)
+
+  Revision 1.3  2000/10/24 10:40:53  jonas
     + register renaming ("fixes" bug1088)
     * changed command line options meanings for optimizer:
         O2 now means peepholopts, CSE and register renaming in 1 pass