Browse Source

* if while we are restoring the contents of a register, we encounter an
operation which changes a register, clear the contents of all registers
which depend on this register

git-svn-id: trunk@3480 -

Jonas Maebe 19 years ago
parent
commit
a1b2701e5f
2 changed files with 53 additions and 16 deletions
  1. 52 16
      compiler/i386/csopt386.pas
  2. 1 0
      compiler/i386/daopt386.pas

+ 52 - 16
compiler/i386/csopt386.pas

@@ -842,6 +842,7 @@ var
 {$endif replaceregdebug}
     regcounter: tsuperregister;
     oldStartmod: tai;
+    regstoclear: tregset;
 begin
 {$ifdef replaceregdebug}
   l := random(1000);
@@ -850,26 +851,43 @@ begin
   insertllitem(asml,p.previous,p,hp);
 {$endif replaceregdebug}
   ptaiprop(p.optinfo)^.Regs[supreg].typ := con_unknown;
+  regstoclear := [supreg];
   while (p <> endP) do
     begin
       for regcounter := RS_EAX to RS_EDI do
-        if (regcounter <> supreg) and
-           assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
-           reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
-          clearmemwrites(p,regcounter);
-      with ptaiprop(p.optinfo)^.Regs[supreg] do
         begin
-          typ := con_unknown;
-          memwrite := nil;
+          if (regcounter <> supreg) and
+             assigned(ptaiprop(p.optinfo)^.regs[supreg].memwrite) and
+             reginref(regcounter,ptaiprop(p.optinfo)^.regs[supreg].memwrite.oper[1]^.ref^) then
+            clearmemwrites(p,regcounter);
+          { needs double loop to cheack for each dependency combination? }
+          if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
+             sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
+            include(regstoclear,regcounter);
+
+          if regcounter in regstoclear then
+            with ptaiprop(p.optinfo)^.Regs[regcounter] do
+              begin
+                typ := con_unknown;
+                memwrite := nil;
+              end;
         end;
       getNextInstruction(p,p);
     end;
   oldStartmod := ptaiprop(p.optinfo)^.Regs[supreg].startmod;
   repeat
-    with ptaiprop(p.optinfo)^.Regs[supreg] do
+    for regcounter := RS_EAX to RS_EDI do
       begin
-        typ := con_unknown;
-        memwrite := nil;
+        { needs double loop to cheack for each dependency combination? }
+        if assigned(ptaiprop(p.optinfo)^.regs[regcounter].startmod) and
+           sequencedependsonreg(ptaiprop(p.optinfo)^.regs[regcounter],regcounter,supreg) then
+          include(regstoclear,regcounter);
+        with ptaiprop(p.optinfo)^.Regs[supreg] do
+          if regcounter in regstoclear then
+            begin
+              typ := con_unknown;
+              memwrite := nil;
+            end;
       end;
   until not getNextInstruction(p,p) or
         (ptaiprop(p.optinfo)^.Regs[supreg].startmod <> oldStartmod);
@@ -889,7 +907,8 @@ var
   l: longint;
 {$endif replaceregdebug}
   hp: tai;
-  dummyregs: tregset;
+  validregs, prevvalidregs: tregset;
+  regcounter: tsuperregister;
   tmpState, newrstate: byte;
   prevcontenttyp: byte;
   memconflict: boolean;
@@ -906,6 +925,8 @@ begin
   incstate(newrstate,$7f);
   memconflict := false;
   invalsmemwrite := false;
+  validregs := [RS_EAX..RS_EDI];
+  prevvalidregs := validregs;
   while (p <> endP) and
         not(memconflict) and
         not(invalsmemwrite) do
@@ -914,8 +935,16 @@ begin
          regreadbyinstruction(supreg,p) then
         incstate(newrstate,1);
       // is this a write to memory that destroys the contents we are restoring?
-      memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,dummyregs,true,invalsmemwrite);
-      if not memconflict and not invalsmemwrite then
+      memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
+      if (validregs <> prevvalidregs) then
+        begin
+          prevvalidregs := validregs >< prevvalidregs;
+          for regcounter := RS_EAX to RS_EDI do
+            if regcounter in prevvalidregs then
+              clearRegContentsFrom(asml,regcounter,p,endP);
+        end;
+      prevvalidregs := validregs;
+      if (not memconflict and not invalsmemwrite) then
         begin
           ptaiprop(p.optinfo)^.Regs[supreg] := c;
           ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;
@@ -946,13 +975,20 @@ begin
       if (ptaiprop(hp.optinfo)^.regs[supreg].rstate = ptaiprop(p.optinfo)^.regs[supreg].rstate) then
         internalerror(2004122710);
      end;
-  dummyregs := [supreg];
   repeat
     newrstate := ptaiprop(p.optinfo)^.Regs[supreg].rState;
     prevcontenttyp := ptaiprop(p.optinfo)^.Regs[supreg].typ;
     // is this a write to memory that destroys the contents we are restoring?
-    memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,dummyregs,true,invalsmemwrite);
-    if not memconflict and not invalsmemwrite then
+    memconflict := modifiesConflictingMemLocation(p,supreg,ptaiprop(p.optinfo)^.regs,validregs,false,invalsmemwrite);
+    if (validregs <> prevvalidregs) then
+      begin
+        prevvalidregs := validregs >< prevvalidregs;
+        for regcounter := RS_EAX to RS_EDI do
+          if regcounter in prevvalidregs then
+            clearRegContentsFrom(asml,regcounter,p,p);
+      end;
+    prevvalidregs := validregs;
+    if (not memconflict and not invalsmemwrite) then
       begin
         ptaiprop(p.optinfo)^.Regs[supreg] := c;
         ptaiprop(p.optinfo)^.Regs[supreg].rstate := newrstate;

+ 1 - 0
compiler/i386/daopt386.pas

@@ -187,6 +187,7 @@ function writeToRegDestroysContents(destReg, supreg: tsuperregister;
 function writeDestroysContents(const op: toper; supreg: tsuperregister; size: tcgsize;
   const c: tcontent; var memwritedestroyed: boolean): boolean;
 
+function sequenceDependsonReg(const Content: TContent; seqreg: tsuperregister; supreg: tsuperregister): Boolean;
 
 function GetNextInstruction(Current: tai; var Next: tai): Boolean;
 function GetLastInstruction(Current: tai; var Last: tai): Boolean;