Explorar o código

* Try to avoid spilling of an imm register if it contains a value loaded from an already spilled imm register. It likely leads to an endless loop and the register allocation fails.
This fixes the register allocation for i8086 when handling registers for very constrained instructions such as "mov ireg1,[ireg2+ireg3]".
Here ireg2 can be only BX or BP. So in most cases only BX is available. When ireg2 is spilled, its value must be loaded to BX only.
Coloring of the ireg which holds the spilled value must be as early as possible to be able to assign BX to this ireg.
This fix should also help register allocation for other constrained/old CPUs.

git-svn-id: trunk@45843 -

yury %!s(int64=5) %!d(string=hai) anos
pai
achega
c455e942e5
Modificáronse 1 ficheiros con 54 adicións e 13 borrados
  1. 54 13
      compiler/rgobj.pas

+ 54 - 13
compiler/rgobj.pas

@@ -92,7 +92,11 @@ unit rgobj;
         x,y:Tsuperregister;
       end;
 
-      Treginfoflag=(ri_coalesced,ri_selected);
+      Treginfoflag=(
+        ri_coalesced,   { the register is coalesced with other register }
+        ri_selected,    { the register is put to selectstack }
+        ri_spill_read   { the register contains a value loaded from a spilled register }
+      );
       Treginfoflagset=set of Treginfoflag;
 
       Treginfo=record
@@ -1476,7 +1480,7 @@ unit rgobj;
     var
       n : tsuperregister;
       adj : psuperregisterworklist;
-      maxlength,p,i :word;
+      maxlength,minlength,p,i :word;
       minweight: longint;
       {$ifdef SPILLING_NEW}
       dist: Double;
@@ -1535,25 +1539,61 @@ unit rgobj;
         the most conflicts and keeping them in a register will not reduce the
         complexity and even can cause the help registers for the spilling code
         to get too much conflicts with the result that the spilling code
-        will never converge (PFV) }
+        will never converge (PFV)
+
+        We need a special processing for nodes with the ri_spill_read flag set. 
+        These nodes contain a value loaded from a previously spilled node. 
+        We need to avoid another spilling of ri_spill_read nodes, since it will 
+        likely lead to an endless loop and the register allocation will fail.
+      }
       maxlength:=0;
       minweight:=high(longint);
-      p:=0;
+      p:=high(p);
       with spillworklist do
         begin
           {Safe: This procedure is only called if length<>0}
+          { Search for a candidate to be spilled, ignoring nodes with the ri_spill_read flag set. }
           for i:=0 to length-1 do
+            if not(ri_spill_read in reginfo[buf^[i]].flags) then
+              begin
+                adj:=reginfo[buf^[i]].adjlist;
+                if assigned(adj) and
+                   (
+                    (adj^.length>maxlength) or
+                    ((adj^.length=maxlength) and (reginfo[buf^[i]].weight<minweight))
+                   ) then
+                  begin
+                    p:=i;
+                    maxlength:=adj^.length;
+                    minweight:=reginfo[buf^[i]].weight;
+                  end;
+              end;
+
+          if p=high(p) then
             begin
-              adj:=reginfo[buf^[i]].adjlist;
-              if assigned(adj) and
-                 (
-                  (adj^.length>maxlength) or
-                  ((adj^.length=maxlength) and (reginfo[buf^[i]].weight<minweight))
-                 ) then
+              { If no normal nodes found, then only ri_spill_read nodes are present
+                in the list. Finding the node with the least interferences and
+                the least weight.
+                This allows us to put the most restricted ri_spill_read nodes
+                to the top of selectstack so they will be the first to get
+                a color assigned.
+              }
+              minlength:=high(maxlength);
+              minweight:=high(minweight);
+              p:=0;
+              for i:=0 to length-1 do
                 begin
-                  p:=i;
-                  maxlength:=adj^.length;
-                  minweight:=reginfo[buf^[i]].weight;
+                  adj:=reginfo[buf^[i]].adjlist;
+                  if assigned(adj) and
+                     (
+                      (adj^.length<minlength) or
+                      ((adj^.length=minlength) and (reginfo[buf^[i]].weight<minweight))
+                     ) then
+                    begin
+                      p:=i;
+                      minlength:=adj^.length;
+                      minweight:=reginfo[buf^[i]].weight;
+                    end;
                 end;
             end;
           n:=buf^[p];
@@ -2647,6 +2687,7 @@ unit rgobj;
                 begin
                   loadreg:=getregisterinline(list,regs.reginfo[counter].spillregconstraints);
                   do_spill_read(list,tai(loadpos.previous),spilltemplist[orgreg],loadreg,orgreg);
+                  include(reginfo[getsupreg(loadreg)].flags,ri_spill_read);
                 end;
             end;