+ MIPS: prevent coalescing written-to registers with $sp,$fp,$zero and $at.

+ Implemented subset of "spill replace" functionality, replacing moves from/to spilled registers with loads/stores to spill locations. This helps to reduce amount of instructions.

git-svn-id: trunk@24900 -
This commit is contained in:
sergei 2013-06-15 04:04:08 +00:00
parent 0af7a6f92c
commit 8b8553991a
3 changed files with 66 additions and 5 deletions

View File

@ -402,14 +402,14 @@ begin
(pi_needs_got in current_procinfo.flags) then
begin
current_procinfo.got := NR_GP;
rg[R_INTREGISTER] := Trgcpu.Create(R_INTREGISTER, R_SUBD,
rg[R_INTREGISTER] := Trgintcpu.Create(R_INTREGISTER, R_SUBD,
[RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],
first_int_imreg, []);
end
else
rg[R_INTREGISTER] := trgcpu.Create(R_INTREGISTER, R_SUBD,
rg[R_INTREGISTER] := trgintcpu.Create(R_INTREGISTER, R_SUBD,
[RS_R2,RS_R3,RS_R4,RS_R5,RS_R6,RS_R7,RS_R8,RS_R9,
RS_R10,RS_R11,RS_R12,RS_R13,RS_R14,RS_R15,RS_R16,RS_R17,RS_R18,RS_R19,
RS_R20,RS_R21,RS_R22,RS_R23,RS_R24{,RS_R25}],

View File

@ -38,8 +38,12 @@ unit rgcpu;
function get_spill_subreg(r : tregister) : tsubregister;override;
procedure do_spill_read(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
procedure do_spill_written(list:tasmlist;pos:tai;const spilltemp:treference;tempreg:tregister);override;
function do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;override;
end;
trgintcpu=class(trgcpu)
procedure add_cpu_interferences(p:tai);override;
end;
implementation
@ -152,4 +156,58 @@ implementation
inherited do_spill_written(list,pos,spilltemp,tempreg);
end;
function trgcpu.do_spill_replace(list:TAsmList;instr:taicpu;orgreg:tsuperregister;const spilltemp:treference):boolean;
begin
result:=false;
{ Replace 'move orgreg,src' with 'sw src,spilltemp'
and 'move dst,orgreg' with 'lw dst,spilltemp' }
{ TODO: A_MOV_S and A_MOV_D for float registers are also replaceable }
if (instr.opcode<>A_MOVE) or (abs(spilltemp.offset)>32767) then
exit;
if (instr.ops<>2) or
(instr.oper[0]^.typ<>top_reg) or
(instr.oper[1]^.typ<>top_reg) or
(getregtype(instr.oper[0]^.reg)<>regtype) or
(getregtype(instr.oper[1]^.reg)<>regtype) then
InternalError(2013061001);
if get_alias(getsupreg(instr.oper[1]^.reg))=orgreg then
begin
instr.opcode:=A_LW;
end
else if get_alias(getsupreg(instr.oper[0]^.reg))=orgreg then
begin
instr.opcode:=A_SW;
instr.oper[0]^:=instr.oper[1]^;
end
else
InternalError(2013061002);
instr.oper[1]^.typ:=top_ref;
new(instr.oper[1]^.ref);
instr.oper[1]^.ref^:=spilltemp;
result:=true;
end;
procedure trgintcpu.add_cpu_interferences(p: tai);
var
supreg: tsuperregister;
begin
if p.typ<>ait_instruction then
exit;
if (taicpu(p).ops>=1) and (taicpu(p).oper[0]^.typ=top_reg) and
(getregtype(taicpu(p).oper[0]^.reg)=regtype) and
(taicpu(p).spilling_get_operation_type(0) in [operand_write,operand_readwrite]) then
begin
{ prevent merging registers with frame/stack pointer, $zero and $at
if an instruction writes to the register }
supreg:=getsupreg(taicpu(p).oper[0]^.reg);
add_edge(supreg,RS_STACK_POINTER_REG);
add_edge(supreg,RS_FRAME_POINTER_REG);
add_edge(supreg,RS_R0);
add_edge(supreg,RS_R1);
end;
end;
end.

View File

@ -2134,9 +2134,12 @@ unit rgobj;
if not spilled then
exit;
{$ifdef x86}
{$if defined(x86) or defined(mips)}
{ Try replacing the register with the spilltemp. This is useful only
for the i386,x86_64 that support memory locations for several instructions }
for the i386,x86_64 that support memory locations for several instructions
For non-x86 it is nevertheless possible to replace moves to/from the register
with loads/stores to spilltemp (Sergei) }
for counter := 0 to pred(regindex) do
with regs[counter] do
begin
@ -2146,7 +2149,7 @@ unit rgobj;
mustbespilled:=false;
end;
end;
{$endif x86}
{$endif defined(x86) or defined(mips)}
{
There are registers that need are spilled. We generate the