浏览代码

+ MIPS: prevent coalescing written-to registers with $sp,$fp,$zero and $at.
+ Implemented subset of "spill replace" functionality, replacing moves from/to spilled registers with loads/stores to spill locations. This helps to reduce amount of instructions.

git-svn-id: trunk@24900 -

sergei 12 年之前
父节点
当前提交
8b8553991a
共有 3 个文件被更改,包括 66 次插入5 次删除
  1. 2 2
      compiler/mips/cgcpu.pas
  2. 58 0
      compiler/mips/rgcpu.pas
  3. 6 3
      compiler/rgobj.pas

+ 2 - 2
compiler/mips/cgcpu.pas

@@ -402,14 +402,14 @@ begin
     (pi_needs_got in current_procinfo.flags) then
     (pi_needs_got in current_procinfo.flags) then
     begin
     begin
       current_procinfo.got := NR_GP;
       current_procinfo.got := NR_GP;
-      rg[R_INTREGISTER]    := Trgcpu.Create(R_INTREGISTER, R_SUBD,
+      rg[R_INTREGISTER]    := Trgintcpu.Create(R_INTREGISTER, R_SUBD,
         [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
         [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
        RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
        RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
        RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
        RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
         first_int_imreg, []);
         first_int_imreg, []);
     end
     end
   else
   else
-    rg[R_INTREGISTER] := trgcpu.Create(R_INTREGISTER, R_SUBD,
+    rg[R_INTREGISTER] := trgintcpu.Create(R_INTREGISTER, R_SUBD,
       [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
       [RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
        RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
        RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
        RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
        RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],

+ 58 - 0
compiler/mips/rgcpu.pas

@@ -38,8 +38,12 @@ unit rgcpu;
         function get_spill_subreg(r : tregister) : tsubregister;override;
         function get_spill_subreg(r : tregister) : tsubregister;override;
         procedure do_spill_read(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
         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;
         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;
       end;
       end;
 
 
+      trgintcpu=class(trgcpu)
+        procedure add_cpu_interferences(p:tai);override;
+      end;
 
 
 implementation
 implementation
 
 
@@ -152,4 +156,58 @@ implementation
           inherited do_spill_written(list,pos,spilltemp,tempreg);
           inherited do_spill_written(list,pos,spilltemp,tempreg);
     end;
     end;
 
 
+
+    function trgcpu.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
+      begin
+        result:=false;
+        { Replace 'move  orgreg,src' with 'sw  src,spilltemp'
+              and 'move  dst,orgreg' with 'lw  dst,spilltemp' }
+        { TODO: A_MOV_S and A_MOV_D for float registers are also replaceable }
+        if (instr.opcode<>A_MOVE) or (abs(spilltemp.offset)>32767) then
+          exit;
+        if (instr.ops<>2) or
+           (instr.oper[0]^.typ<>top_reg) or
+           (instr.oper[1]^.typ<>top_reg) or
+           (getregtype(instr.oper[0]^.reg)<>regtype) or
+           (getregtype(instr.oper[1]^.reg)<>regtype) then
+          InternalError(2013061001);
+        if get_alias(getsupreg(instr.oper[1]^.reg))=orgreg then
+          begin
+            instr.opcode:=A_LW;
+          end
+        else if get_alias(getsupreg(instr.oper[0]^.reg))=orgreg then
+          begin
+            instr.opcode:=A_SW;
+            instr.oper[0]^:=instr.oper[1]^;
+          end
+        else
+          InternalError(2013061002);
+        instr.oper[1]^.typ:=top_ref;
+        new(instr.oper[1]^.ref);
+        instr.oper[1]^.ref^:=spilltemp;
+        result:=true;
+      end;
+
+
+    procedure trgintcpu.add_cpu_interferences(p: tai);
+      var
+        supreg: tsuperregister;
+      begin
+        if p.typ<>ait_instruction then
+          exit;
+        if (taicpu(p).ops>=1) and (taicpu(p).oper[0]^.typ=top_reg) and
+          (getregtype(taicpu(p).oper[0]^.reg)=regtype) and
+          (taicpu(p).spilling_get_operation_type(0) in [operand_write,operand_readwrite]) then
+          begin
+            { prevent merging registers with frame/stack pointer, $zero and $at
+              if an instruction writes to the register }
+            supreg:=getsupreg(taicpu(p).oper[0]^.reg);
+            add_edge(supreg,RS_STACK_POINTER_REG);
+            add_edge(supreg,RS_FRAME_POINTER_REG);
+            add_edge(supreg,RS_R0);
+            add_edge(supreg,RS_R1);
+          end;
+      end;
+
+
 end.
 end.

+ 6 - 3
compiler/rgobj.pas

@@ -2134,9 +2134,12 @@ unit rgobj;
         if not spilled then
         if not spilled then
           exit;
           exit;
 
 
-{$ifdef x86}
+{$if defined(x86) or defined(mips)}
         { Try replacing the register with the spilltemp. This is useful only
         { Try replacing the register with the spilltemp. This is useful only
-          for the i386,x86_64 that support memory locations for several instructions }
+          for the i386,x86_64 that support memory locations for several instructions
+
+          For non-x86 it is nevertheless possible to replace moves to/from the register
+          with loads/stores to spilltemp (Sergei) }
         for counter := 0 to pred(regindex) do
         for counter := 0 to pred(regindex) do
           with regs[counter] do
           with regs[counter] do
             begin
             begin
@@ -2146,7 +2149,7 @@ unit rgobj;
                     mustbespilled:=false;
                     mustbespilled:=false;
                 end;
                 end;
             end;
             end;
-{$endif x86}
+{$endif defined(x86) or defined(mips)}
 
 
         {
         {
           There are registers that need are spilled. We generate the
           There are registers that need are spilled. We generate the