Bladeren bron

* renamed t_times to executionweight and moved it to
code generation pass
* include executionweight in the spilling decision

git-svn-id: trunk@9330 -

peter 17 jaren geleden
bovenliggende
commit
6058b2c247
10 gewijzigde bestanden met toevoegingen van 63 en 65 verwijderingen
  1. 4 2
      compiler/cgobj.pas
  2. 1 0
      compiler/cgutils.pas
  3. 30 3
      compiler/ncgflw.pas
  4. 10 0
      compiler/ncgset.pas
  5. 2 27
      compiler/nflw.pas
  6. 0 3
      compiler/nld.pas
  7. 0 11
      compiler/nset.pas
  8. 0 7
      compiler/psub.pas
  9. 15 7
      compiler/rgobj.pas
  10. 1 5
      compiler/x86/rgx86.pas

+ 4 - 2
compiler/cgobj.pas

@@ -55,9 +55,10 @@ unit cgobj;
        }
        tcg = class
        public
+          { how many times is this current code executed }
+          executionweight : longint;
           alignment : talignment;
           rg        : array[tregistertype] of trgobj;
-          t_times   : longint;
        {$ifdef flowgraph}
           aktflownode:word;
        {$endif}
@@ -608,6 +609,7 @@ implementation
       begin
         fillchar(rg,sizeof(rg),0);
         add_reg_instruction_hook:=@add_reg_instruction;
+        executionweight:=1;
       end;
 
 
@@ -757,7 +759,7 @@ implementation
           No IE can be generated, because the VMT is written
           without a valid rg[] }
         if assigned(rg[rt]) then
-          rg[rt].add_reg_instruction(instr,r);
+          rg[rt].add_reg_instruction(instr,r,cg.executionweight);
       end;
 
 

+ 1 - 0
compiler/cgutils.pas

@@ -142,6 +142,7 @@ unit cgutils;
     { returns r with the given alignment }
     function setalignment(const r : treference;b : byte) : treference;
 
+
 implementation
 
 uses

+ 30 - 3
compiler/ncgflw.pas

@@ -138,6 +138,7 @@ implementation
          oldclabel,oldblabel : tasmlabel;
          otlabel,oflabel : tasmlabel;
          oldflowcontrol : tflowcontrol;
+         oldexecutionweight : longint;
       begin
          location_reset(location,LOC_VOID,OS_NO);
 
@@ -167,8 +168,15 @@ implementation
 
          current_procinfo.CurrContinueLabel:=lcont;
          current_procinfo.CurrBreakLabel:=lbreak;
+
          if assigned(right) then
-           secondpass(right);
+           begin
+             { calc register weight }
+             oldexecutionweight:=cg.executionweight;
+             cg.executionweight:=cg.executionweight*8;
+             secondpass(right);
+             cg.executionweight:=oldexecutionweight;
+           end;
 
 {$ifdef OLDREGVARS}
          load_all_regvars(current_asmdata.CurrAsmList);
@@ -213,6 +221,7 @@ implementation
       var
          hl,otlabel,oflabel : tasmlabel;
          oldflowcontrol: tflowcontrol;
+         oldexecutionweight : longint;
 (*
          org_regvar_loaded_other,
          then_regvar_loaded_other,
@@ -254,6 +263,11 @@ implementation
              org_regvar_loaded_other := rg.regvar_loaded_other;
            end;
 *)
+         { determines registers weigths }
+         oldexecutionweight:=cg.executionweight;
+         cg.executionweight:=cg.executionweight div 2;
+         if cg.executionweight<1 then
+           cg.executionweight:=1;
 
          if assigned(right) then
            begin
@@ -361,6 +375,8 @@ implementation
            end;
 *)
 
+         cg.executionweight:=oldexecutionweight;
+
          current_procinfo.CurrTrueLabel:=otlabel;
          current_procinfo.CurrFalseLabel:=oflabel;
          flowcontrol := oldflowcontrol + (flowcontrol - [fc_inflowcontrol]);
@@ -416,7 +432,7 @@ implementation
          count_var_is_signed,do_loopvar_at_end : boolean;
          cmp_const:Tconstexprint;
          oldflowcontrol : tflowcontrol;
-
+         oldexecutionweight : longint;
       begin
          location_reset(location,LOC_VOID,OS_NO);
          oldflowcontrol:=flowcontrol;
@@ -452,9 +468,16 @@ implementation
          else
            temptovalue:=false;
 
-         { produce start assignment }
+         { load loopvar, prefer loopvar being a register variable }
+         oldexecutionweight:=cg.executionweight;
+         inc(cg.executionweight,8);
          secondpass(left);
+         cg.executionweight:=oldexecutionweight;
+
+         { load from value }
          secondpass(right);
+
+         { produce start assignment }
          case left.location.loc of
            LOC_REFERENCE,
            LOC_CREFERENCE :
@@ -534,7 +557,11 @@ implementation
 
          if assigned(t2) then
            begin
+             { Calc register weight }
+             oldexecutionweight:=cg.executionweight;
+             cg.executionweight:=cg.executionweight*8;
              secondpass(t2);
+             cg.executionweight:=oldexecutionweight;
 {$ifdef OLDREGVARS}
              load_all_regvars(current_asmdata.CurrAsmList);
 {$endif OLDREGVARS}

+ 10 - 0
compiler/ncgset.pas

@@ -673,6 +673,7 @@ implementation
          isjump : boolean;
          max_dist,
          dist : aword;
+         oldexecutionweight : longint;
       begin
          location_reset(location,LOC_VOID,OS_NO);
 
@@ -817,6 +818,12 @@ implementation
                 genlinearlist(labels);
            end;
 
+         { estimates the repeat of each instruction }
+         oldexecutionweight:=cg.executionweight;
+         cg.executionweight:=cg.executionweight div case_count_labels(labels);
+         if cg.executionweight<1 then
+           cg.executionweight:=1;
+
          { generate the instruction blocks }
          for i:=0 to blocks.count-1 do
            begin
@@ -840,6 +847,9 @@ implementation
               load_all_regvars(current_asmdata.CurrAsmList);
 {$endif OLDREGVARS}
            end;
+
+         cg.executionweight:=oldexecutionweight;
+
          current_asmdata.CurrAsmList.concat(cai_align.create(current_settings.alignment.jumpalign));
          cg.a_label(current_asmdata.CurrAsmList,endlabel);
 

+ 2 - 27
compiler/nflw.pas

@@ -474,21 +474,15 @@ implementation
 
 
     function twhilerepeatnode.pass_1 : tnode;
-      var
 {$ifdef prefetchnext}
+      var
          runnernode, prefetchcode: tnode;
          assignmentnode: tassignmentnode;
          prefetchstatements: tstatementnode;
 {$endif prefetchnext}
-         old_t_times : longint;
       begin
          result:=nil;
          expectloc:=LOC_VOID;
-         old_t_times:=cg.t_times;
-
-         { calc register weight }
-         if not(cs_opt_size in current_settings.optimizerswitches) then
-           cg.t_times:=cg.t_times*8;
 
          firstpass(left);
          if codegenerror then
@@ -502,7 +496,6 @@ implementation
                 exit;
            end;
 
-         cg.t_times:=old_t_times;
 {$ifdef prefetchnext}
          { do at the end so all complex typeconversions are already }
          { converted to calln's                                     }
@@ -708,20 +701,11 @@ implementation
 
 
     function tifnode.pass_1 : tnode;
-      var
-         old_t_times : longint;
       begin
          result:=nil;
          expectloc:=LOC_VOID;
-         old_t_times:=cg.t_times;
          firstpass(left);
 
-         { determines registers weigths }
-         if not(cs_opt_size in current_settings.optimizerswitches) then
-           cg.t_times:=cg.t_times div 2;
-         if cg.t_times=0 then
-           cg.t_times:=1;
-
          { if path }
          if assigned(right) then
            firstpass(right);
@@ -734,8 +718,6 @@ implementation
 
          if codegenerror then
            exit;
-
-         cg.t_times:=old_t_times;
       end;
 
 
@@ -824,9 +806,7 @@ implementation
 
 
     function tfornode.pass_1 : tnode;
-      var
-         old_t_times : longint;
-     begin
+      begin
          result:=nil;
          expectloc:=LOC_VOID;
 
@@ -836,14 +816,9 @@ implementation
 
          if assigned(t2) then
           begin
-            { Calc register weight }
-            old_t_times:=cg.t_times;
-            if not(cs_opt_size in current_settings.optimizerswitches) then
-              cg.t_times:=cg.t_times*8;
             firstpass(t2);
             if codegenerror then
              exit;
-            cg.t_times:=old_t_times;
           end;
       end;
 

+ 0 - 3
compiler/nld.pas

@@ -385,9 +385,6 @@ implementation
                   Tabstractvarsym(symtableentry).trigger_notifications(vn_onwrite)
                 else
                   Tabstractvarsym(symtableentry).trigger_notifications(vn_onread);
-                { count variable references }
-                if cg.t_times>1 then
-                  tabstractvarsym(symtableentry).IncRefCountBy(cg.t_times-1);
               end;
             procsym :
                 begin

+ 0 - 11
compiler/nset.pas

@@ -601,7 +601,6 @@ implementation
 
     function tcasenode.pass_1 : tnode;
       var
-         old_t_times : longint;
          i  : integer;
       begin
          result:=nil;
@@ -611,16 +610,7 @@ implementation
          set_varstate(left,vs_read,[vsf_must_be_valid]);
          if codegenerror then
            exit;
-         { walk through all instructions }
 
-         { estimates the repeat of each instruction }
-         old_t_times:=cg.t_times;
-         if not(cs_opt_size in current_settings.optimizerswitches) then
-           begin
-              cg.t_times:=cg.t_times div case_count_labels(labels);
-              if cg.t_times<1 then
-                cg.t_times:=1;
-           end;
          { first case }
          for i:=0 to blocks.count-1 do
            firstpass(pcaseblock(blocks[i])^.statement);
@@ -628,7 +618,6 @@ implementation
          { may be handle else tree }
          if assigned(elseblock) then
            firstpass(elseblock);
-         cg.t_times:=old_t_times;
       end;
 
 

+ 0 - 7
compiler/psub.pas

@@ -728,13 +728,6 @@ implementation
         { add parast/localst to symtablestack }
         add_to_symtablestack;
 
-        { when size optimization only count occurrence }
-        if cs_opt_size in current_settings.optimizerswitches then
-          cg.t_times:=1
-        else
-          { reference for repetition is 100 }
-          cg.t_times:=100;
-
         { clear register count }
         procdef.localst.SymList.ForEachCall(@clearrefs,nil);
         procdef.parast.SymList.ForEachCall(@clearrefs,nil);

+ 15 - 7
compiler/rgobj.pas

@@ -100,6 +100,7 @@ unit rgobj;
         adjlist  : Psuperregisterworklist;
         degree   : TSuperregister;
         flags    : Treginfoflagset;
+        weight   : longint;
       end;
       Preginfo=^TReginfo;
 
@@ -145,7 +146,7 @@ unit rgobj;
         {# Free multiple registers specified.}
         procedure dealloccpuregisters(list:TAsmList;const r:Tcpuregisterset);virtual;
         function uses_registers:boolean;virtual;
-        procedure add_reg_instruction(instr:Tai;r:tregister);
+        procedure add_reg_instruction(instr:Tai;r:tregister;aweight:longint);
         procedure add_move_instruction(instr:Taicpu);
         {# Do the register allocation.}
         procedure do_register_allocation(list:TAsmList;headertai:tai);virtual;
@@ -694,7 +695,7 @@ unit rgobj;
       end;
 
 
-    procedure trgobj.add_reg_instruction(instr:Tai;r:tregister);
+    procedure trgobj.add_reg_instruction(instr:Tai;r:tregister;aweight:longint);
       var
         supreg : tsuperregister;
       begin
@@ -707,6 +708,8 @@ unit rgobj;
         if supreg>=first_imaginary then
           with reginfo[supreg] do
             begin
+              if aweight>weight then
+                weight:=aweight;
               if (live_range_direction=rad_forward) then
                 begin
                   if not assigned(live_start) then
@@ -1250,12 +1253,11 @@ unit rgobj;
     end;
 
     procedure trgobj.select_spill;
-
     var
       n : tsuperregister;
       adj : psuperregisterworklist;
       max,p,i:word;
-
+      minweight: longint;
     begin
       { We must look for the element with the most interferences in the
         spillworklist. This is required because those registers are creating
@@ -1264,6 +1266,7 @@ unit rgobj;
         to get too much conflicts with the result that the spilling code
         will never converge (PFV) }
       max:=0;
+      minweight:=high(longint);
       p:=0;
       with spillworklist do
         begin
@@ -1271,10 +1274,15 @@ unit rgobj;
           for i:=0 to length-1 do
             begin
               adj:=reginfo[buf^[i]].adjlist;
-              if assigned(adj) and (adj^.length>max) then
+              if assigned(adj) and
+                 (
+                  (adj^.length>max) or
+                  ((adj^.length=max) and (reginfo[buf^[i]].weight<minweight))
+                 ) then
                 begin
                   p:=i;
                   max:=adj^.length;
+                  minweight:=reginfo[buf^[i]].weight;
                 end;
             end;
           n:=buf^[p];
@@ -2023,7 +2031,7 @@ unit rgobj;
               if mustbespilled and regread and (not regwritten) then
                 begin
                   { The original instruction will be the next that uses this register }
-                  add_reg_instruction(instr,tempreg);
+                  add_reg_instruction(instr,tempreg,1);
                   ungetregisterinline(list,tempreg);
                 end;
             end;
@@ -2040,7 +2048,7 @@ unit rgobj;
                     tempreg:=getregisterinline(list,get_spill_subreg(regs[counter].spillreg));
                   { The original instruction will be the next that uses this register, this
                     also needs to be done for read-write registers }
-                  add_reg_instruction(instr,tempreg);
+                  add_reg_instruction(instr,tempreg,1);
                 end;
             end;
 

+ 1 - 5
compiler/x86/rgx86.pas

@@ -66,9 +66,6 @@ unit rgx86;
           is_reg_var_other : regvarother_booleanarray;
           regvar_loaded_other : regvarother_booleanarray;}
 
-          { tries to hold the amount of times which the current tree is processed  }
-          t_times: longint;
-
           fpuvaroffset : byte;
 
           constructor create;
@@ -134,7 +131,7 @@ implementation
                     end;
                 end;
               2,3 :
-                begin 
+                begin
                   { We can handle opcodes with 2 and 3 operands the same way. The opcodes
                     with 3 registers are shrd/shld, where the 3rd operand is const or CL,
                     that doesn't need spilling.
@@ -269,7 +266,6 @@ implementation
     constructor Trgx86fpu.create;
       begin
         used_in_proc:=[];
-        t_times := 0;
         unusedregsfpu:=usableregsfpu;
       end;