* stack frame optimizations

git-svn-id: trunk@2172 -
This commit is contained in:
tom_at_work 2006-01-04 23:27:40 +00:00
parent 21d51d8815
commit 3462426b1d
5 changed files with 63 additions and 13 deletions

View File

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

View File

@ -129,6 +129,8 @@ type
{ the sum of part of the original reference } { the sum of part of the original reference }
function fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean; 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 } { returns whether a reference can be used immediately in a powerpc }
{ instruction } { instruction }
function issimpleref(const ref: treference): boolean; function issimpleref(const ref: treference): boolean;
@ -1304,7 +1306,8 @@ begin
{ determine whether we need to save the link register } { determine whether we need to save the link register }
needslinkreg := needslinkreg :=
((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or ((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_STACK_POINTER_REG);
a_reg_alloc(list, NR_R0); a_reg_alloc(list, NR_R0);
@ -1316,7 +1319,7 @@ begin
save_standard_registers; save_standard_registers;
{ save old stack frame pointer } { 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); 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)); list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG));
end; end;
@ -1441,7 +1444,8 @@ begin
{ determine whether we need to restore the link register } { determine whether we need to restore the link register }
needslinkreg := needslinkreg :=
((not (po_assembler in current_procinfo.procdef.procoptions)) and (pi_do_call in current_procinfo.flags)) or ((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 } { calculate stack frame }
localsize := tppcprocinfo(current_procinfo).calc_stackframe_size( localsize := tppcprocinfo(current_procinfo).calc_stackframe_size(
@ -1819,13 +1823,41 @@ begin
(ref.offset = 0))); (ref.offset = 0)));
end; 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; function tcgppc.fixref(list: taasmoutput; var ref: treference; const size : TCgsize): boolean;
var var
tmpreg: tregister; tmpreg: tregister;
needsAlign : boolean; name : string;
begin begin
result := false; 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 if (ref.base = NR_NO) then begin
ref.base := ref.index; ref.base := ref.index;

View File

@ -370,6 +370,10 @@ const
ELF_STACK_ALIGN = 16; 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 Helpers
*****************************************************************************} *****************************************************************************}

View File

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

View File

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