Browse Source

+ implemented TCpuPreRegallocScheduler.SwapRegLive and make use of it to be able to reschedule instructions before register allocation

git-svn-id: trunk@22110 -
florian 13 years ago
parent
commit
a693fe9fb7
1 changed files with 91 additions and 4 deletions
  1. 91 4
      compiler/arm/aoptcpu.pas

+ 91 - 4
compiler/arm/aoptcpu.pas

@@ -21,14 +21,15 @@
  ****************************************************************************
  ****************************************************************************
 }
 }
 
 
-
 Unit aoptcpu;
 Unit aoptcpu;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
 
 
+{ $define DEBUG_PREREGSCHEDULER}
+
 Interface
 Interface
 
 
-uses cgbase, cpubase, aasmtai, aopt, aoptcpub, aoptobj;
+uses cgbase, cpubase, aasmtai, aasmcpu,aopt, aoptcpub, aoptobj;
 
 
 Type
 Type
 
 
@@ -44,8 +45,11 @@ Type
                                      var AllUsedRegs: TAllUsedRegs): Boolean;
                                      var AllUsedRegs: TAllUsedRegs): Boolean;
   End;
   End;
 
 
+  { TCpuPreRegallocScheduler }
+
   TCpuPreRegallocScheduler = class(TAsmOptimizer)
   TCpuPreRegallocScheduler = class(TAsmOptimizer)
     function PeepHoleOptPass1Cpu(var p: tai): boolean;override;
     function PeepHoleOptPass1Cpu(var p: tai): boolean;override;
+    procedure SwapRegLive(p, hp1: taicpu);
   end;
   end;
 
 
   TCpuThumb2AsmOptimizer = class(TCpuAsmOptimizer)
   TCpuThumb2AsmOptimizer = class(TCpuAsmOptimizer)
@@ -59,8 +63,8 @@ Implementation
     cutils,verbose,globals,
     cutils,verbose,globals,
     systems,
     systems,
     cpuinfo,
     cpuinfo,
-    cgutils,procinfo,
-    aasmbase,aasmdata,aasmcpu;
+    cgobj,cgutils,procinfo,
+    aasmbase,aasmdata;
 
 
   function CanBeCond(p : tai) : boolean;
   function CanBeCond(p : tai) : boolean;
     begin
     begin
@@ -1112,6 +1116,86 @@ Implementation
     opcode_could_mem_write = [A_B,A_BL,A_BLX,A_BKPT,A_BX,A_STR,A_STRB,A_STRBT,
     opcode_could_mem_write = [A_B,A_BL,A_BLX,A_BKPT,A_BX,A_STR,A_STRB,A_STRBT,
                               A_STRH,A_STRT,A_STF,A_SFM,A_STM,A_FSTS,A_FSTD];
                               A_STRH,A_STRT,A_STF,A_SFM,A_STM,A_FSTS,A_FSTD];
 
 
+
+  { adjust the register live information when swapping the two instructions p and hp1,
+    they must follow one after the other }
+  procedure TCpuPreRegallocScheduler.SwapRegLive(p,hp1 : taicpu);
+
+    procedure CheckLiveEnd(reg : tregister);
+      var
+        supreg : TSuperRegister;
+        regtype : TRegisterType;
+      begin
+        if reg=NR_NO then
+          exit;
+        regtype:=getregtype(reg);
+        supreg:=getsupreg(reg);
+        if (cg.rg[regtype].live_end[supreg]=hp1) and
+          RegInInstruction(reg,p) then
+          cg.rg[regtype].live_end[supreg]:=p;
+      end;
+
+
+    procedure CheckLiveStart(reg : TRegister);
+      var
+        supreg : TSuperRegister;
+        regtype : TRegisterType;
+      begin
+        if reg=NR_NO then
+          exit;
+        regtype:=getregtype(reg);
+        supreg:=getsupreg(reg);
+        if (cg.rg[regtype].live_start[supreg]=p) and
+          RegInInstruction(reg,hp1) then
+         cg.rg[regtype].live_start[supreg]:=hp1;
+      end;
+
+    var
+      i : longint;
+      r : TSuperRegister;
+    begin
+      { assumption: p is directly followed by hp1 }
+
+      { if live of any reg used by p starts at p and hp1 uses this register then
+        set live start to hp1 }
+      for i:=0 to p.ops-1 do
+        case p.oper[i]^.typ of
+          Top_Reg:
+            CheckLiveStart(p.oper[i]^.reg);
+          Top_Ref:
+            begin
+              CheckLiveStart(p.oper[i]^.ref^.base);
+              CheckLiveStart(p.oper[i]^.ref^.base);
+            end;
+          Top_Shifterop:
+            CheckLiveStart(p.oper[i]^.shifterop^.rs);
+          Top_RegSet:
+            for r:=RS_R0 to RS_R15 do
+               if r in p.oper[i]^.regset^ then
+                 CheckLiveStart(newreg(R_INTREGISTER,r,R_SUBWHOLE));
+        end;
+
+      { if live of any reg used by hp1 ends at hp1 and p uses this register then
+        set live end to p }
+      for i:=0 to hp1.ops-1 do
+        case hp1.oper[i]^.typ of
+          Top_Reg:
+            CheckLiveEnd(hp1.oper[i]^.reg);
+          Top_Ref:
+            begin
+              CheckLiveEnd(hp1.oper[i]^.ref^.base);
+              CheckLiveEnd(hp1.oper[i]^.ref^.index);
+            end;
+          Top_Shifterop:
+            CheckLiveStart(p.oper[i]^.shifterop^.rs);
+          Top_RegSet:
+            for r:=RS_R0 to RS_R15 do
+               if r in p.oper[i]^.regset^ then
+                 CheckLiveEnd(newreg(R_INTREGISTER,r,R_SUBWHOLE));
+        end;
+    end;
+
+
   function TCpuPreRegallocScheduler.PeepHoleOptPass1Cpu(var p: tai): boolean;
   function TCpuPreRegallocScheduler.PeepHoleOptPass1Cpu(var p: tai): boolean;
   { TODO : schedule also forward }
   { TODO : schedule also forward }
   { TODO : schedule distance > 1 }
   { TODO : schedule distance > 1 }
@@ -1189,7 +1273,10 @@ Implementation
                   else
                   else
                   hp3:=tai(hp3.Previous);
                   hp3:=tai(hp3.Previous);
                 end;
                 end;
+
               list.Concat(p);
               list.Concat(p);
+              SwapRegLive(taicpu(p),taicpu(hp1));
+
               { after the instruction? }
               { after the instruction? }
               while assigned(hp5) and (hp5.typ<>ait_instruction) do
               while assigned(hp5) and (hp5.typ<>ait_instruction) do
                 begin
                 begin