Prechádzať zdrojové kódy

* factored out spilling code that deals with operand types into virtual
methods so they can be overridden by platform-specific variants
for platform-specific operand types

git-svn-id: trunk@30425 -

Jonas Maebe 10 rokov pred
rodič
commit
e750678f37
1 zmenil súbory, kde vykonal 139 pridanie a 122 odobranie
  1. 139 122
      compiler/rgobj.pas

+ 139 - 122
compiler/rgobj.pas

@@ -192,6 +192,10 @@ unit rgobj;
         procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister;orgsupreg:tsuperregister);virtual;
         procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister;orgsupreg:tsuperregister);virtual;
 
+        function addreginfo(var regs: tspillregsinfo; const r: tsuperregisterset; reg: tregister; operation: topertype): boolean;
+        function instr_get_oper_spilling_info(var regs: tspillregsinfo; const r: tsuperregisterset; instr: tai_cpu_abstract_sym; opidx: longint): boolean; virtual;
+        procedure substitute_spilled_registers(const regs: tspillregsinfo; instr: tai_cpu_abstract_sym; opidx: longint);
+        procedure try_replace_reg(const regs: tspillregsinfo; var reg: tregister; useloadreg: boolean); virtual;
         function instr_spill_register(list:TAsmList;
                                       instr:tai_cpu_abstract_sym;
                                       const r:Tsuperregisterset;
@@ -2067,99 +2071,56 @@ unit rgobj;
       end;
 
 
-    function trgobj.instr_spill_register(list:TAsmList;
-                                         instr:tai_cpu_abstract_sym;
-                                         const r:Tsuperregisterset;
-                                         const spilltemplist:Tspill_temp_list): boolean;
+    function trgobj.addreginfo(var regs: tspillregsinfo; const r: tsuperregisterset; reg: tregister; operation: topertype): boolean;
       var
-        counter: longint;
-        regs: tspillregsinfo;
-        spilled: boolean;
-
-      procedure addreginfo(reg: tregister; operation: topertype);
-        var
-          i, tmpindex: longint;
-          supreg: tsuperregister;
-        begin
-          tmpindex := regs.reginfocount;
-          supreg := get_alias(getsupreg(reg));
-          { did we already encounter this register? }
-          for i := 0 to pred(regs.reginfocount) do
-            if (regs.reginfo[i].orgreg = supreg) then
-              begin
-                tmpindex := i;
-                break;
-              end;
-          if tmpindex > high(regs.reginfo) then
-            internalerror(2003120301);
-          regs.reginfo[tmpindex].orgreg := supreg;
-          include(regs.reginfo[tmpindex].spillregconstraints,get_spill_subreg(reg));
-          if supregset_in(r,supreg) then
+        i, tmpindex: longint;
+        supreg: tsuperregister;
+      begin
+        result:=false;
+        tmpindex := regs.reginfocount;
+        supreg := get_alias(getsupreg(reg));
+        { did we already encounter this register? }
+        for i := 0 to pred(regs.reginfocount) do
+          if (regs.reginfo[i].orgreg = supreg) then
             begin
-              { add/update info on this register }
-              regs.reginfo[tmpindex].mustbespilled := true;
-              case operation of
-                operand_read:
+              tmpindex := i;
+              break;
+            end;
+        if tmpindex > high(regs.reginfo) then
+          internalerror(2003120301);
+        regs.reginfo[tmpindex].orgreg := supreg;
+        include(regs.reginfo[tmpindex].spillregconstraints,get_spill_subreg(reg));
+        if supregset_in(r,supreg) then
+          begin
+            { add/update info on this register }
+            regs.reginfo[tmpindex].mustbespilled := true;
+            case operation of
+              operand_read:
+                regs.reginfo[tmpindex].regread := true;
+              operand_write:
+                regs.reginfo[tmpindex].regwritten := true;
+              operand_readwrite:
+                begin
                   regs.reginfo[tmpindex].regread := true;
-                operand_write:
                   regs.reginfo[tmpindex].regwritten := true;
-                operand_readwrite:
-                  begin
-                    regs.reginfo[tmpindex].regread := true;
-                    regs.reginfo[tmpindex].regwritten := true;
-                  end;
-              end;
-              spilled := true;
+                end;
             end;
-          inc(regs.reginfocount,ord(regs.reginfocount=tmpindex));
-        end;
-
-
-      procedure tryreplacereg(var reg: tregister; useloadreg: boolean);
-        var
-          i: longint;
-          supreg: tsuperregister;
-        begin
-          supreg:=get_alias(getsupreg(reg));
-          for i:=0 to pred(regs.reginfocount) do
-            if (regs.reginfo[i].mustbespilled) and
-               (regs.reginfo[i].orgreg=supreg) then
-              begin
-                { Only replace supreg }
-                if useloadreg then
-                  setsupreg(reg,getsupreg(regs.reginfo[i].loadreg))
-                else
-                  setsupreg(reg,getsupreg(regs.reginfo[i].storereg));
-                break;
-              end;
-        end;
+            result:=true;
+          end;
+        inc(regs.reginfocount,ord(regs.reginfocount=tmpindex));
+      end;
 
 
-      var
-        loadpos,
-        storepos : tai;
-        oldlive_registers : tsuperregisterworklist;
+    function trgobj.instr_get_oper_spilling_info(var regs: tspillregsinfo; const r: tsuperregisterset; instr: tai_cpu_abstract_sym; opidx: longint): boolean;
       begin
-        result := false;
-        fillchar(regs,sizeof(regs),0);
-        for counter := low(regs.reginfo) to high(regs.reginfo) do
-          begin
-            regs.reginfo[counter].orgreg := RS_INVALID;
-            regs.reginfo[counter].loadreg := NR_INVALID;
-            regs.reginfo[counter].storereg := NR_INVALID;
-          end;
-        spilled := false;
-
-        { check whether and if so which and how (read/written) this instructions contains
-          registers that must be spilled }
-        for counter := 0 to instr.ops-1 do
-         with instr.oper[counter]^ do
+        result:=false;
+        with instr.oper[opidx]^ do
           begin
             case typ of
               top_reg:
                 begin
                   if (getregtype(reg) = regtype) then
-                    addreginfo(reg,instr.spilling_get_operation_type(counter));
+                    result:=addreginfo(regs,r,reg,instr.spilling_get_operation_type(opidx));
                 end;
               top_ref:
                 begin
@@ -2168,14 +2129,14 @@ unit rgobj;
                       begin
                         if (base <> NR_NO) and
                             (getregtype(base)=regtype) then
-                          addreginfo(base,instr.spilling_get_operation_type_ref(counter,base));
+                          result:=addreginfo(regs,r,base,instr.spilling_get_operation_type_ref(opidx,base));
                         if (index <> NR_NO) and
                             (getregtype(index)=regtype) then
-                          addreginfo(index,instr.spilling_get_operation_type_ref(counter,index));
+                          result:=addreginfo(regs,r,index,instr.spilling_get_operation_type_ref(opidx,index)) or result;
 {$if defined(x86)}
                         if (segment <> NR_NO) and
                             (getregtype(segment)=regtype) then
-                          addreginfo(segment,instr.spilling_get_operation_type_ref(counter,segment));
+                          result:=addreginfo(regs,r,segment,instr.spilling_get_operation_type_ref(opidx,segment)) or result;
 {$endif defined(x86)}
                       end;
                 end;
@@ -2184,11 +2145,101 @@ unit rgobj;
                 begin
                   if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
                     if shifterop^.rs<>NR_NO then
-                      addreginfo(shifterop^.rs,operand_read);
+                      result:=addreginfo(regs,r,shifterop^.rs,operand_read);
                 end;
 {$endif ARM}
             end;
           end;
+      end;
+
+
+    procedure trgobj.try_replace_reg(const regs: tspillregsinfo; var reg: tregister; useloadreg: boolean);
+      var
+        i: longint;
+        supreg: tsuperregister;
+      begin
+        supreg:=get_alias(getsupreg(reg));
+        for i:=0 to pred(regs.reginfocount) do
+          if (regs.reginfo[i].mustbespilled) and
+             (regs.reginfo[i].orgreg=supreg) then
+            begin
+              { Only replace supreg }
+              if useloadreg then
+                setsupreg(reg, getsupreg(regs.reginfo[i].loadreg))
+              else
+                setsupreg(reg, getsupreg(regs.reginfo[i].storereg));
+              break;
+            end;
+      end;
+
+
+    procedure trgobj.substitute_spilled_registers(const regs: tspillregsinfo; instr: tai_cpu_abstract_sym; opidx: longint);
+      begin
+        with instr.oper[opidx]^ do
+          case typ of
+            top_reg:
+              begin
+                if (getregtype(reg) = regtype) then
+                  try_replace_reg(regs, reg, not ssa_safe or
+                    (instr.spilling_get_operation_type(opidx)=operand_read));
+              end;
+            top_ref:
+              begin
+                if regtype in [R_INTREGISTER, R_ADDRESSREGISTER] then
+                  begin
+                    if (ref^.base <> NR_NO) and
+                        (getregtype(ref^.base)=regtype) then
+                      try_replace_reg(regs, ref^.base,
+                        not ssa_safe or (instr.spilling_get_operation_type_ref(opidx, ref^.base)=operand_read));
+                    if (ref^.index <> NR_NO) and
+                        (getregtype(ref^.index)=regtype) then
+                      try_replace_reg(regs, ref^.index,
+                        not ssa_safe or (instr.spilling_get_operation_type_ref(opidx, ref^.index)=operand_read));
+  {$if defined(x86)}
+                    if (ref^.segment <> NR_NO) and
+                        (getregtype(ref^.segment)=regtype) then
+                      try_replace_reg(regs, ref^.segment, true { always read-only });
+  {$endif defined(x86)}
+                  end;
+              end;
+  {$ifdef ARM}
+            top_shifterop:
+              begin
+                if regtype in [R_INTREGISTER, R_ADDRESSREGISTER] then
+                  try_replace_reg(regs, shifterop^.rs, true { always read-only });
+              end;
+  {$endif ARM}
+          end;
+      end;
+
+
+    function trgobj.instr_spill_register(list:TAsmList;
+                                         instr:tai_cpu_abstract_sym;
+                                         const r:Tsuperregisterset;
+                                         const spilltemplist:Tspill_temp_list): boolean;
+      var
+        counter: longint;
+        regs: tspillregsinfo;
+        spilled: boolean;
+      var
+        loadpos,
+        storepos : tai;
+        oldlive_registers : tsuperregisterworklist;
+      begin
+        result := false;
+        fillchar(regs,sizeof(regs),0);
+        for counter := low(regs.reginfo) to high(regs.reginfo) do
+          begin
+            regs.reginfo[counter].orgreg := RS_INVALID;
+            regs.reginfo[counter].loadreg := NR_INVALID;
+            regs.reginfo[counter].storereg := NR_INVALID;
+          end;
+        spilled := false;
+
+        { check whether and if so which and how (read/written) this instructions contains
+          registers that must be spilled }
+        for counter := 0 to instr.ops-1 do
+          spilled:=instr_get_oper_spilling_info(regs,r,instr,counter) or spilled;
 
         { if no spilling for this instruction we can leave }
         if not spilled then
@@ -2352,45 +2403,11 @@ unit rgobj;
 
         { substitute registers }
         for counter:=0 to instr.ops-1 do
-          with instr.oper[counter]^ do
-            case typ of
-              top_reg:
-                begin
-                  if (getregtype(reg) = regtype) then
-                    tryreplacereg(reg,not ssa_safe or
-                      (instr.spilling_get_operation_type(counter)=operand_read));
-                end;
-              top_ref:
-                begin
-                  if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
-                    begin
-                      if (ref^.base <> NR_NO) and
-                          (getregtype(ref^.base)=regtype) then
-                        tryreplacereg(ref^.base,
-                          not ssa_safe or (instr.spilling_get_operation_type_ref(counter,ref^.base)=operand_read));
-                      if (ref^.index <> NR_NO) and
-                          (getregtype(ref^.index)=regtype) then
-                        tryreplacereg(ref^.index,
-                          not ssa_safe or (instr.spilling_get_operation_type_ref(counter,ref^.index)=operand_read));
-{$if defined(x86)}
-                      if (ref^.segment <> NR_NO) and
-                          (getregtype(ref^.segment)=regtype) then
-                        tryreplacereg(ref^.segment,true { always read-only });
-{$endif defined(x86)}
-                    end;
-                end;
-{$ifdef ARM}
-              top_shifterop:
-                begin
-                  if regtype in [R_INTREGISTER,R_ADDRESSREGISTER] then
-                    tryreplacereg(shifterop^.rs,true { always read-only });
-                end;
-{$endif ARM}
-            end;
-         {We have modified the instruction; perhaps the new instruction has
+          substitute_spilled_registers(regs,instr,counter);
+        { We have modified the instruction; perhaps the new instruction has
           certain constraints regarding which imaginary registers interfere
-          with certain physical registers.}
-         add_cpu_interferences(instr);
+          with certain physical registers. }
+        add_cpu_interferences(instr);
       end;
 
 end.