소스 검색

Procedure-saved registers are now recorded for peephole optimizers to use

J. Gareth "Curious Kit" Moreton 3 년 전
부모
커밋
30166f8eb7
3개의 변경된 파일33개의 추가작업 그리고 12개의 파일을 삭제
  1. 20 10
      compiler/cgobj.pas
  2. 5 0
      compiler/procinfo.pas
  3. 8 2
      compiler/x86/aoptx86.pas

+ 20 - 10
compiler/cgobj.pas

@@ -2698,6 +2698,7 @@ implementation
         for r:=low(regs_to_save_int) to high(regs_to_save_int) do
           if regs_to_save_int[r] in rg[R_INTREGISTER].used_in_proc then
             inc(size,sizeof(aint));
+
         if uses_registers(R_ADDRESSREGISTER) then
           for r:=low(regs_to_save_int) to high(regs_to_save_int) do
             if regs_to_save_int[r] in rg[R_ADDRESSREGISTER].used_in_proc then
@@ -2713,7 +2714,9 @@ implementation
 
             for r:=low(regs_to_save_mm) to high(regs_to_save_mm) do
               if regs_to_save_mm[r] in rg[R_MMREGISTER].used_in_proc then
-                inc(size,tcgsize2size[OS_VECTOR]);
+                begin
+                  inc(size,tcgsize2size[OS_VECTOR]);
+                end;
           end;
 
         if size>0 then
@@ -2732,17 +2735,22 @@ implementation
                   end;
                 include(rg[R_INTREGISTER].preserved_by_proc,regs_to_save_int[r]);
               end;
+            current_procinfo.saved_regs_int := rg[R_INTREGISTER].preserved_by_proc;
 
             if uses_registers(R_ADDRESSREGISTER) then
-              for r:=low(regs_to_save_address) to high(regs_to_save_address) do
-                begin
-                  if regs_to_save_address[r] in rg[R_ADDRESSREGISTER].used_in_proc then
-                    begin
-                      a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_ADDRESSREGISTER,regs_to_save_address[r],R_SUBWHOLE),href);
-                      inc(href.offset,sizeof(aint));
-                    end;
-                  include(rg[R_ADDRESSREGISTER].preserved_by_proc,regs_to_save_address[r]);
-                end;
+              begin
+                for r:=low(regs_to_save_address) to high(regs_to_save_address) do
+                  begin
+                    if regs_to_save_address[r] in rg[R_ADDRESSREGISTER].used_in_proc then
+                      begin
+                        a_load_reg_ref(list,OS_ADDR,OS_ADDR,newreg(R_ADDRESSREGISTER,regs_to_save_address[r],R_SUBWHOLE),href);
+                        inc(href.offset,sizeof(aint));
+                      end;
+                    include(rg[R_ADDRESSREGISTER].preserved_by_proc,regs_to_save_address[r]);
+                  end;
+
+                current_procinfo.saved_regs_mm := rg[R_MMREGISTER].preserved_by_proc;
+              end;
 
             if uses_registers(R_MMREGISTER) then
               begin
@@ -2765,6 +2773,8 @@ implementation
                         include(rg[R_MMREGISTER].preserved_by_proc,regs_to_save_mm[r]);
                       end;
                   end;
+
+                current_procinfo.saved_regs_mm := rg[R_MMREGISTER].preserved_by_proc;
               end;
           end;
       end;

+ 5 - 0
compiler/procinfo.pas

@@ -145,6 +145,11 @@ unit procinfo;
           localrefsyms : tfpobjectlist;
           localrefdefs : tfpobjectlist;
 
+          { Registers saved by the current procedure - useful for peephole optimizers }
+          saved_regs_int,
+          saved_regs_address,
+          saved_regs_mm: TCPURegisterSet;
+
           constructor create(aparent:tprocinfo);virtual;
           destructor destroy;override;
 

+ 8 - 2
compiler/x86/aoptx86.pas

@@ -1070,7 +1070,10 @@ unit aoptx86;
       begin
         { TODO: Currently, only the volatile registers are checked - can this be extended to use any register the procedure has preserved? }
         Result := NR_NO;
-        RegSet := paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
+        RegSet :=
+          paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption) +
+          current_procinfo.saved_regs_int;
+
         for CurrentSuperReg in RegSet do
           begin
             CurrentReg := newreg(R_INTREGISTER, TSuperRegister(CurrentSuperReg), RegSize);
@@ -1141,7 +1144,10 @@ unit aoptx86;
       begin
         { TODO: Currently, only the volatile registers are checked - can this be extended to use any register the procedure has preserved? }
         Result := NR_NO;
-        RegSet := paramanager.get_volatile_registers_mm(current_procinfo.procdef.proccalloption);
+        RegSet :=
+          paramanager.get_volatile_registers_mm(current_procinfo.procdef.proccalloption) +
+          current_procinfo.saved_regs_mm;
+
         for CurrentSuperReg in RegSet do
           begin
             CurrentReg := newreg(R_MMREGISTER, TSuperRegister(CurrentSuperReg), RegSize);