소스 검색

* stack frame optimizations

git-svn-id: trunk@2172 -
tom_at_work 19 년 전
부모
커밋
3462426b1d
5개의 변경된 파일63개의 추가작업 그리고 13개의 파일을 삭제
  1. 7 3
      compiler/ncgutil.pas
  2. 38 6
      compiler/powerpc64/cgcpu.pas
  3. 4 0
      compiler/powerpc64/cpubase.pas
  4. 5 2
      compiler/powerpc64/cpupara.pas
  5. 9 2
      compiler/powerpc64/cpupi.pas

+ 7 - 3
compiler/ncgutil.pas

@@ -136,6 +136,9 @@ implementation
 {$ifdef powerpc}
     , cpupi
 {$endif}
+{$ifdef powerpc64}
+    , cpupi
+{$endif}
 ;
 
 
@@ -1346,10 +1349,10 @@ implementation
             case paraloc.loc of
               LOC_REGISTER :
                 begin
-                  {$IFDEF CPUPOWERPC64}
+                  {$IFDEF POWERPC64}
                   if (paraloc.shiftval <> 0) then
                     cg.a_op_const_reg_reg(list, OP_SHL, OS_INT, paraloc.shiftval, paraloc.register, paraloc.register);
-                  {$ENDIF CPUPOWERPC64}
+                  {$ENDIF POWERPC64}
                   cg.a_load_reg_ref(list,paraloc.size,paraloc.size,paraloc.register,ref);
                 end;
               LOC_MMREGISTER :
@@ -1576,7 +1579,8 @@ implementation
 {$ifdef powerpc64}
         { unget the register that contains the stack pointer before the procedure entry, }
         { which is used to access the parameters in their original callee-side location  }
-        cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
+        if (tppcprocinfo(current_procinfo).needs_frame_pointer) then
+          cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
 {$endif powerpc64}
       end;
 

+ 38 - 6
compiler/powerpc64/cgcpu.pas

@@ -129,6 +129,8 @@ type
     { the sum of part of the original reference                       }
     function fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
 
+    function load_got_symbol(list : taasmoutput; symbol : string) : tregister;
+    
     { returns whether a reference can be used immediately in a powerpc }
     { instruction                                                      }
     function issimpleref(const ref: treference): boolean;
@@ -1304,7 +1306,8 @@ begin
   { determine whether we need to save the link register }
   needslinkreg := 
     ((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or 
-    ((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0)));
+    ((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0))) or
+    ([cs_lineinfo, cs_debuginfo] * aktmoduleswitches <> []);
 
   a_reg_alloc(list, NR_STACK_POINTER_REG);
   a_reg_alloc(list, NR_R0);
@@ -1316,7 +1319,7 @@ begin
   save_standard_registers;
 
   { save old stack frame pointer }
-  if (localsize > 0) then begin
+  if (tppcprocinfo(current_procinfo).needs_frame_pointer) then begin
     a_reg_alloc(list, NR_OLD_STACK_POINTER_REG);
     list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
   end;
@@ -1441,7 +1444,8 @@ begin
   { determine whether we need to restore the link register }
   needslinkreg := 
     ((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or
-    ((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0)));
+    ((cs_littlesize in aktglobalswitches) and ((fprcount > 0) or (gprcount > 0))) or
+    ([cs_lineinfo, cs_debuginfo] * aktmoduleswitches <> []);
 
   { calculate stack frame }
   localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
@@ -1819,13 +1823,41 @@ begin
     (ref.offset = 0)));
 end;
 
+function tcgppc.load_got_symbol(list: taasmoutput; symbol : string) : tregister;
+var
+  l: tasmsymbol;
+  ref: treference;
+begin
+  l:=objectlibrary.getasmsymbol(symbol+'$got');
+  if not(assigned(l)) then begin
+    l:=objectlibrary.newasmsymbol(symbol+'$got',AB_COMMON,AT_DATA);
+    asmlist[al_picdata].concat(tai_symbol.create(l,0));
+    asmlist[al_picdata].concat(tai_const.create_indirect_sym(objectlibrary.newasmsymbol(symbol,AB_EXTERNAL,AT_DATA)));
+    asmlist[al_picdata].concat(tai_const.create_32bit(0));
+  end;
+  reference_reset_symbol(ref,l,0);
+  ref.base := NR_R2;
+  result := cg.rg[R_INTREGISTER].getregister(list, R_SUBWHOLE);
+  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,ref,result);
+end;
+
 function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
 var
-  tmpreg: tregister;
-  needsAlign : boolean;
+  tmpreg: tregister; 
+  name : string;
 begin
   result := false;
-  needsAlign := size in [OS_S32, OS_64, OS_S64];
+  if (cs_create_pic in aktmoduleswitches) and (assigned(ref.symbol)) and (ref.symbol.defbind = AB_EXTERNAL) then begin
+    if (length(name) > 100) then internalerror(123456);
+    tmpreg := load_got_symbol(list, ref.symbol.name);
+    if (ref.base = NR_NO) then
+      ref.base := tmpreg
+    else if (ref.index = NR_NO) then
+      ref.index := tmpreg
+    else
+      list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.base,tmpreg));
+    ref.symbol := nil;    
+  end;
 
   if (ref.base = NR_NO) then  begin
     ref.base := ref.index;

+ 4 - 0
compiler/powerpc64/cpubase.pas

@@ -370,6 +370,10 @@ const
 
   ELF_STACK_ALIGN = 16;
 
+  { the size of the "red zone" which must not be changed by asynchronous calls
+   in the stack frame and can be used for storing temps }
+  RED_ZONE_SIZE = 288;
+
   {*****************************************************************************
                                     Helpers
   *****************************************************************************}

+ 5 - 2
compiler/powerpc64/cpupara.pas

@@ -62,7 +62,8 @@ implementation
 uses
   verbose, systems,
   defutil,
-  cgutils;
+  cgutils,
+  procinfo, cpupi;
 
 function tppcparamanager.get_volatile_registers_int(calloption:
   tproccalloption): tcpuregisterset;
@@ -417,9 +418,11 @@ begin
         paraloc^.size := int_cgsize(paralen);
         if (side = callerside) then
           paraloc^.reference.index := NR_STACK_POINTER_REG
-        else
+        else begin
           { during procedure entry, NR_OLD_STACK_POINTER_REG contains the old stack pointer }
           paraloc^.reference.index := NR_OLD_STACK_POINTER_REG;
+          tppcprocinfo(current_procinfo).needs_frame_pointer := true;
+        end;
         paraloc^.reference.offset := stack_offset;
 
         { align temp contents to next register size }

+ 9 - 2
compiler/powerpc64/cpupi.pas

@@ -40,6 +40,8 @@ type
     procedure allocate_push_parasize(size: longint); override;
     function calc_stackframe_size: longint; override;
     function calc_stackframe_size(numgpr, numfpr : longint): longint;
+
+    needs_frame_pointer : boolean;
   end;
 
 implementation
@@ -57,6 +59,7 @@ constructor tppcprocinfo.create(aparent: tprocinfo);
 begin
   inherited create(aparent);
   maxpushedparasize := 0;
+  needs_frame_pointer := false;
 end;
 
 procedure tppcprocinfo.set_first_temp_offset;
@@ -100,8 +103,12 @@ begin
   { more or less copied from cgcpu.pas/g_stackframe_entry }
   if not (po_assembler in procdef.procoptions) then begin
     // no VMX support
-    result := align(align(numgpr * tcgsize2size[OS_INT] +
-      numfpr * tcgsize2size[OS_FLOAT], ELF_STACK_ALIGN) + tg.lasttemp, ELF_STACK_ALIGN);
+    result := align(numgpr * tcgsize2size[OS_INT] +
+        numfpr * tcgsize2size[OS_FLOAT], ELF_STACK_ALIGN);
+
+    if not ((not (pi_do_call in flags)) and (tg.lasttemp = tg.firsttemp) and
+      (result <= RED_ZONE_SIZE)) then
+      result := align(result + tg.lasttemp, ELF_STACK_ALIGN);
   end else
     result := align(tg.lasttemp, ELF_STACK_ALIGN);
 end;