浏览代码

+ replace registers to spill in mov instructions and convert them into ldr/str

git-svn-id: trunk@26677 -
florian 11 年之前
父节点
当前提交
829764e96b
共有 2 个文件被更改,包括 46 次插入2 次删除
  1. 44 0
      compiler/arm/rgcpu.pas
  2. 2 2
      compiler/rgobj.pas

+ 44 - 0
compiler/arm/rgcpu.pas

@@ -43,6 +43,8 @@ unit rgcpu;
        public
          procedure do_spill_read(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
          procedure do_spill_written(list:TAsmList;pos:tai;const spilltemp:treference;tempreg:tregister);override;
+         function do_spill_replace(list : TAsmList;instr : taicpu;
+           orgreg : tsuperregister;const spilltemp : treference) : boolean;override;
          procedure add_constraints(reg:tregister);override;
          function  get_spill_subreg(r:tregister) : tsubregister;override;
        end;
@@ -280,6 +282,48 @@ unit rgcpu;
       end;
 
 
+    function trgcpu.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+      var
+        b : byte;
+      begin
+        result:=false;
+        if abs(spilltemp.offset)>4095 then
+          exit;
+
+        { Replace 'mov  dst,orgreg' with 'ldr  dst,spilltemp'
+          and     'mov  orgreg,src' with 'str  dst,spilltemp' }
+        with instr do
+          begin
+            if (opcode=A_MOV) and (ops=2) and (oper[1]^.typ=top_reg) and (oper[0]^.typ=top_reg) then
+              begin
+                if (getregtype(oper[0]^.reg)=regtype) and
+                   (get_alias(getsupreg(oper[0]^.reg))=orgreg) and
+                   (get_alias(getsupreg(oper[1]^.reg))<>orgreg) then
+                  begin
+                    { str expects the register in oper[0] }
+                    oper[0]^.typ:=top_reg;
+                    oper[0]^.reg:=oper[1]^.reg;
+                    oper[1]^.typ:=top_ref;
+                    new(oper[1]^.ref);
+                    oper[1]^.ref^:=spilltemp;
+                    opcode:=A_STR;
+                    result:=true;
+                  end
+                else if (getregtype(oper[1]^.reg)=regtype) and
+                   (get_alias(getsupreg(oper[1]^.reg))=orgreg) and
+                   (get_alias(getsupreg(oper[0]^.reg))<>orgreg) then
+                  begin
+                    oper[1]^.typ:=top_ref;
+                    new(oper[1]^.ref);
+                    oper[1]^.ref^:=spilltemp;
+                    opcode:=A_LDR;
+                    result:=true;
+                  end;
+              end;
+          end;
+      end;
+
+
     procedure trgcpu.add_constraints(reg:tregister);
       var
         supreg,i : Tsuperregister;

+ 2 - 2
compiler/rgobj.pas

@@ -2137,7 +2137,7 @@ unit rgobj;
         if not spilled then
           exit;
 
-{$if defined(x86) or defined(mips) or defined(sparc)}
+{$if defined(x86) or defined(mips) or defined(sparc) or defined(arm)}
         { Try replacing the register with the spilltemp. This is useful only
           for the i386,x86_64 that support memory locations for several instructions
 
@@ -2152,7 +2152,7 @@ unit rgobj;
                     mustbespilled:=false;
                 end;
             end;
-{$endif defined(x86) or defined(mips) or defined(sparc)}
+{$endif defined(x86) or defined(mips) or defined(sparc) or defined(arm)}
 
         {
           There are registers that need are spilled. We generate the