فهرست منبع

+ replace mem accesses to locations to which a reg was stored recently with that reg

Jonas Maebe 24 سال پیش
والد
کامیت
e02d95ed13
2فایلهای تغییر یافته به همراه177 افزوده شده و 83 حذف شده
  1. 105 53
      compiler/i386/csopt386.pas
  2. 72 30
      compiler/i386/daopt386.pas

+ 105 - 53
compiler/i386/csopt386.pas

@@ -70,6 +70,7 @@ var
   tmpRef: treference;
   regCounter: tregister;
   opCount: byte;
+  dummy: boolean;
 begin
   modifiesConflictingMemLocation := false;
   if p1.typ <> ait_instruction then
@@ -81,7 +82,7 @@ begin
         for regCounter := R_EAX to R_EDI do
           begin
             if writeToMemDestroysContents(reg32(p.oper[0].reg),p.oper[1].ref^,
-                 regCounter,c[regCounter]) then
+                 regCounter,c[regCounter],dummy) then
               begin
                 exclude(regsStillValid,regCounter);
                 modifiesConflictingMemLocation := not(reg in regsStillValid);
@@ -170,7 +171,7 @@ begin
               tmpRef.base := R_EDI;
               tmpRef.index := R_EDI;
               for regCounter := R_EAX to R_EDI do
-                if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter]) then
+                if writeToMemDestroysContents(R_NO,tmpRef,regCounter,c[regCounter],dummy) then
                   begin
                     exclude(regsStillValid,regCounter);
                     modifiesConflictingMemLocation := not(reg in regsStillValid);
@@ -720,6 +721,16 @@ begin
 {$endif replaceregdebug}
 end;
 
+procedure clearmemwrites(p: tai; reg: tregister);
+var
+  beginmemwrite: tai;
+begin
+  beginmemwrite := pTaiprop(p.optinfo)^.regs[reg].memwrite;
+  repeat
+    pTaiprop(p.optinfo)^.regs[reg].memwrite := nil;
+  until not getnextinstruction(p,p) or
+        (pTaiprop(p.optinfo)^.regs[reg].memwrite <> beginmemwrite);
+end;
 
 Procedure ClearRegContentsFrom(reg: TRegister; p, endP: Tai);
 { first clears the contents of reg from p till endP. Then the contents are }
@@ -729,6 +740,7 @@ var
     hp: Tai;
     l: longint;
 {$endif replaceregdebug}
+    regcounter: tregister;
     oldStartmod: Tai;
 begin
 {$ifdef replaceregdebug}
@@ -744,12 +756,25 @@ begin
   PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown;
   While (p <> endP) Do
     Begin
-      PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown;
+      for regcounter := R_EAX to R_EDI do
+        if (regcounter <> reg) and
+           assigned(pTaiprop(p.optinfo)^.regs[reg].memwrite) and
+           reginref(regcounter,pTaiprop(p.optinfo)^.regs[reg].memwrite.oper[1].ref^) then
+          clearmemwrites(p,regcounter);
+      with PTaiProp(p.optInfo)^.Regs[reg] do
+        begin
+          typ := con_unknown;
+          memwrite := nil;
+        end;
       getNextInstruction(p,p);
     end;
   oldStartmod := PTaiProp(p.optInfo)^.Regs[reg].startmod;
   repeat
-    PTaiProp(p.optInfo)^.Regs[reg].typ := con_unknown;
+    with PTaiProp(p.optInfo)^.Regs[reg] do
+      begin
+        typ := con_unknown;
+        memwrite := nil;
+      end;
   until not getNextInstruction(p,p) or
         (PTaiProp(p.optInfo)^.Regs[reg].startmod <> oldStartmod);
 {$ifdef replaceregdebug}
@@ -1311,45 +1336,57 @@ begin
      (p.opcode = A_IDIV));
 end;
 
-function memtoreg(const t: Taicpu; const ref: treference): tregister;
+function memtoreg(const t: Taicpu; const ref: treference; var startp: tai): tregister;
 var
   hp: tai;
   p: pTaiprop;
   regcounter: tregister;
+  optimizable: boolean;
 begin
-  if not getlastinstruction(t,hp) then
+  if not getlastinstruction(t,hp) or
+     not issimplememloc(ref) then
     begin
       memtoreg := R_NO;
       exit;
     end;
   p := pTaiprop(hp.optinfo);
-  if isSimpleMemLoc(ref) then
+  optimizable := false;
+  for regcounter := R_EAX to R_EDI do
     begin
-      for regcounter := R_EAX to R_EDI do
-        if (p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
-           (p^.regs[regcounter].nrofmods = 1) and
-           ((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
-            (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
-            (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
-           (taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and
-           refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^) then
-          begin
-            if ((t.opsize <> S_B) or
-                (regcounter <> R_EDI)) and
-               sizescompatible(Taicpu(p^.regs[regcounter].startmod).opsize,t.opsize) then
-              begin
-                case t.opsize of
-                  S_B,S_BW,S_BL:
-                    memtoreg := reg32toreg8(regcounter);
-                  S_W,S_WL:
-                    memtoreg := reg32toreg16(regcounter);
-                  S_L:
-                    memtoreg := regcounter;
-                end;
-                exit;
+      if (assigned(p^.regs[regcounter].memwrite) and
+         refsequal(ref,p^.regs[regcounter].memwrite.oper[1].ref^)) then
+        begin
+          optimizable := true;
+          hp := p^.regs[regcounter].memwrite;
+        end
+      else if ((p^.regs[regcounter].typ in [CON_REF,CON_NOREMOVEREF]) and
+             (p^.regs[regcounter].nrofmods = 1) and
+             ((Taicpu(p^.regs[regcounter].startmod).opcode = A_MOV) or
+              (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVZX) or
+              (Taicpu(p^.regs[regcounter].startmod).opcode = A_MOVSX)) and
+             (taicpu(p^.regs[regcounter].startmod).oper[0].typ = top_ref) and
+             refsequal(ref,taicpu(p^.regs[regcounter].startmod).oper[0].ref^)) then
+        begin
+          optimizable := true;
+          hp := p^.regs[regcounter].startmod;
+        end;
+      if optimizable then
+          if ((t.opsize <> S_B) or
+              (regcounter <> R_EDI)) and
+             sizescompatible(Taicpu(hp).opsize,t.opsize) then
+            begin
+              case t.opsize of
+                S_B,S_BW,S_BL:
+                  memtoreg := reg32toreg8(regcounter);
+                S_W,S_WL:
+                  memtoreg := reg32toreg16(regcounter);
+                S_L:
+                  memtoreg := regcounter;
               end;
-          end;
-    end;
+              startp := hp;
+              exit;
+            end;
+        end;
   memtoreg := R_NO;
 end;
 
@@ -1643,14 +1680,20 @@ Begin
                               begin
                                 regcounter :=
                                   memtoreg(taicpu(p),
-                                  Taicpu(p).oper[0].ref^);
+                                  Taicpu(p).oper[0].ref^,hp5);
                                 if regcounter <> R_NO then
-                                  begin
-                                    Taicpu(p).loadreg(0,regcounter);
-                                    allocregbetween(asml,reg32(regcounter),
-                                      pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
-                                      p);
-                                  end;
+                                  if (taicpu(p).opcode = A_MOV) and
+                                     (taicpu(p).oper[1].typ = top_reg) and
+                                     (taicpu(p).oper[1].reg = regcounter) then
+                                    pTaiProp(p.optinfo)^.canberemoved := true
+                                  else
+                                    begin
+                                      Taicpu(p).loadreg(0,regcounter);
+                                      regcounter := reg32(regcounter);
+                                      allocregbetween(asml,regcounter,hp5,p);
+                                      incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+                                      updatestate(regcounter,p);
+                                    end;
                               end;
                           end;
                         { at first, only try optimizations of large blocks, because doing }
@@ -1715,13 +1758,14 @@ Begin
                             begin
                               regcounter :=
                                 memtoreg(taicpu(p),
-                                Taicpu(p).oper[0].ref^);
+                                Taicpu(p).oper[0].ref^,hp5);
                               if regcounter <> R_NO then
                                 begin
                                   Taicpu(p).loadreg(0,regcounter);
-                                  allocregbetween(asml,reg32(regcounter),
-                                    pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
-                                    p);
+                                  regcounter := reg32(regcounter);
+                                  allocregbetween(asml,regcounter,hp5,p);
+                                  incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+                                  updatestate(regcounter,p);
                                 end;
                             end;
                         Ch_MOp1:
@@ -1730,7 +1774,7 @@ Begin
                             begin
                               regcounter :=
                                 memtoreg(taicpu(p),
-                                Taicpu(p).oper[0].ref^);
+                                Taicpu(p).oper[0].ref^,hp5);
                               if (regcounter <> R_NO) (* and
                                  (not getNextInstruction(p,hp1) or
                                   (RegLoadedWithNewValue(reg32(regcounter),false,hp1) or
@@ -1744,11 +1788,13 @@ Begin
                                   new(pTaiprop(hp1.optinfo));
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   insertllitem(asml,p,p.next,hp1);
+                                  incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1);
+                                  updatestate(reg32(regcounter),hp1);
                                   hp1 := Tai_Marker.Create(NoPropInfoStart);
                                   insertllitem(asml,p,p.next,hp1);
                                   Taicpu(p).loadreg(0,regcounter);
-                                  allocregbetween(asml,reg32(regcounter),
-                                    pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
+                                  regcounter := reg32(regcounter);
+                                  allocregbetween(asml,regcounter,hp5,
                                     tai(p.next.next));
                                 end;
                             end;
@@ -1759,13 +1805,14 @@ Begin
                             begin
                               regcounter :=
                                 memtoreg(taicpu(p),
-                                Taicpu(p).oper[1].ref^);
+                                Taicpu(p).oper[1].ref^,hp5);
                               if regcounter <> R_NO then
                                 begin
                                   Taicpu(p).loadreg(1,regcounter);
-                                  allocregbetween(asml,reg32(regcounter),
-                                    pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
-                                    p);
+                                  regcounter := reg32(regcounter);
+                                  allocregbetween(asml,regcounter,hp5,p);
+                                  incstate(pTaiProp(p.optinfo)^.regs[regcounter].rstate,1);
+                                  updatestate(regcounter,p);
                                 end;
                             end;
                         Ch_MOp2:
@@ -1780,7 +1827,7 @@ Begin
                             begin
                               regcounter :=
                                 memtoreg(taicpu(p),
-                                Taicpu(p).oper[1].ref^);
+                                Taicpu(p).oper[1].ref^,hp5);
                               if (regcounter <> R_NO) (* and
                                  (not getNextInstruction(p,hp1) or
                                   (RegLoadedWithNewValue(reg32(regcounter),false,hp1) or
@@ -1794,11 +1841,13 @@ Begin
                                   new(pTaiprop(hp1.optinfo));
                                   pTaiProp(hp1.optinfo)^ := pTaiProp(p.optinfo)^;
                                   insertllitem(asml,p,p.next,hp1);
+                                  incstate(pTaiProp(hp1.optinfo)^.regs[reg32(regcounter)].rstate,1);
+                                  updatestate(reg32(regcounter),hp1);
                                   hp1 := Tai_Marker.Create(NoPropInfoStart);
                                   insertllitem(asml,p,p.next,hp1);
                                   Taicpu(p).loadreg(1,regcounter);
-                                  allocregbetween(asml,reg32(regcounter),
-                                    pTaiprop(p.optinfo)^.regs[reg32(regcounter)].startmod,
+                                  regcounter := reg32(regcounter);
+                                  allocregbetween(asml,regcounter,hp5,
                                     tai(p.next.next));
                                 end;
                             end;
@@ -1904,7 +1953,10 @@ End.
 
 {
   $Log$
-  Revision 1.20  2001-10-14 11:50:21  jonas
+  Revision 1.21  2001-10-27 10:20:43  jonas
+    + replace mem accesses to locations to which a reg was stored recently with that reg
+
+  Revision 1.20  2001/10/14 11:50:21  jonas
     + also replace mem references in modify operands with regs
 
   Revision 1.19  2001/10/12 13:58:05  jonas

+ 72 - 30
compiler/i386/daopt386.pas

@@ -73,6 +73,7 @@ type
       {start and end of block instructions that defines the
        content of this register.}
                StartMod: Tai;
+               MemWrite: Taicpu;
       {how many instructions starting with StarMod does the block consist of}
                NrOfMods: Byte;
       {the type of the content of the register: unknown, memory, constant}
@@ -170,7 +171,7 @@ function instrWritesFlags(p: Tai): boolean;
 function instrReadsFlags(p: Tai): boolean;
 
 function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
-  reg: tregister; const c: tcontent): boolean;
+  reg: tregister; const c: tcontent; var invalsmemwrite: boolean): boolean;
 function writeToRegDestroysContents(destReg: tregister; reg: tregister;
   const c: tcontent): boolean;
 function writeDestroysContents(const op: toper; reg: tregister;
@@ -1328,12 +1329,17 @@ begin
   for counter := R_EAX to R_EDI Do
     if counter <> reg then
       with p1^.regs[counter] Do
-        if (typ in [con_ref,con_noRemoveRef]) and
-           sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then
-          if typ in [con_ref,con_invalid] then
-            typ := con_invalid
-          { con_invalid and con_noRemoveRef = con_unknown }
-          else typ := con_unknown;
+        begin
+          if (typ in [con_ref,con_noRemoveRef]) and
+             sequenceDependsOnReg(p1^.Regs[counter],counter,reg) then
+            if typ in [con_ref,con_invalid] then
+              typ := con_invalid
+            { con_invalid and con_noRemoveRef = con_unknown }
+            else typ := con_unknown;
+          if assigned(memwrite) and
+             regInRef(counter,memwrite.oper[1].ref^) then
+            memwrite := nil;
+        end;
 end;
 
 Procedure DestroyReg(p1: PTaiProp; Reg: TRegister; doIncState:Boolean);
@@ -1364,6 +1370,7 @@ Begin
               typ := con_invalid
             { con_invalid and con_noRemoveRef = con_unknown }
             else typ := con_unknown;
+          memwrite := nil;
         end;
       invalidateDependingRegs(p1,reg);
     end;
@@ -1737,17 +1744,12 @@ begin
 end;
 
 function writeToMemDestroysContents(regWritten: tregister; const ref: treference;
-  reg: tregister; const c: tcontent): boolean;
+  reg: tregister; const c: tcontent; var invalsmemwrite: boolean): boolean;
 { returns whether the contents c of reg are invalid after regWritten is }
 { is written to ref                                                     }
 var
   refsEq: trefCompare;
 begin
-  if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
-    begin
-      writeToMemDestroysContents := false;
-      exit;
-    end;
   reg := reg32(reg);
   regWritten := reg32(regWritten);
   if isSimpleRef(ref) then
@@ -1760,6 +1762,16 @@ begin
       else
         { local/global variable or parameter which is not an array }
         refsEq := {$ifdef fpc}@{$endif}refsEqual;
+      invalsmemwrite :=
+        assigned(c.memwrite) and
+        ((not(cs_uncertainOpts in aktglobalswitches) and
+          containsPointerRef(c.memwrite)) or
+         refsEq(c.memwrite.oper[1].ref^,ref));
+      if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
+        begin
+          writeToMemDestroysContents := false;
+          exit;
+        end;
 
      { write something to a parameter, a local or global variable, so          }
      {  * with uncertain optimizations on:                                     }
@@ -1785,7 +1797,7 @@ begin
                 )
             )
            )
-          )
+          );
     end
   else
     { write something to a pointer location, so                               }
@@ -1794,15 +1806,26 @@ begin
     {       a parameter, except if DestroyRefs is called because of a "movsl" }
     {   * with uncertain optimzations off:                                    }
     {     - destroy every register which contains a memory location           }
-    with c do
-      writeToMemDestroysContents :=
-        (typ in [con_ref,con_noRemoveRef]) and
+    begin
+      invalsmemwrite :=
+        assigned(c.memwrite) and
         (not(cs_UncertainOpts in aktglobalswitches) or
-       { for movsl }
-         ((ref.base = R_EDI) and (ref.index = R_EDI)) or
-       { don't destroy if reg contains a parameter, local or global variable }
-         containsPointerLoad(c)
-        )
+         containsPointerRef(c.memwrite));
+      if not(c.typ in [con_ref,con_noRemoveRef,con_invalid]) then
+        begin
+          writeToMemDestroysContents := false;
+          exit;
+        end;
+      with c do
+        writeToMemDestroysContents :=
+          (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
+         { don't destroy if reg contains a parameter, local or global variable }
+           containsPointerLoad(c)
+          );
+    end;
 end;
 
 function writeToRegDestroysContents(destReg: tregister; reg: tregister;
@@ -1819,6 +1842,8 @@ function writeDestroysContents(const op: toper; reg: tregister;
   const c: tcontent): boolean;
 { returns whether the contents c of reg are invalid after regWritten is }
 { is written to op                                                      }
+var
+  dummy: boolean;
 begin
   reg := reg32(reg);
   case op.typ of
@@ -1827,7 +1852,7 @@ begin
         writeToRegDestroysContents(op.reg,reg,c);
     top_ref:
       writeDestroysContents :=
-        writeToMemDestroysContents(R_NO,op.ref^,reg,c);
+        writeToMemDestroysContents(R_NO,op.ref^,reg,c,dummy);
   else
     writeDestroysContents := false;
   end;
@@ -1839,11 +1864,16 @@ procedure destroyRefs(p: Tai; const ref: treference; regWritten: tregister);
 { is called because of a "mov?? %reg, (mem)" instruction)                      }
 var
   counter: TRegister;
+  destroymemwrite: boolean;
 begin
   for counter := R_EAX to R_EDI Do
-    if writeToMemDestroysContents(regWritten,ref,counter,
-         pTaiProp(p.optInfo)^.regs[counter]) then
-      destroyReg(pTaiProp(p.optInfo), counter, false)
+    begin
+      if writeToMemDestroysContents(regWritten,ref,counter,
+           pTaiProp(p.optInfo)^.regs[counter],destroymemwrite) then
+        destroyReg(pTaiProp(p.optInfo), counter, false)
+      else if destroymemwrite then
+        pTaiProp(p.optinfo)^.regs[counter].MemWrite := nil;
+    end;
 End;
 
 Procedure DestroyAllRegs(p: PTaiProp);
@@ -1853,6 +1883,7 @@ Begin {initializes/desrtoys all registers}
     Begin
       ReadReg(p, Counter);
       DestroyReg(p, Counter, true);
+      p^.regs[counter].MemWrite := nil;
     End;
   p^.DirFlag := F_Unknown;
 End;
@@ -1914,6 +1945,7 @@ Begin
           PTaiProp(Tai(StartMod).OptInfo)^.Regs[Reg].NrOfMods := NrOfMods;
           NrOfInstrSinceLastMod[Reg] := 0;
           invalidateDependingRegs(p.optinfo,reg);
+          pTaiprop(p.optinfo)^.regs[reg].memwrite := nil;
 {$ifdef StateDebug}
           hp := Tai_asm_comment.Create(strpnew(att_reg2str[reg]+': '+tostr(PTaiProp(p.optinfo)^.Regs[reg].WState)
                 + ' -- ' + tostr(PTaiProp(p.optinfo)^.Regs[reg].nrofmods))));
@@ -2237,6 +2269,7 @@ Begin
                                    { that depended on the previous value of }
                                    { this register                          }
                                     invalidateDependingRegs(curprop,tmpreg);
+                                    curprop^.regs[tmpreg].memwrite := nil;
                                 end;
                             end
                           else
@@ -2260,11 +2293,17 @@ Begin
 {$endif StateDebug}
                           End;
                         Top_Ref:
-                          { can only be if oper[0] = top_reg }
                           Begin
-                            ReadReg(CurProp, Taicpu(p).oper[0].reg);
                             ReadRef(CurProp, Taicpu(p).oper[1].ref);
-                            DestroyRefs(p, Taicpu(p).oper[1].ref^, Taicpu(p).oper[0].reg);
+                            if taicpu(p).oper[0].typ = top_reg then
+                              begin
+                                ReadReg(CurProp, Taicpu(p).oper[0].reg);
+                                DestroyRefs(p, Taicpu(p).oper[1].ref^, Taicpu(p).oper[0].reg);
+                                pTaiProp(p.optinfo)^.regs[reg32(Taicpu(p).oper[0].reg)].memwrite :=
+                                  Taicpu(p);
+                              end
+                            else
+                              DestroyRefs(p, Taicpu(p).oper[1].ref^, R_NO);
                           End;
                       End;
                     top_symbol,Top_Const:
@@ -2552,7 +2591,10 @@ End.
 
 {
   $Log$
-  Revision 1.22  2001-10-12 13:58:05  jonas
+  Revision 1.23  2001-10-27 10:20:43  jonas
+    + replace mem accesses to locations to which a reg was stored recently with that reg
+
+  Revision 1.22  2001/10/12 13:58:05  jonas
     + memory references are now replaced by register reads in "regular"
       instructions (e.g. "addl ref1,%eax" will be replaced by "addl %ebx,%eax"
       if %ebx contains ref1). Previously only complete load sequences were