Bladeren bron

* optimized register allocation for tempnodes

git-svn-id: trunk@2221 -
Jonas Maebe 19 jaren geleden
bovenliggende
commit
e4451558c4
3 gewijzigde bestanden met toevoegingen van 84 en 40 verwijderingen
  1. 3 2
      compiler/nbas.pas
  2. 40 18
      compiler/ncgbas.pas
  3. 41 20
      compiler/ncgutil.pas

+ 3 - 2
compiler/nbas.pas

@@ -133,6 +133,8 @@ interface
 
         { a node which is a reference to a certain temp }
         ttemprefnode = class(tnode)
+          tempinfo: ptempinfo;
+
           constructor create(const temp: ttempcreatenode); virtual;
           constructor create_offset(const temp: ttempcreatenode;aoffset:longint);
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
@@ -145,9 +147,8 @@ interface
           function docompare(p: tnode): boolean; override;
           procedure printnodedata(var t:text);override;
          protected
-          tempinfo: ptempinfo;
           offset : longint;
-        private
+         private
           tempidx : longint;
         end;
        ttemprefnodeclass = class of ttemprefnode;

+ 40 - 18
compiler/ncgbas.pas

@@ -66,7 +66,7 @@ interface
   implementation
 
     uses
-      globtype,systems,
+      globtype,globals,systems,
       cutils,verbose,
       aasmbase,aasmtai,aasmcpu,symsym,symconst,
       defutil,
@@ -430,8 +430,15 @@ interface
         if not tempinfo^.valid then
           internalerror(200108231);
         location:=tempinfo^.location;
-        if tempinfo^.location.loc=LOC_REFERENCE then
-          inc(location.reference.offset,offset);
+        case tempinfo^.location.loc of
+          LOC_REFERENCE:
+            begin
+              inc(location.reference.offset,offset);
+              { tempinfo^.valid should be set to false it it's a normal temp }
+            end;
+          LOC_REGISTER,LOC_FPUREGISTER:
+            tempinfo^.valid := false;
+        end;
       end;
 
 
@@ -467,33 +474,48 @@ interface
               if release_to_normal then
                 tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tt_normal)
               else
-                tg.UnGetTemp(exprasmlist,tempinfo^.location.reference);
+                begin
+                  tg.UnGetTemp(exprasmlist,tempinfo^.location.reference);
+                  tempinfo^.valid := false;
+                end;
             end;
           LOC_CREGISTER,
           LOC_REGISTER:
             begin
-              { make sure the register allocator doesn't reuse the }
-              { register e.g. in the middle of a loop              }
-{$ifndef cpu64bit}
-              if tempinfo^.location.size in [OS_64,OS_S64] then
+              if not(cs_regvars in aktglobalswitches) or
+                 (pi_has_goto in current_procinfo.flags) then
                 begin
-                  cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reghi);
-                  cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reglo);
-                end
-              else
+                  { make sure the register allocator doesn't reuse the }
+                  { register e.g. in the middle of a loop              }
+{$ifndef cpu64bit}
+                  if tempinfo^.location.size in [OS_64,OS_S64] then
+                    begin
+                      cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reghi);
+                      cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reglo);
+                    end
+                  else
 {$endif cpu64bit}
-                cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
+                    cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
+                end;
               if release_to_normal then
-                tempinfo^.location.loc := LOC_REGISTER;
+                tempinfo^.location.loc := LOC_REGISTER
+              else
+                tempinfo^.valid := false;
             end;
           LOC_CFPUREGISTER,
           LOC_FPUREGISTER:
             begin
-              { make sure the register allocator doesn't reuse the }
-              { register e.g. in the middle of a loop              }
-              cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
+              if not(cs_regvars in aktglobalswitches) or
+                 (pi_has_goto in current_procinfo.flags) then
+                begin
+                  { make sure the register allocator doesn't reuse the }
+                  { register e.g. in the middle of a loop              }
+                  cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
+                end;
               if release_to_normal then
-                tempinfo^.location.loc := LOC_FPUREGISTER;
+                tempinfo^.location.loc := LOC_FPUREGISTER
+              else
+                tempinfo^.valid := false;
             end;
           else
             internalerror(200507161);

+ 41 - 20
compiler/ncgutil.pas

@@ -159,7 +159,7 @@ implementation
     procinfo,paramgr,fmodule,
     regvars,dwarf,dbgbase,
     pass_1,pass_2,
-    ncon,nld,nutils,
+    nbas,ncon,nld,nutils,
     tgobj,cgobj
 {$ifdef powerpc}
     , cpupi
@@ -2121,29 +2121,50 @@ implementation
       end;
 
 
+    procedure add_regvars(var rv: tusedregvars; const location: tlocation);
+      begin
+        case location.loc of
+          LOC_CREGISTER:
+{$ifndef cpu64bit}
+            if location.size in [OS_64,OS_S64] then
+              begin
+                rv.intregvars.addnodup(getsupreg(location.register64.reglo));
+                rv.intregvars.addnodup(getsupreg(location.register64.reghi));
+              end
+            else
+{$endif cpu64bit}
+              rv.intregvars.addnodup(getsupreg(location.register));
+          LOC_CFPUREGISTER:
+            rv.fpuregvars.addnodup(getsupreg(location.register));
+          LOC_CMMREGISTER:
+            rv.mmregvars.addnodup(getsupreg(location.register));
+        end;
+      end;
+
+
     function do_get_used_regvars(var n: tnode; arg: pointer): foreachnoderesult;
       var
         rv: pusedregvars absolute arg;
       begin
-        if (n.nodetype = loadn) and
-           (tloadnode(n).symtableentry.typ in [globalvarsym,localvarsym,paravarsym]) then
-          with tabstractnormalvarsym(tloadnode(n).symtableentry).localloc do
-            case loc of
-              LOC_CREGISTER:
-{$ifndef cpu64bit}
-                if size in [OS_64,OS_S64] then
-                  begin
-                    rv^.intregvars.addnodup(getsupreg(register64.reglo));
-                    rv^.intregvars.addnodup(getsupreg(register64.reghi));
-                end
-              else
-{$endif cpu64bit}
-                rv^.intregvars.addnodup(getsupreg(register));
-              LOC_CFPUREGISTER:
-                rv^.fpuregvars.addnodup(getsupreg(register));
-              LOC_CMMREGISTER:
-                rv^.mmregvars.addnodup(getsupreg(register));
-            end;
+        case (n.nodetype) of
+          temprefn:
+            { We only have to synchronise a tempnode before a loop if it is }
+            { not created inside the loop, and only synchronise after the   }
+            { loop if it's not destroyed inside the loop. If it's created   }
+            { before the loop and not yet destroyed, then before the loop   }
+            { is secondpassed tempinfo^.valid will be true, and we get the  }
+            { correct registers. If it's not destroyed inside the loop,     }
+            { then after the loop has been secondpassed tempinfo^.valid     }
+            { be true and we also get the right registers. In other cases,  }
+            { tempinfo^.valid will be false and so we do not add            }
+            { unnecessary registers. This way, we don't have to look at     }
+            { tempcreate and tempdestroy nodes to get this info (JM)        }
+            if (ttemprefnode(n).tempinfo^.valid) then
+              add_regvars(rv^,ttemprefnode(n).tempinfo^.location);
+          loadn:
+            if (tloadnode(n).symtableentry.typ in [globalvarsym,localvarsym,paravarsym]) then
+              add_regvars(rv^,tabstractnormalvarsym(tloadnode(n).symtableentry).localloc);
+        end;
         result := fen_true;
       end;