mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-17 03:19:33 +02:00
+ 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:
parent
0af7a6f92c
commit
8b8553991a
@ -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}],
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user