Browse Source

* Count the number of interferences with real registers.
* Do not coalesce registers 'u' and 'v' if 'u' is the last usable real register available for imaginary register 'n' which also interferences with 'v'.
This prevents endless spilling in some cases for constrained CPUs such as AVR. Resolves issue #37421.
Also this reduces the number of spilled registers in some cases and even eliminates spilling completely for some simple routines for i386 and AVR.
* Added a debug output of the number of spilled registers for each routine. This allows to easily compare results after changes in spilling algorithms.

git-svn-id: trunk@45987 -

yury 5 years ago
parent
commit
4964f5cf76
1 changed files with 23 additions and 1 deletions
  1. 23 1
      compiler/rgobj.pas

+ 23 - 1
compiler/rgobj.pas

@@ -116,6 +116,7 @@ unit rgobj;
 {$endif llvm}
 {$endif llvm}
         count_uses : longint;
         count_uses : longint;
         total_interferences : longint;
         total_interferences : longint;
+        real_reg_interferences: word;
       end;
       end;
       Preginfo=^TReginfo;
       Preginfo=^TReginfo;
 
 
@@ -605,7 +606,7 @@ unit rgobj;
       rtindex : longint = 0;
       rtindex : longint = 0;
     procedure trgobj.do_register_allocation(list:TAsmList;headertai:tai);
     procedure trgobj.do_register_allocation(list:TAsmList;headertai:tai);
       var
       var
-        spillingcounter:byte;
+        spillingcounter:longint;
         endspill:boolean;
         endspill:boolean;
         i : Longint;
         i : Longint;
       begin
       begin
@@ -645,6 +646,15 @@ unit rgobj;
 
 
         translate_registers(list);
         translate_registers(list);
 
 
+{$ifdef DEBUG_SPILLCOALESCE}
+        spillingcounter:=0;
+        for i:=0 to High(spillinfo) do
+          if spillinfo[i].spilled then
+            inc(spillingcounter);
+        if spillingcounter>0 then
+          writeln(current_procinfo.procdef.mangledname, ': spilled regs: ',spillingcounter);
+{$endif DEBUG_SPILLCOALESCE}
+
         { we need the translation table for debugging info and verbose assembler output,
         { we need the translation table for debugging info and verbose assembler output,
           so not dispose them yet (FK)
           so not dispose them yet (FK)
         }
         }
@@ -677,6 +687,8 @@ unit rgobj;
             if adjlist=nil then
             if adjlist=nil then
               new(adjlist,init);
               new(adjlist,init);
             adjlist^.add(v);
             adjlist^.add(v);
+            if v<first_imaginary then
+              inc(real_reg_interferences);
           end;
           end;
       end;
       end;
 
 
@@ -1233,6 +1245,16 @@ unit rgobj;
         for i:=1 to adj^.length do
         for i:=1 to adj^.length do
           begin
           begin
             n:=adj^.buf^[i-1];
             n:=adj^.buf^[i-1];
+            if (u<first_imaginary) and
+               (n>=first_imaginary) and
+               not ibitmap[u,n] and
+               (usable_registers_cnt-reginfo[n].real_reg_interferences<=1) then
+              begin
+                { Do not coalesce if 'u' is the last usable real register available
+                  for imaginary register 'n'. }
+                conservative:=false;
+                exit;
+              end;
             if not supregset_in(done,n) and
             if not supregset_in(done,n) and
                (reginfo[n].degree>=usable_registers_cnt) and
                (reginfo[n].degree>=usable_registers_cnt) and
                (reginfo[n].flags*[ri_coalesced,ri_selected]=[]) then
                (reginfo[n].flags*[ri_coalesced,ri_selected]=[]) then