MIPS procinfo improvements:

- Removed TMIPSProcInfo.needs_frame_pointer, it duplicates pi_needs_stackframe flag.
- Don't save RA for leaf procedures.
* GP is caller-saved register, it does not need saving/restoring as nonvolatile registers. Handle its restore position as a "normal" temp, whose offset is known before secondpass. This allows to handle PIC calls without involving GAS macro processing.

git-svn-id: trunk@23885 -
This commit is contained in:
sergei 2013-03-17 08:43:39 +00:00
parent d5985b4f0e
commit 1c652eb8f9
3 changed files with 52 additions and 51 deletions

View File

@ -1203,7 +1203,7 @@ begin
if nostackframe then if nostackframe then
exit; exit;
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then if (pi_needs_stackframe in current_procinfo.flags) then
a_reg_alloc(list,NR_FRAME_POINTER_REG); a_reg_alloc(list,NR_FRAME_POINTER_REG);
helplist:=TAsmList.Create; helplist:=TAsmList.Create;
@ -1236,15 +1236,12 @@ begin
mask:=0; mask:=0;
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart; nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall); saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
include(saveregs,RS_R31); if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then include(saveregs,RS_R31);
if (pi_needs_stackframe in current_procinfo.flags) then
include(saveregs,RS_FRAME_POINTER_REG); include(saveregs,RS_FRAME_POINTER_REG);
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
include(saveregs,RS_GP);
lastintoffset:=LocalSize; lastintoffset:=LocalSize;
framesave:=nil; framesave:=nil;
gp_save:=nil;
ra_save:=nil; ra_save:=nil;
for reg:=RS_R1 to RS_R31 do for reg:=RS_R1 to RS_R31 do
@ -1258,10 +1255,6 @@ begin
framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href) framesave:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
else if (reg=RS_R31) then else if (reg=RS_R31) then
ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href) ra_save:=taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)
else if (reg=RS_GP) and
(cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
gp_save:=taicpu.op_const(A_P_CPRESTORE,nextoffset)
else else
helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href)); helplist.concat(taicpu.op_reg_ref(A_SW,newreg(R_INTREGISTER,reg,R_SUBWHOLE),href));
inc(nextoffset,4); inc(nextoffset,4);
@ -1311,10 +1304,11 @@ begin
even use AT register, which is why we use R9 instead of AT here for -LocalSize } even use AT register, which is why we use R9 instead of AT here for -LocalSize }
list.concat(Taicpu.op_none(A_P_SET_NOMACRO)); list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
end; end;
if assigned(gp_save) then if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
begin begin
list.concat(Taicpu.op_none(A_P_SET_MACRO)); list.concat(Taicpu.op_none(A_P_SET_MACRO));
list.concat(gp_save); list.concat(Taicpu.op_const(A_P_CPRESTORE,TMIPSProcinfo(current_procinfo).save_gp_ref.offset));
list.concat(Taicpu.op_none(A_P_SET_NOMACRO)); list.concat(Taicpu.op_none(A_P_SET_NOMACRO));
end; end;
@ -1338,11 +1332,6 @@ begin
list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href)); list.concat(taicpu.op_reg_ref(A_SW, newreg(R_INTREGISTER,reg,R_SUBWHOLE), href));
end; end;
end; end;
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in current_procinfo.flags) then
begin
current_procinfo.got := NR_GP;
end;
list.concatList(helplist); list.concatList(helplist);
helplist.Free; helplist.Free;
end; end;
@ -1382,12 +1371,11 @@ begin
nextoffset:=TMIPSProcInfo(current_procinfo).intregstart; nextoffset:=TMIPSProcInfo(current_procinfo).intregstart;
saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall); saveregs:=rg[R_INTREGISTER].used_in_proc-paramanager.get_volatile_registers_int(pocall_stdcall);
include(saveregs,RS_R31); if (current_procinfo.flags*[pi_do_call,pi_is_assembler]<>[]) then
if (TMIPSProcinfo(current_procinfo).needs_frame_pointer) or (pi_needs_stackframe in current_procinfo.flags) then include(saveregs,RS_R31);
if (pi_needs_stackframe in current_procinfo.flags) then
include(saveregs,RS_FRAME_POINTER_REG); include(saveregs,RS_FRAME_POINTER_REG);
if (cs_create_pic in current_settings.moduleswitches) and // GP does not need to be restored on exit
(pi_needs_got in current_procinfo.flags) then
include(saveregs,RS_GP);
for reg:=RS_R1 to RS_R31 do for reg:=RS_R1 to RS_R31 do
begin begin
if reg in saveregs then if reg in saveregs then

View File

@ -450,7 +450,7 @@ implementation
begin begin
paraloc^.reference.index := NR_FRAME_POINTER_REG; paraloc^.reference.index := NR_FRAME_POINTER_REG;
if assigned(current_procinfo) then if assigned(current_procinfo) then
TMIPSProcinfo(current_procinfo).needs_frame_pointer := true; include(current_procinfo.flags,pi_needs_stackframe);
end; end;
paraloc^.reference.offset:=intparasize; paraloc^.reference.offset:=intparasize;

View File

@ -29,7 +29,7 @@ interface
cutils, cutils,
globtype,symdef, globtype,symdef,
procinfo,cpuinfo,cpupara, procinfo,cpuinfo,cpupara,
psub; psub,aasmdata,cgutils;
type type
@ -40,17 +40,18 @@ interface
floatregstart : aint; floatregstart : aint;
intregssave, intregssave,
floatregssave : byte; floatregssave : byte;
needs_frame_pointer: boolean;
register_used : tparasupregsused; register_used : tparasupregsused;
register_size : tparasupregsize; register_size : tparasupregsize;
register_name : tparasuprename; register_name : tparasuprename;
register_offset : tparasupregsoffset; register_offset : tparasupregsoffset;
computed_local_size : longint; computed_local_size : longint;
save_gp_ref: treference;
//intparareg, //intparareg,
//parasize : longint; //parasize : longint;
constructor create(aparent:tprocinfo);override; constructor create(aparent:tprocinfo);override;
function calc_stackframe_size:longint;override; function calc_stackframe_size:longint;override;
procedure set_first_temp_offset;override; procedure set_first_temp_offset;override;
procedure allocate_got_register(list:tasmlist);override;
end; end;
{ Used by Stabs debug info generator } { Used by Stabs debug info generator }
@ -61,7 +62,7 @@ implementation
uses uses
systems,globals,verbose, systems,globals,verbose,
cpubase,cgbase,cgutils,cgobj, cpubase,cgbase,cgobj,
tgobj,paramgr,symconst; tgobj,paramgr,symconst;
constructor TMIPSProcInfo.create(aparent: tprocinfo); constructor TMIPSProcInfo.create(aparent: tprocinfo);
@ -69,9 +70,9 @@ implementation
i : longint; i : longint;
begin begin
inherited create(aparent); inherited create(aparent);
{ will call _mcount if profiling } { if (cs_generate_stackframes in current_settings.localswitches) or
if cs_profile in current_settings.moduleswitches then not (cs_opt_stackframe in current_settings.optimizerswitches) then }
include(flags,pi_do_call); include(flags,pi_needs_stackframe);
for i:=low(tparasupregs) to high(tparasupregs) do for i:=low(tparasupregs) to high(tparasupregs) do
begin begin
register_used[i]:=false; register_used[i]:=false;
@ -80,9 +81,7 @@ implementation
register_offset[i]:=-1; register_offset[i]:=-1;
end; end;
floatregssave:=12; { f20-f31 } floatregssave:=12; { f20-f31 }
intregssave:=12; { r16-r23,r28-r31 } intregssave:=10; { r16-r23,r30,r31 }
{ for testing }
needs_frame_pointer := true;//false;
computed_local_size:=-1; computed_local_size:=-1;
{ pi_needs_got is not yet set correctly { pi_needs_got is not yet set correctly
so include it always if creating PIC code } so include it always if creating PIC code }
@ -98,28 +97,42 @@ implementation
procedure TMIPSProcInfo.set_first_temp_offset; procedure TMIPSProcInfo.set_first_temp_offset;
begin begin
{ MIPS stack frame is always "optimized" }
framepointer:=NR_STACK_POINTER_REG;
tg.direction:=1;
{ We allocate enough space to save all registers because we can't determine { We allocate enough space to save all registers because we can't determine
the necessary space because the used registers aren't known before the necessary space because the used registers aren't known before
secondpass is run. } secondpass is run. }
if tg.direction = -1 then
tg.setfirsttemp(0)
else
begin
{ Fixes the case when there are calls done by low-level means
(cg.a_call_name) but no child callnode. !!For assembler procedure
there is no clean way to determine what it calls, unless it is
also declared as nostackframe and everything is managed manually. }
if (pi_do_call in flags) or
((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
if not (po_nostackframe in procdef.procoptions) then { will call _mcount if profiling }
tg.setfirsttemp(Align(maxpushedparasize+ if (cs_profile in current_settings.moduleswitches) and
floatregssave*sizeof(aint)+intregssave*sizeof(aint) not (po_nostackframe in procdef.procoptions) then
,max(current_settings.alignment.localalignmin,8))) include(flags,pi_do_call);
else
tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8))); { Fixes the case when there are calls done by low-level means
end; (cg.a_call_name) but no child callnode. !!For assembler procedure
there is no clean way to determine what it calls, unless it is
also declared as nostackframe and everything is managed manually. }
if (pi_do_call in flags) or
((pi_is_assembler in flags) and not (po_nostackframe in procdef.procoptions)) then
allocate_push_parasize(mips_nb_used_registers*sizeof(aint));
if not (po_nostackframe in procdef.procoptions) then
tg.setfirsttemp(Align(maxpushedparasize+
floatregssave*sizeof(aint)+intregssave*sizeof(aint)
,max(current_settings.alignment.localalignmin,8)))
else
tg.setfirsttemp(align(maxpushedparasize,max(current_settings.alignment.localalignmin,8)));
end;
procedure TMIPSProcInfo.allocate_got_register(list:tasmlist);
begin
if (cs_create_pic in current_settings.moduleswitches) and
(pi_needs_got in flags) and
not (po_nostackframe in procdef.procoptions) then
tg.gettemp(list,sizeof(aint),sizeof(aint),tt_noreuse,save_gp_ref);
end; end;