* spilling code rewritten for x86. It now used the generic

spilling routines. Special x86 optimization still needs
    to be added.
  * Spilling fixed when both operands needed to be spilled
  * Cleanup of spilling routine, do_spill_readwritten removed
This commit is contained in:
peter 2004-10-04 20:46:22 +00:00
parent ec720a5800
commit ee3585f56f
8 changed files with 349 additions and 352 deletions

View File

@ -140,7 +140,7 @@ begin
end end
end; end;
else else
for opCount := 1 to MaxCh do for opCount := 1 to maxinschanges do
case InsProp[p.opcode].Ch[opCount] of case InsProp[p.opcode].Ch[opCount] of
Ch_MOp1,CH_WOp1,CH_RWOp1: Ch_MOp1,CH_WOp1,CH_RWOp1:
if not(onlymem) or if not(onlymem) or
@ -904,7 +904,7 @@ begin
begin begin
NoHardCodedRegs := true; NoHardCodedRegs := true;
with InsProp[p.opcode] do with InsProp[p.opcode] do
for chCount := 1 to MaxCh do for chCount := 1 to maxinschanges do
if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then if Ch[chCount] in ([Ch_REAX..Ch_MEDI,Ch_WMemEDI,Ch_All]-[Ch_RESP,Ch_WESP,Ch_RWESP]) then
begin begin
NoHardCodedRegs := false; NoHardCodedRegs := false;
@ -1058,7 +1058,7 @@ begin
{ updateStates(orgReg,newReg,p,false);} { updateStates(orgReg,newReg,p,false);}
doReplaceReadReg := true; doReplaceReadReg := true;
end; end;
for opCount := 1 to MaxCh do for opCount := 1 to maxinschanges do
case InsProp[p.opcode].Ch[opCount] of case InsProp[p.opcode].Ch[opCount] of
Ch_ROp1: Ch_ROp1:
if p.oper[0]^.typ = top_reg then if p.oper[0]^.typ = top_reg then
@ -1901,7 +1901,7 @@ begin
ptaiprop(tai(p).optinfo)^.CanBeRemoved := True; ptaiprop(tai(p).optinfo)^.CanBeRemoved := True;
else else
begin begin
for cnt := 1 to maxch do for cnt := 1 to maxinschanges do
begin begin
case InsProp[taicpu(p).opcode].Ch[cnt] of case InsProp[taicpu(p).opcode].Ch[cnt] of
Ch_ROp1: Ch_ROp1:
@ -2109,7 +2109,14 @@ end.
{ {
$Log$ $Log$
Revision 1.65 2004-09-21 17:25:12 peter Revision 1.66 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.65 2004/09/21 17:25:12 peter
* paraloc branch merged * paraloc branch merged
Revision 1.64.4.1 2004/09/20 19:28:23 peter Revision 1.64.4.1 2004/09/20 19:28:23 peter

View File

@ -725,7 +725,7 @@ begin
RegReadByInstruction := true; RegReadByInstruction := true;
exit exit
end; end;
for opcount := 1 to maxch do for opcount := 1 to maxinschanges do
case insprop[p.opcode].ch[opcount] of case insprop[p.opcode].ch[opcount] of
CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI: CH_REAX..CH_REDI,CH_RWEAX..CH_MEDI:
if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then if supreg = tch2reg(insprop[p.opcode].ch[opcount]) then
@ -791,7 +791,7 @@ begin
(supreg in [RS_EAX,RS_EDX]) (supreg in [RS_EAX,RS_EDX])
else else
begin begin
for opcount := 1 to MaxCh do for opcount := 1 to maxinschanges do
case insprop[p.opcode].Ch[opCount] of case insprop[p.opcode].Ch[opCount] of
CH_REAX..CH_MEDI: CH_REAX..CH_MEDI:
if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then if tch2reg(InsProp[p.opcode].Ch[opCount]) = supreg then
@ -866,7 +866,7 @@ begin
begin begin
Cnt := 1; Cnt := 1;
InstrProp := InsProp[taicpu(p1).OpCode]; InstrProp := InsProp[taicpu(p1).OpCode];
while (Cnt <= MaxCh) and while (Cnt <= maxinschanges) and
(InstrProp.Ch[Cnt] <> Ch_None) and (InstrProp.Ch[Cnt] <> Ch_None) and
not(TmpResult) Do not(TmpResult) Do
begin begin
@ -901,7 +901,7 @@ begin
case p.typ of case p.typ of
ait_instruction: ait_instruction:
begin begin
for l := 1 to MaxCh do for l := 1 to maxinschanges do
if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then if InsProp[taicpu(p).opcode].Ch[l] in [Ch_WFlags,Ch_RWFlags,Ch_All] then
exit; exit;
end; end;
@ -920,7 +920,7 @@ begin
case p.typ of case p.typ of
ait_instruction: ait_instruction:
begin begin
for l := 1 to MaxCh do for l := 1 to maxinschanges do
if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then if InsProp[taicpu(p).opcode].Ch[l] in [Ch_RFlags,Ch_RWFlags,Ch_All] then
exit; exit;
end; end;
@ -2555,7 +2555,7 @@ begin
else else
begin begin
Cnt := 1; Cnt := 1;
while (Cnt <= MaxCh) and while (Cnt <= maxinschanges) and
(InstrProp.Ch[Cnt] <> Ch_None) Do (InstrProp.Ch[Cnt] <> Ch_None) Do
begin begin
case InstrProp.Ch[Cnt] Of case InstrProp.Ch[Cnt] Of
@ -2719,7 +2719,14 @@ end.
{ {
$Log$ $Log$
Revision 1.69 2004-09-26 17:45:30 peter Revision 1.70 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.69 2004/09/26 17:45:30 peter
* simple regvar support, not yet finished * simple regvar support, not yet finished
Revision 1.68 2004/06/20 08:55:31 florian Revision 1.68 2004/06/20 08:55:31 florian

View File

@ -28,49 +28,6 @@ unit optbase;
interface interface
uses cpuinfo, cpubase;
{*****************************************************************************
Opcode propeties (needed for optimizer)
*****************************************************************************}
{$ifndef NOOPT}
Type
{What an instruction can change}
TInsChange = (Ch_None,
{Read from a register}
Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
{write from a register}
Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
{read and write from/to a register}
Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
{modify the contents of a register with the purpose of using
this changed content afterwards (add/sub/..., but e.g. not rep
or movsd)}
Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
Ch_WMemEDI,
Ch_All
);
const
MaxCh = 3; { Max things a instruction can change }
type
TInsProp = packed record
Ch : Array[1..MaxCh] of TInsChange;
end;
const
InsProp : array[tasmop] of TInsProp =
{$i i386prop.inc}
{$endif NOOPT}
implementation implementation
@ -79,7 +36,14 @@ end.
{ {
$Log$ $Log$
Revision 1.3 2004-06-20 08:55:31 florian Revision 1.4 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.3 2004/06/20 08:55:31 florian
* logs truncated * logs truncated
} }

View File

@ -135,8 +135,6 @@ unit rgobj;
trgobj=class trgobj=class
preserved_by_proc : tcpuregisterset; preserved_by_proc : tcpuregisterset;
used_in_proc : tcpuregisterset; used_in_proc : tcpuregisterset;
// is_reg_var : Tsuperregisterset; {old regvars}
// reg_var_loaded:Tsuperregisterset; {old regvars}
constructor create(Aregtype:Tregistertype; constructor create(Aregtype:Tregistertype;
Adefaultsub:Tsubregister; Adefaultsub:Tsubregister;
@ -170,25 +168,12 @@ unit rgobj;
live_registers:Tsuperregisterworklist; live_registers:Tsuperregisterworklist;
{ can be overriden to add cpu specific interferences } { can be overriden to add cpu specific interferences }
procedure add_cpu_interferences(p : tai);virtual; procedure add_cpu_interferences(p : tai);virtual;
function get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai; procedure add_constraints(reg:Tregister);virtual;
procedure forward_allocation(pfrom,pto:Tai);
procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister); procedure getregisterinline(list:Taasmoutput;position:Tai;subreg:Tsubregister;var result:Tregister);
procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister); procedure ungetregisterinline(list:Taasmoutput;position:Tai;r:Tregister);
procedure add_constraints(reg:Tregister);virtual;
function get_spill_subreg(r : tregister) : tsubregister;virtual; function get_spill_subreg(r : tregister) : tsubregister;virtual;
procedure do_spill_read(list:Taasmoutput;instr:Taicpu; procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual;
pos:Tai;regidx:word; procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);virtual;
const spilltemplist:Tspill_temp_list;
const regs:Tspillregsinfo);virtual;
procedure do_spill_written(list:Taasmoutput;instr:Taicpu;
pos:Tai;regidx:word;
const spilltemplist:Tspill_temp_list;
const regs:Tspillregsinfo);virtual;
procedure do_spill_readwritten(list:Taasmoutput;instr:Taicpu;
pos:Tai;regidx:word;
const spilltemplist:Tspill_temp_list;
const regs:Tspillregsinfo);virtual;
function instr_spill_register(list:Taasmoutput; function instr_spill_register(list:Taasmoutput;
instr:taicpu; instr:taicpu;
@ -603,22 +588,12 @@ unit rgobj;
procedure trgobj.add_edges_used(u:Tsuperregister); procedure trgobj.add_edges_used(u:Tsuperregister);
var i:word; var i:word;
v:tsuperregister;
begin begin
with live_registers do with live_registers do
if length>0 then if length>0 then
for i:=0 to length-1 do for i:=0 to length-1 do
begin add_edge(u,get_alias(buf^[i]));
v:=buf^[i];
add_edge(u,v);
{ add also conflicts with all coalesced registers }
while ri_coalesced in reginfo[v].flags do
begin
v:=reginfo[v].alias;
add_edge(u,v);
end;
end;
end; end;
{$ifdef EXTDEBUG} {$ifdef EXTDEBUG}
@ -1638,69 +1613,6 @@ unit rgobj;
end; end;
function trgobj.get_insert_pos(p:Tai;huntfor1,huntfor2,huntfor3:Tsuperregister):Tai;
var
back : Tsuperregisterworklist;
supreg : tsuperregister;
begin
back.copyfrom(live_registers);
result:=p;
while (p<>nil) and (p.typ=ait_regalloc) do
begin
supreg:=getsupreg(Tai_regalloc(p).reg);
{Rewind the register allocation.}
if (Tai_regalloc(p).ratype=ra_alloc) then
live_registers.delete(supreg)
else
begin
live_registers.add(supreg);
if supreg=huntfor1 then
begin
get_insert_pos:=Tai(p.previous);
back.done;
back.copyfrom(live_registers);
end;
if supreg=huntfor2 then
begin
get_insert_pos:=Tai(p.previous);
back.done;
back.copyfrom(live_registers);
end;
if supreg=huntfor3 then
begin
get_insert_pos:=Tai(p.previous);
back.done;
back.copyfrom(live_registers);
end;
end;
p:=Tai(p.previous);
end;
live_registers.done;
live_registers:=back;
end;
procedure trgobj.forward_allocation(pfrom,pto:Tai);
var
p : tai;
begin
{Forward the register allocation again.}
p:=pfrom;
while (p<>pto) do
begin
if p.typ<>ait_regalloc then
internalerror(200305311);
case Tai_regalloc(p).ratype of
ra_alloc :
live_registers.add(getsupreg(Tai_regalloc(p).reg));
ra_dealloc :
live_registers.delete(getsupreg(Tai_regalloc(p).reg));
end;
p:=Tai(p.next);
end;
end;
function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean; function trgobj.spill_registers(list:Taasmoutput;headertai:tai):boolean;
{ Returns true if any help registers have been used } { Returns true if any help registers have been used }
var var
@ -1790,64 +1702,21 @@ unit rgobj;
end; end;
procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu; procedure Trgobj.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
pos:Tai;regidx:word; var
const spilltemplist:Tspill_temp_list; helpins : Tai;
const regs:Tspillregsinfo);
var helpins:Tai;
begin begin
with regs[regidx] do helpins:=spilling_create_load(spilltemp,tempreg);
begin list.insertbefore(helpins,instr);
helpins:=spilling_create_load(spilltemplist[orgreg],tempreg);
if pos=nil then
list.insertafter(helpins,list.first)
else
list.insertafter(helpins,pos.next);
ungetregisterinline(list,instr,tempreg);
forward_allocation(tai(helpins.next),instr);
end;
end; end;
procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu; procedure Trgobj.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
pos:Tai;regidx:word; var
const spilltemplist:Tspill_temp_list; helpins : Tai;
const regs:Tspillregsinfo);
var helpins:Tai;
begin begin
with regs[regidx] do helpins:=spilling_create_store(tempreg,spilltemp);
begin
helpins:=spilling_create_store(tempreg,spilltemplist[orgreg]);
list.insertafter(helpins,instr); list.insertafter(helpins,instr);
ungetregisterinline(list,helpins,tempreg);
end;
end;
procedure Trgobj.do_spill_readwritten(list:Taasmoutput;instr:taicpu;
pos:Tai;regidx:word;
const spilltemplist:Tspill_temp_list;
const regs:Tspillregsinfo);
var helpins1,helpins2:Tai;
begin
with regs[regidx] do
begin
helpins1:=spilling_create_load(spilltemplist[orgreg],tempreg);
if pos=nil then
list.insertafter(helpins1,list.first)
else
list.insertafter(helpins1,pos.next);
helpins2:=spilling_create_store(tempreg,spilltemplist[orgreg]);
list.insertafter(helpins2,instr);
ungetregisterinline(list,helpins2,tempreg);
forward_allocation(tai(helpins1.next),instr);
end;
end; end;
@ -1863,7 +1732,6 @@ unit rgobj;
const spilltemplist:Tspill_temp_list): boolean; const spilltemplist:Tspill_temp_list): boolean;
var var
counter, regindex: longint; counter, regindex: longint;
pos: tai;
regs: tspillregsinfo; regs: tspillregsinfo;
spilled: boolean; spilled: boolean;
@ -1874,7 +1742,7 @@ unit rgobj;
begin begin
tmpindex := regindex; tmpindex := regindex;
supreg:=getsupreg(reg); supreg:=getsupreg(reg);
// did we already encounter this register? { did we already encounter this register? }
for i := 0 to pred(regindex) do for i := 0 to pred(regindex) do
if (regs[i].orgreg = supreg) then if (regs[i].orgreg = supreg) then
begin begin
@ -1887,7 +1755,7 @@ unit rgobj;
regs[tmpindex].spillreg:=reg; regs[tmpindex].spillreg:=reg;
if supregset_in(r,supreg) then if supregset_in(r,supreg) then
begin begin
// add/update info on this register { add/update info on this register }
regs[tmpindex].mustbespilled := true; regs[tmpindex].mustbespilled := true;
case operation of case operation of
operand_read: operand_read:
@ -1916,12 +1784,15 @@ unit rgobj;
if (regs[i].mustbespilled) and if (regs[i].mustbespilled) and
(regs[i].orgreg=supreg) then (regs[i].orgreg=supreg) then
begin begin
reg:=regs[i].tempreg; { Only replace supreg }
setsupreg(reg,getsupreg(regs[i].tempreg));
break; break;
end; end;
end; end;
var
counter2 : longint;
oldlive_registers : tsuperregisterworklist;
begin begin
result := false; result := false;
fillchar(regs,sizeof(regs),0); fillchar(regs,sizeof(regs),0);
@ -1966,6 +1837,14 @@ unit rgobj;
if not spilled then if not spilled then
exit; exit;
{ Add conflicts with all non-spilled registers }
oldlive_registers.copyfrom(live_registers);
for counter2 := 0 to pred(regindex) do
begin
if (not regs[counter2].mustbespilled) then
live_registers.add(get_alias(regs[counter2].orgreg));
end;
{ generate the spilling code } { generate the spilling code }
result := true; result := true;
for counter := 0 to pred(regindex) do for counter := 0 to pred(regindex) do
@ -1973,18 +1852,27 @@ unit rgobj;
begin begin
if mustbespilled then if mustbespilled then
begin begin
pos:=get_insert_pos(Tai(instr.previous),regs[0].orgreg,regs[1].orgreg,regs[2].orgreg); getregisterinline(list,tai(instr.previous),get_spill_subreg(regs[counter].spillreg),tempreg);
getregisterinline(list,pos,get_spill_subreg(regs[counter].spillreg),tempreg);
if regread then if regread then
do_spill_read(list,instr,spilltemplist[orgreg],tempreg);
if regwritten then if regwritten then
do_spill_readwritten(list,instr,pos,counter,spilltemplist,regs) do_spill_written(list,instr,spilltemplist[orgreg],tempreg);
else
do_spill_read(list,instr,pos,counter,spilltemplist,regs)
else
do_spill_written(list,instr,pos,counter,spilltemplist,regs)
end; end;
end; end;
{ Release temp registers after all registers for the instruction are spilled }
for counter := 0 to pred(regindex) do
with regs[counter] do
begin
if mustbespilled then
ungetregisterinline(list,instr,tempreg);
end;
{ restore live registers }
live_registers.done;
live_registers:=oldlive_registers;
{ substitute registers } { substitute registers }
for counter:=0 to instr.ops-1 do for counter:=0 to instr.ops-1 do
with instr.oper[counter]^ do with instr.oper[counter]^ do
@ -2015,7 +1903,14 @@ unit rgobj;
end. end.
{ {
$Log$ $Log$
Revision 1.137 2004-09-26 17:45:30 peter Revision 1.138 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.137 2004/09/26 17:45:30 peter
* simple regvar support, not yet finished * simple regvar support, not yet finished
Revision 1.136 2004/09/25 14:23:54 peter Revision 1.136 2004/09/25 14:23:54 peter

View File

@ -36,12 +36,8 @@ unit rgcpu;
trgcpu=class(trgobj) trgcpu=class(trgobj)
procedure add_constraints(reg:tregister);override; procedure add_constraints(reg:tregister);override;
function get_spill_subreg(r : tregister) : tsubregister;override; function get_spill_subreg(r : tregister) : tsubregister;override;
procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; procedure do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override; procedure do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);override;
procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
end; end;
@ -91,159 +87,89 @@ implementation
end; end;
procedure trgcpu.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; procedure trgcpu.do_spill_read(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
var var
helpins : tai; helpins : tai;
tmpref,ref : treference; tmpref : treference;
helplist : taasmoutput; helplist : taasmoutput;
tmpreg : tregister; hreg : tregister;
begin begin
ref:=spilltemplist[regs[regidx].orgreg]; if abs(spilltemp.offset)>4095 then
if abs(ref.offset)>4095 then
begin begin
helplist:=taasmoutput.create; helplist:=taasmoutput.create;
reference_reset(tmpref);
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then if getregtype(tempreg)=R_INTREGISTER then
getregisterinline(helplist,nil,defaultsub,tmpreg) hreg:=tempreg
else else
tmpreg:=cg.getintregister(helplist,OS_ADDR); hreg:=cg.getintregister(helplist,OS_ADDR);
tmpref.offset:=ref.offset; reference_reset(tmpref);
tmpref.offset:=spilltemp.offset;
tmpref.refaddr:=addr_hi; tmpref.refaddr:=addr_hi;
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg)); helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
tmpref.refaddr:=addr_lo; tmpref.refaddr:=addr_lo;
helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg)); helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
if ref.index<>NR_NO then reference_reset_base(tmpref,hreg,0);
internalerror(200401263);
ref.index:=tmpreg;
ref.offset:=0;
helpins:=spilling_create_load(ref,regs[regidx].tempreg); helpins:=spilling_create_load(spilltemp,tempreg);
helplist.concat(helpins); helplist.concat(helpins);
if pos=nil then list.insertlistbefore(instr,helplist)
list.insertlistafter(list.first,helplist)
else
list.insertlistafter(pos.next,helplist);
helplist.free;
ungetregisterinline(list,helpins,regs[regidx].tempreg);
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
ungetregisterinline(list,helpins,tmpreg);
forward_allocation(tai(helpins.next),instr);
end end
else else
inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs); inherited do_spill_read(list,instr,spilltemp,tempreg);
end; end;
procedure trgcpu.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word; procedure trgcpu.do_spill_written(list:Taasmoutput;instr:taicpu;const spilltemp:treference;const tempreg:tregister);
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
var var
helpins : tai; helpins : tai;
ref,tmpref : treference; tmpref : treference;
helplist : taasmoutput; helplist : taasmoutput;
tmpreg : tregister; hreg : tregister;
begin begin
ref:=spilltemplist[regs[regidx].orgreg]; if abs(spilltemp.offset)>4095 then
if abs(ref.offset)>4095 then
begin begin
helplist:=taasmoutput.create; helplist:=taasmoutput.create;
reference_reset(tmpref);
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then if getregtype(tempreg)=R_INTREGISTER then
getregisterinline(helplist,pos,defaultsub,tmpreg) getregisterinline(helplist,tai(helplist.first),R_SUBWHOLE,hreg)
else else
tmpreg:=cg.getintregister(helplist,OS_ADDR); hreg:=cg.getintregister(helplist,OS_ADDR);
tmpref.offset:=ref.offset; reference_reset(tmpref);
tmpref.offset:=spilltemp.offset;
tmpref.refaddr:=addr_hi; tmpref.refaddr:=addr_hi;
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg)); helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
tmpref.refaddr:=addr_lo; tmpref.refaddr:=addr_lo;
helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg)); helplist.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
if ref.index<>NR_NO then reference_reset_base(tmpref,hreg,0);
internalerror(200401263);
ref.index:=tmpreg;
ref.offset:=0;
helpins:=spilling_create_store(regs[regidx].tempreg,ref); helpins:=spilling_create_store(tempreg,spilltemp);
helplist.concat(helpins); helplist.concat(helpins);
list.insertlistafter(instr,helplist); if getregtype(tempreg)=R_INTREGISTER then
helplist.free; ungetregisterinline(helplist,tai(helplist.last),hreg);
ungetregisterinline(list,helpins,regs[regidx].tempreg); list.insertlistafter(instr,helplist)
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
ungetregisterinline(list,helpins,tmpreg);
end end
else else
inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs); inherited do_spill_written(list,instr,spilltemp,tempreg);
end;
procedure trgcpu.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
var
helpins1, helpins2: tai;
tmpref,ref : treference;
helplist : taasmoutput;
tmpreg : tregister;
begin
ref:=spilltemplist[regs[regidx].orgreg];
if abs(ref.offset)>4095 then
begin
helplist:=taasmoutput.create;
reference_reset(tmpref);
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
getregisterinline(helplist,nil,defaultsub,tmpreg)
else
tmpreg:=cg.getintregister(helplist,OS_ADDR);
tmpref.offset:=ref.offset;
tmpref.refaddr:=addr_hi;
helplist.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
tmpref.refaddr:=addr_lo;
helplist.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
if ref.index<>NR_NO then
internalerror(200401263);
ref.index:=tmpreg;
ref.offset:=0;
helpins1:=spilling_create_load(ref,regs[regidx].tempreg);
helplist.concat(helpins1);
if pos=nil then
list.insertlistafter(list.first,helplist)
else
list.insertlistafter(pos.next,helplist);
helplist.free;
helpins2:=spilling_create_store(regs[regidx].tempreg,ref);
list.insertafter(helpins2,instr);
ungetregisterinline(list,helpins2,regs[regidx].tempreg);
if getregtype(regs[regidx].tempreg)=R_INTREGISTER then
ungetregisterinline(list,helpins2,tmpreg);
forward_allocation(tai(helpins1.next),instr);
end
else
inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs);
end; end;
end. end.
{ {
$Log$ $Log$
Revision 1.27 2004-10-01 17:33:47 peter Revision 1.28 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.27 2004/10/01 17:33:47 peter
* indents * indents
Revision 1.26 2004/09/28 20:19:36 peter Revision 1.26 2004/09/28 20:19:36 peter

View File

@ -130,6 +130,36 @@ interface
instabentries = {$i i386nop.inc} instabentries = {$i i386nop.inc}
{$endif x86_64} {$endif x86_64}
maxinfolen = 8; maxinfolen = 8;
MaxInsChanges = 3; { Max things a instruction can change }
type
{ What an instruction can change. Needed for optimizer and spilling code }
TInsChange = (Ch_None,
{Read from a register}
Ch_REAX, Ch_RECX, Ch_REDX, Ch_REBX, Ch_RESP, Ch_REBP, Ch_RESI, Ch_REDI,
{write from a register}
Ch_WEAX, Ch_WECX, Ch_WEDX, Ch_WEBX, Ch_WESP, Ch_WEBP, Ch_WESI, Ch_WEDI,
{read and write from/to a register}
Ch_RWEAX, Ch_RWECX, Ch_RWEDX, Ch_RWEBX, Ch_RWESP, Ch_RWEBP, Ch_RWESI, Ch_RWEDI,
{modify the contents of a register with the purpose of using
this changed content afterwards (add/sub/..., but e.g. not rep
or movsd)}
Ch_MEAX, Ch_MECX, Ch_MEDX, Ch_MEBX, Ch_MESP, Ch_MEBP, Ch_MESI, Ch_MEDI,
Ch_CDirFlag {clear direction flag}, Ch_SDirFlag {set dir flag},
Ch_RFlags, Ch_WFlags, Ch_RWFlags, Ch_FPU,
Ch_Rop1, Ch_Wop1, Ch_RWop1,Ch_Mop1,
Ch_Rop2, Ch_Wop2, Ch_RWop2,Ch_Mop2,
Ch_Rop3, Ch_WOp3, Ch_RWOp3,Ch_Mop3,
Ch_WMemEDI,
Ch_All
);
TInsProp = packed record
Ch : Array[1..MaxInsChanges] of TInsChange;
end;
const
InsProp : array[tasmop] of TInsProp = {$i i386prop.inc}
type type
TOperandOrder = (op_intel,op_att); TOperandOrder = (op_intel,op_att);
@ -201,6 +231,8 @@ interface
procedure Pass2(objdata:TAsmObjectdata);virtual; procedure Pass2(objdata:TAsmObjectdata);virtual;
procedure SetOperandOrder(order:TOperandOrder); procedure SetOperandOrder(order:TOperandOrder);
function is_same_reg_move(regtype: Tregistertype):boolean;override; function is_same_reg_move(regtype: Tregistertype):boolean;override;
{ register spilling code }
function spilling_get_operation_type(opnr: longint): topertype;override;
protected protected
procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override; procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override; procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
@ -366,6 +398,12 @@ implementation
); );
{$endif x86_64} {$endif x86_64}
{ Operation type for spilling code }
type
toperation_type_table=array[tasmop,0..Max_Operands] of topertype;
var
operation_type_table : ^toperation_type_table;
{**************************************************************************** {****************************************************************************
TAI_ALIGN TAI_ALIGN
@ -1932,15 +1970,74 @@ implementation
end; end;
procedure build_spilling_operation_type_table;
var
opcode : tasmop;
i : integer;
begin
new(operation_type_table);
fillchar(operation_type_table^,sizeof(toperation_type_table),byte(operand_read));
for opcode:=low(tasmop) to high(tasmop) do
begin
for i:=1 to MaxInsChanges do
begin
case InsProp[opcode].Ch[i] of
Ch_Rop1 :
operation_type_table^[opcode,0]:=operand_read;
Ch_Wop1 :
operation_type_table^[opcode,0]:=operand_write;
Ch_RWop1,
Ch_Mop1 :
operation_type_table^[opcode,0]:=operand_readwrite;
Ch_Rop2 :
operation_type_table^[opcode,1]:=operand_read;
Ch_Wop2 :
operation_type_table^[opcode,1]:=operand_write;
Ch_RWop2,
Ch_Mop2 :
operation_type_table^[opcode,1]:=operand_readwrite;
Ch_Rop3 :
operation_type_table^[opcode,2]:=operand_read;
Ch_Wop3 :
operation_type_table^[opcode,2]:=operand_write;
Ch_RWop3,
Ch_Mop3 :
operation_type_table^[opcode,2]:=operand_readwrite;
end;
end;
end;
end;
function taicpu.spilling_get_operation_type(opnr: longint): topertype;
begin
result:=operation_type_table^[opcode,opnr];
end;
function spilling_create_load(const ref:treference;r:tregister): tai; function spilling_create_load(const ref:treference;r:tregister): tai;
begin begin
internalerror(200406131); case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r);
R_MMREGISTER :
result:=taicpu.op_ref_reg(A_MOVSD,reg2opsize(r),ref,r);
else
internalerror(200401041);
end;
end; end;
function spilling_create_store(r:tregister; const ref:treference): tai; function spilling_create_store(r:tregister; const ref:treference): tai;
begin begin
internalerror(200406132); case getregtype(r) of
R_INTREGISTER :
result:=taicpu.op_reg_ref(A_MOV,reg2opsize(r),r,ref);
R_MMREGISTER :
result:=taicpu.op_reg_ref(A_MOVSD,reg2opsize(r),r,ref);
else
internalerror(200401041);
end;
end; end;
@ -1970,6 +2067,7 @@ implementation
procedure InitAsm; procedure InitAsm;
begin begin
build_spilling_operation_type_table;
{$ifndef NOAG386BIN} {$ifndef NOAG386BIN}
if not assigned(instabcache) then if not assigned(instabcache) then
BuildInsTabCache; BuildInsTabCache;
@ -1979,6 +2077,11 @@ implementation
procedure DoneAsm; procedure DoneAsm;
begin begin
if assigned(operation_type_table) then
begin
dispose(operation_type_table);
operation_type_table:=nil;
end;
{$ifndef NOAG386BIN} {$ifndef NOAG386BIN}
if assigned(instabcache) then if assigned(instabcache) then
begin begin
@ -1995,7 +2098,14 @@ begin
end. end.
{ {
$Log$ $Log$
Revision 1.58 2004-09-27 15:12:47 peter Revision 1.59 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.58 2004/09/27 15:12:47 peter
* IE when expecting top_ref * IE when expecting top_ref
Revision 1.57 2004/06/20 08:55:32 florian Revision 1.57 2004/06/20 08:55:32 florian

View File

@ -551,12 +551,15 @@ unit cgx86;
if s in [S_BL,S_WL,S_L] then if s in [S_BL,S_WL,S_L] then
reg2:=makeregsize(list,reg2,OS_32); reg2:=makeregsize(list,reg2,OS_32);
{$endif x86_64} {$endif x86_64}
if (reg1<>reg2) then
begin
instr:=taicpu.op_reg_reg(op,s,reg1,reg2); instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
{ Notify the register allocator that we have written a move instruction so { Notify the register allocator that we have written a move instruction so
it can try to eliminate it. } it can try to eliminate it. }
add_move_instruction(instr); add_move_instruction(instr);
list.concat(instr); list.concat(instr);
end; end;
end;
procedure tcgx86.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister); procedure tcgx86.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
@ -1672,7 +1675,14 @@ unit cgx86;
end. end.
{ {
$Log$ $Log$
Revision 1.126 2004-10-03 12:42:22 florian Revision 1.127 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.126 2004/10/03 12:42:22 florian
* made sqrt, sqr and abs internal for the sparc * made sqrt, sqr and abs internal for the sparc
Revision 1.125 2004/09/25 14:23:55 peter Revision 1.125 2004/09/25 14:23:55 peter

View File

@ -36,10 +36,21 @@ unit rgx86;
type type
trgx86 = class(trgobj) trgx86 = class(trgobj)
{$ifdef OLDRGX86}
function instr_spill_register(list:Taasmoutput; function instr_spill_register(list:Taasmoutput;
instr:taicpu; instr:taicpu;
const r:Tsuperregisterset; const r:Tsuperregisterset;
const spilltemplist:Tspill_temp_list): boolean;override; const spilltemplist:Tspill_temp_list): boolean;override;
{$endif OLDRGX86}
function get_spill_subreg(r : tregister) : tsubregister;override;
{
procedure do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
procedure do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
procedure do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);override;
}
end; end;
tpushedsavedloc = record tpushedsavedloc = record
@ -107,6 +118,7 @@ implementation
Trgcpu Trgcpu
******************************************************************************} ******************************************************************************}
{$ifdef OLDRGX86}
function trgx86.instr_spill_register(list:Taasmoutput; function trgx86.instr_spill_register(list:Taasmoutput;
instr:taicpu; instr:taicpu;
const r:Tsuperregisterset; const r:Tsuperregisterset;
@ -485,8 +497,67 @@ implementation
end; end;
end; end;
end; end;
{$endif OLDRGX86}
function trgx86.get_spill_subreg(r : tregister) : tsubregister;
begin
result:=getsubreg(r);
end;
(*
procedure trgx86.do_spill_read(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
var
helpins: tai;
tmpref,ref : treference;
helplist : taasmoutput;
tmpreg : tregister;
begin
{ ref:=spilltemplist[regs[regidx].orgreg];
if abs(ref.offset)>4095 then
begin
end
else }
inherited do_spill_read(list,instr,pos,regidx,spilltemplist,regs);
end;
procedure trgx86.do_spill_written(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
var
helpins: tai;
ref,tmpref : treference;
helplist : taasmoutput;
tmpreg : tregister;
begin
{ ref:=spilltemplist[regs[regidx].orgreg];
if abs(ref.offset)>4095 then
begin
end
else }
inherited do_spill_written(list,instr,pos,regidx,spilltemplist,regs);
end;
procedure trgx86.do_spill_readwritten(list : taasmoutput;instr : taicpu;pos: tai; regidx: word;
const spilltemplist:Tspill_temp_list;const regs : tspillregsinfo);
var
helpins1, helpins2: tai;
tmpref,ref : treference;
helplist : taasmoutput;
tmpreg : tregister;
begin
{ ref:=spilltemplist[regs[regidx].orgreg];
if abs(ref.offset)>4095 then
begin
end
else }
inherited do_spill_readwritten(list,instr,pos,regidx,spilltemplist,regs);
end;
*)
{****************************************************************************** {******************************************************************************
Trgx86fpu Trgx86fpu
******************************************************************************} ******************************************************************************}
@ -619,7 +690,14 @@ implementation
end. end.
{ {
$Log$ $Log$
Revision 1.6 2004-09-27 14:49:45 peter Revision 1.7 2004-10-04 20:46:22 peter
* spilling code rewritten for x86. It now used the generic
spilling routines. Special x86 optimization still needs
to be added.
* Spilling fixed when both operands needed to be spilled
* Cleanup of spilling routine, do_spill_readwritten removed
Revision 1.6 2004/09/27 14:49:45 peter
* handle 3 operand opcodes the same as 2 operand opcodes, the * handle 3 operand opcodes the same as 2 operand opcodes, the
third operand can only be a const or register CL, so it doesn't third operand can only be a const or register CL, so it doesn't
affect spilling affect spilling