mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 03:59:13 +02:00
+ Added newra version of Ti386shlshrnode
+ Added interference graph construction code
This commit is contained in:
parent
fb55235acc
commit
eedc447400
@ -1029,9 +1029,13 @@ interface
|
|||||||
{ right.location<>LOC_REGISTER }
|
{ right.location<>LOC_REGISTER }
|
||||||
if (nodetype=subn) and (nf_swaped in flags) then
|
if (nodetype=subn) and (nf_swaped in flags) then
|
||||||
begin
|
begin
|
||||||
|
{$ifdef newra}
|
||||||
|
r:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
{$else}
|
||||||
rg.getexplicitregisterint(exprasmlist,NR_EDI);
|
rg.getexplicitregisterint(exprasmlist,NR_EDI);
|
||||||
r.enum:=R_INTREGISTER;
|
r.enum:=R_INTREGISTER;
|
||||||
r.number:=NR_EDI;
|
r.number:=NR_EDI;
|
||||||
|
{$endif}
|
||||||
cg64.a_load64low_loc_reg(exprasmlist,right.location,r);
|
cg64.a_load64low_loc_reg(exprasmlist,right.location,r);
|
||||||
emit_reg_reg(op1,opsize,left.location.registerlow,r);
|
emit_reg_reg(op1,opsize,left.location.registerlow,r);
|
||||||
emit_reg_reg(A_MOV,opsize,r,left.location.registerlow);
|
emit_reg_reg(A_MOV,opsize,r,left.location.registerlow);
|
||||||
@ -1636,7 +1640,11 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.57 2003-03-08 13:59:17 daniel
|
Revision 1.58 2003-03-08 20:36:41 daniel
|
||||||
|
+ Added newra version of Ti386shlshrnode
|
||||||
|
+ Added interference graph construction code
|
||||||
|
|
||||||
|
Revision 1.57 2003/03/08 13:59:17 daniel
|
||||||
* Work to handle new register notation in ag386nsm
|
* Work to handle new register notation in ag386nsm
|
||||||
+ Added newra version of Ti386moddivnode
|
+ Added newra version of Ti386moddivnode
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ implementation
|
|||||||
var r,r2,hreg1,hreg2:Tregister;
|
var r,r2,hreg1,hreg2:Tregister;
|
||||||
power:longint;
|
power:longint;
|
||||||
hl:Tasmlabel;
|
hl:Tasmlabel;
|
||||||
|
op:Tasmop;
|
||||||
pushedregs:Tmaybesave;
|
pushedregs:Tmaybesave;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -81,111 +82,105 @@ implementation
|
|||||||
maybe_restore(exprasmlist,left.location,pushedregs);
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
if codegenerror then
|
if codegenerror then
|
||||||
exit;
|
exit;
|
||||||
location_copy(location,left.location);
|
|
||||||
|
|
||||||
if is_64bitint(resulttype.def) then
|
if is_64bitint(resulttype.def) then
|
||||||
|
{ should be handled in pass_1 (JM) }
|
||||||
|
internalerror(200109052);
|
||||||
|
{ put numerator in register }
|
||||||
|
location_reset(location,LOC_REGISTER,OS_INT);
|
||||||
|
location_force_reg(exprasmlist,left.location,OS_INT,false);
|
||||||
|
hreg1:=left.location.register;
|
||||||
|
|
||||||
|
if (nodetype=divn) and (right.nodetype=ordconstn) and
|
||||||
|
ispowerof2(tordconstnode(right).value,power) then
|
||||||
begin
|
begin
|
||||||
{ should be handled in pass_1 (JM) }
|
{ for signed numbers, the numerator must be adjusted before the
|
||||||
internalerror(200109052);
|
shift instruction, but not wih unsigned numbers! Otherwise,
|
||||||
|
"Cardinal($ffffffff) div 16" overflows! (JM) }
|
||||||
|
if is_signed(left.resulttype.def) Then
|
||||||
|
begin
|
||||||
|
if (aktOptProcessor <> class386) and
|
||||||
|
not(cs_littlesize in aktglobalswitches) then
|
||||||
|
{ use a sequence without jumps, saw this in
|
||||||
|
comp.compilers (JM) }
|
||||||
|
begin
|
||||||
|
{ no jumps, but more operations }
|
||||||
|
hreg2:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
|
emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
|
||||||
|
{If the left value is signed, hreg2=$ffffffff, otherwise 0.}
|
||||||
|
emit_const_reg(A_SAR,S_L,31,hreg2);
|
||||||
|
{If signed, hreg2=right value-1, otherwise 0.}
|
||||||
|
emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
|
||||||
|
{ add to the left value }
|
||||||
|
emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
|
||||||
|
{ release EDX if we used it }
|
||||||
|
rg.ungetregisterint(exprasmlist,hreg2);
|
||||||
|
{ do the shift }
|
||||||
|
emit_const_reg(A_SAR,S_L,power,hreg1);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ a jump, but less operations }
|
||||||
|
emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
|
||||||
|
objectlibrary.getlabel(hl);
|
||||||
|
emitjmp(C_NS,hl);
|
||||||
|
if power=1 then
|
||||||
|
emit_reg(A_INC,S_L,hreg1)
|
||||||
|
else
|
||||||
|
emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
|
||||||
|
cg.a_label(exprasmlist,hl);
|
||||||
|
emit_const_reg(A_SAR,S_L,power,hreg1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
emit_const_reg(A_SHR,S_L,power,hreg1);
|
||||||
|
location.register:=hreg1;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ put numerator in register }
|
{Bring denominator to a register.}
|
||||||
location_reset(location,LOC_REGISTER,OS_INT);
|
rg.getexplicitregisterint(exprasmlist,NR_EAX);
|
||||||
location_force_reg(exprasmlist,left.location,OS_INT,false);
|
r.enum:=R_INTREGISTER;
|
||||||
hreg1:=left.location.register;
|
r.number:=NR_EAX;
|
||||||
|
r2.enum:=R_INTREGISTER;
|
||||||
|
r2.number:=NR_EDX;
|
||||||
|
emit_reg_reg(A_MOV,S_L,hreg1,r);
|
||||||
|
rg.ungetregisterint(exprasmlist,hreg1);
|
||||||
|
rg.getexplicitregisterint(exprasmlist,NR_EDX);
|
||||||
|
{Sign extension depends on the left type.}
|
||||||
|
if torddef(left.resulttype.def).typ=u32bit then
|
||||||
|
emit_reg_reg(A_XOR,S_L,r2,r2)
|
||||||
|
else
|
||||||
|
emit_none(A_CDQ,S_NO);
|
||||||
|
|
||||||
if (nodetype=divn) and (right.nodetype=ordconstn) and
|
{Division depends on the right type.}
|
||||||
ispowerof2(tordconstnode(right).value,power) then
|
if torddef(right.resulttype.def).typ=u32bit then
|
||||||
|
op:=A_DIV
|
||||||
|
else
|
||||||
|
op:=A_IDIV;
|
||||||
|
|
||||||
|
if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
|
||||||
|
emit_ref(op,S_L,right.location.reference)
|
||||||
|
else
|
||||||
|
emit_reg(op,S_L,right.location.register);
|
||||||
|
location_release(exprasmlist,right.location);
|
||||||
|
|
||||||
|
{Copy the result into a new register. Release EAX & EDX.}
|
||||||
|
if nodetype=divn then
|
||||||
begin
|
begin
|
||||||
{ for signed numbers, the numerator must be adjusted before the
|
rg.ungetregisterint(exprasmlist,r2);
|
||||||
shift instruction, but not wih unsigned numbers! Otherwise,
|
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
"Cardinal($ffffffff) div 16" overflows! (JM) }
|
emit_reg_reg(A_MOV,S_L,r,location.register);
|
||||||
if is_signed(left.resulttype.def) Then
|
rg.ungetregisterint(exprasmlist,r);
|
||||||
begin
|
|
||||||
if (aktOptProcessor <> class386) and
|
|
||||||
not(CS_LittleSize in aktglobalswitches) then
|
|
||||||
{ use a sequence without jumps, saw this in
|
|
||||||
comp.compilers (JM) }
|
|
||||||
begin
|
|
||||||
{ no jumps, but more operations }
|
|
||||||
hreg2:=rg.getregisterint(exprasmlist,OS_INT);
|
|
||||||
emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
|
|
||||||
{ if the left value is signed, hreg2 := $ffffffff,
|
|
||||||
otherwise 0 }
|
|
||||||
emit_const_reg(A_SAR,S_L,31,hreg2);
|
|
||||||
{ if signed, hreg2 := right value-1, otherwise 0 }
|
|
||||||
emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
|
|
||||||
{ add to the left value }
|
|
||||||
emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
|
|
||||||
{ release EDX if we used it }
|
|
||||||
{ also releas EDI }
|
|
||||||
rg.ungetregisterint(exprasmlist,hreg2);
|
|
||||||
{ do the shift }
|
|
||||||
emit_const_reg(A_SAR,S_L,power,hreg1);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
{ a jump, but less operations }
|
|
||||||
emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
|
|
||||||
objectlibrary.getlabel(hl);
|
|
||||||
emitjmp(C_NS,hl);
|
|
||||||
if power=1 then
|
|
||||||
emit_reg(A_INC,S_L,hreg1)
|
|
||||||
else
|
|
||||||
emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
|
|
||||||
cg.a_label(exprasmlist,hl);
|
|
||||||
emit_const_reg(A_SAR,S_L,power,hreg1);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
emit_const_reg(A_SHR,S_L,power,hreg1);
|
|
||||||
location.register:=hreg1;
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{Bring denominator to a register.}
|
rg.ungetregisterint(exprasmlist,r);
|
||||||
hreg2:=rg.getregisterint(exprasmlist,OS_INT);
|
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
||||||
if right.location.loc<>LOC_CREGISTER then
|
emit_reg_reg(A_MOV,S_L,r2,location.register);
|
||||||
location_release(exprasmlist,right.location);
|
rg.ungetregisterint(exprasmlist,r2);
|
||||||
cg.a_load_loc_reg(exprasmlist,right.location,hreg2);
|
|
||||||
rg.getexplicitregisterint(exprasmlist,NR_EAX);
|
|
||||||
rg.getexplicitregisterint(exprasmlist,NR_EDX);
|
|
||||||
r.enum:=R_INTREGISTER;
|
|
||||||
r.number:=NR_EAX;
|
|
||||||
r2.enum:=R_INTREGISTER;
|
|
||||||
r2.number:=NR_EDX;
|
|
||||||
emit_reg_reg(A_MOV,S_L,hreg1,r);
|
|
||||||
rg.ungetregisterint(exprasmlist,hreg1);
|
|
||||||
{Sign extension depends on the left type.}
|
|
||||||
if torddef(left.resulttype.def).typ=u32bit then
|
|
||||||
emit_reg_reg(A_XOR,S_L,r2,r2)
|
|
||||||
else
|
|
||||||
emit_none(A_CDQ,S_NO);
|
|
||||||
|
|
||||||
{Division depends on the right type.}
|
|
||||||
if torddef(right.resulttype.def).typ=u32bit then
|
|
||||||
emit_reg(A_DIV,S_L,hreg2)
|
|
||||||
else
|
|
||||||
emit_reg(A_IDIV,S_L,hreg2);
|
|
||||||
|
|
||||||
rg.ungetregisterint(exprasmlist,hreg2);
|
|
||||||
if nodetype=divn then
|
|
||||||
begin
|
|
||||||
rg.ungetregisterint(exprasmlist,r2);
|
|
||||||
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
|
||||||
emit_reg_reg(A_MOV,S_L,r,location.register);
|
|
||||||
rg.ungetregisterint(exprasmlist,r);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
rg.ungetregisterint(exprasmlist,r);
|
|
||||||
location.register:=rg.getregisterint(exprasmlist,OS_INT);
|
|
||||||
emit_reg_reg(A_MOV,S_L,r2,location.register);
|
|
||||||
rg.ungetregisterint(exprasmlist,r2);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$else}
|
{$else}
|
||||||
procedure ti386moddivnode.pass_2;
|
procedure ti386moddivnode.pass_2;
|
||||||
@ -414,10 +409,175 @@ implementation
|
|||||||
|
|
||||||
|
|
||||||
function ti386shlshrnode.first_shlshr64bitint: tnode;
|
function ti386shlshrnode.first_shlshr64bitint: tnode;
|
||||||
begin
|
|
||||||
result := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
begin
|
||||||
|
result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$ifdef newra}
|
||||||
|
procedure ti386shlshrnode.pass_2;
|
||||||
|
|
||||||
|
var hregister2,hregisterhigh,hregisterlow:Tregister;
|
||||||
|
r,r2:Tregister;
|
||||||
|
op:Tasmop;
|
||||||
|
l1,l2,l3:Tasmlabel;
|
||||||
|
pushedregs:Tmaybesave;
|
||||||
|
|
||||||
|
begin
|
||||||
|
secondpass(left);
|
||||||
|
maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
|
||||||
|
secondpass(right);
|
||||||
|
maybe_restore(exprasmlist,left.location,pushedregs);
|
||||||
|
|
||||||
|
{ determine operator }
|
||||||
|
if nodetype=shln then
|
||||||
|
op:=A_SHL
|
||||||
|
else
|
||||||
|
op:=A_SHR;
|
||||||
|
|
||||||
|
if is_64bitint(left.resulttype.def) then
|
||||||
|
begin
|
||||||
|
location_reset(location,LOC_REGISTER,OS_64);
|
||||||
|
|
||||||
|
{ load left operator in a register }
|
||||||
|
location_force_reg(exprasmlist,left.location,OS_64,false);
|
||||||
|
hregisterhigh:=left.location.registerhigh;
|
||||||
|
hregisterlow:=left.location.registerlow;
|
||||||
|
if hregisterhigh.enum<>R_INTREGISTER then
|
||||||
|
internalerror(200302056);
|
||||||
|
if hregisterlow.enum<>R_INTREGISTER then
|
||||||
|
internalerror(200302056);
|
||||||
|
|
||||||
|
{ shifting by a constant directly coded: }
|
||||||
|
if (right.nodetype=ordconstn) then
|
||||||
|
begin
|
||||||
|
{ shrd/shl works only for values <=31 !! }
|
||||||
|
if Tordconstnode(right).value>31 then
|
||||||
|
begin
|
||||||
|
if nodetype=shln then
|
||||||
|
begin
|
||||||
|
emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
|
||||||
|
if ((tordconstnode(right).value and 31) <> 0) then
|
||||||
|
emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
|
||||||
|
hregisterlow);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
|
||||||
|
if ((tordconstnode(right).value and 31) <> 0) then
|
||||||
|
emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
|
||||||
|
hregisterhigh);
|
||||||
|
end;
|
||||||
|
location.registerhigh:=hregisterlow;
|
||||||
|
location.registerlow:=hregisterhigh;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if nodetype=shln then
|
||||||
|
begin
|
||||||
|
emit_const_reg_reg(A_SHLD,S_L,tordconstnode(right).value and 31,
|
||||||
|
hregisterlow,hregisterhigh);
|
||||||
|
emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
|
||||||
|
hregisterlow);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
emit_const_reg_reg(A_SHRD,S_L,tordconstnode(right).value and 31,
|
||||||
|
hregisterhigh,hregisterlow);
|
||||||
|
emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
|
||||||
|
hregisterhigh);
|
||||||
|
end;
|
||||||
|
location.registerlow:=hregisterlow;
|
||||||
|
location.registerhigh:=hregisterhigh;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ load right operators in a register }
|
||||||
|
rg.getexplicitregisterint(exprasmlist,NR_ECX);
|
||||||
|
hregister2.enum:=R_INTREGISTER;
|
||||||
|
hregister2.number:=NR_ECX;
|
||||||
|
cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
|
||||||
|
if right.location.loc<>LOC_CREGISTER then
|
||||||
|
location_release(exprasmlist,right.location);
|
||||||
|
|
||||||
|
{ left operator is already in a register }
|
||||||
|
{ hence are both in a register }
|
||||||
|
{ is it in the case ECX ? }
|
||||||
|
r.enum:=R_INTREGISTER;
|
||||||
|
r.number:=NR_ECX;
|
||||||
|
r2.enum:=R_INTREGISTER;
|
||||||
|
r2.number:=NR_CL;
|
||||||
|
|
||||||
|
{ the damned shift instructions work only til a count of 32 }
|
||||||
|
{ so we've to do some tricks here }
|
||||||
|
objectlibrary.getlabel(l1);
|
||||||
|
objectlibrary.getlabel(l2);
|
||||||
|
objectlibrary.getlabel(l3);
|
||||||
|
emit_const_reg(A_CMP,S_L,64,hregister2);
|
||||||
|
emitjmp(C_L,l1);
|
||||||
|
emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
|
||||||
|
emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
|
||||||
|
cg.a_jmp_always(exprasmlist,l3);
|
||||||
|
cg.a_label(exprasmlist,l1);
|
||||||
|
emit_const_reg(A_CMP,S_L,32,hregister2);
|
||||||
|
emitjmp(C_L,l2);
|
||||||
|
emit_const_reg(A_SUB,S_L,32,hregister2);
|
||||||
|
if nodetype=shln then
|
||||||
|
begin
|
||||||
|
emit_reg_reg(A_SHL,S_L,r2,hregisterlow);
|
||||||
|
emit_reg_reg(A_MOV,S_L,hregisterlow,hregisterhigh);
|
||||||
|
emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
|
||||||
|
cg.a_jmp_always(exprasmlist,l3);
|
||||||
|
cg.a_label(exprasmlist,l2);
|
||||||
|
emit_reg_reg_reg(A_SHLD,S_L,r2,hregisterlow,hregisterhigh);
|
||||||
|
emit_reg_reg(A_SHL,S_L,r2,hregisterlow);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
emit_reg_reg(A_SHR,S_L,r2,hregisterhigh);
|
||||||
|
emit_reg_reg(A_MOV,S_L,hregisterhigh,hregisterlow);
|
||||||
|
emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
|
||||||
|
cg.a_jmp_always(exprasmlist,l3);
|
||||||
|
cg.a_label(exprasmlist,l2);
|
||||||
|
emit_reg_reg_reg(A_SHRD,S_L,r2,hregisterhigh,hregisterlow);
|
||||||
|
emit_reg_reg(A_SHR,S_L,r2,hregisterhigh);
|
||||||
|
end;
|
||||||
|
cg.a_label(exprasmlist,l3);
|
||||||
|
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister2);
|
||||||
|
location.registerlow:=hregisterlow;
|
||||||
|
location.registerhigh:=hregisterhigh;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ load left operators in a register }
|
||||||
|
location_copy(location,left.location);
|
||||||
|
location_force_reg(exprasmlist,location,OS_INT,false);
|
||||||
|
|
||||||
|
r2.enum:=R_INTREGISTER;
|
||||||
|
r2.number:=NR_CL;
|
||||||
|
|
||||||
|
{ shifting by a constant directly coded: }
|
||||||
|
if (right.nodetype=ordconstn) then
|
||||||
|
{ l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
|
||||||
|
emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ load right operators in a ECX }
|
||||||
|
if right.location.loc<>LOC_CREGISTER then
|
||||||
|
location_release(exprasmlist,right.location);
|
||||||
|
hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
|
||||||
|
cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
|
||||||
|
|
||||||
|
{ right operand is in ECX }
|
||||||
|
emit_reg_reg(op,S_L,r2,location.register);
|
||||||
|
rg.ungetregisterint(exprasmlist,hregister2);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$else}
|
||||||
procedure ti386shlshrnode.pass_2;
|
procedure ti386shlshrnode.pass_2;
|
||||||
var
|
var
|
||||||
hregister2,hregister3,
|
hregister2,hregister3,
|
||||||
@ -692,6 +852,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
@ -1008,7 +1169,11 @@ begin
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.46 2003-03-08 13:59:17 daniel
|
Revision 1.47 2003-03-08 20:36:41 daniel
|
||||||
|
+ Added newra version of Ti386shlshrnode
|
||||||
|
+ Added interference graph construction code
|
||||||
|
|
||||||
|
Revision 1.46 2003/03/08 13:59:17 daniel
|
||||||
* Work to handle new register notation in ag386nsm
|
* Work to handle new register notation in ag386nsm
|
||||||
+ Added newra version of Ti386moddivnode
|
+ Added newra version of Ti386moddivnode
|
||||||
|
|
||||||
|
@ -28,6 +28,47 @@
|
|||||||
references and registers which are used by
|
references and registers which are used by
|
||||||
the code generator.
|
the code generator.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{*******************************************************************************
|
||||||
|
|
||||||
|
(applies to new register allocator)
|
||||||
|
|
||||||
|
Register allocator introduction.
|
||||||
|
|
||||||
|
Free Pascal uses a Chaitin style register allocator similair to the one
|
||||||
|
described in the book "Modern compiler implementation in C" by Andrew W. Appel.,
|
||||||
|
published by Cambridge University Press.
|
||||||
|
|
||||||
|
Reading this book is recommended for a complete understanding. Here is a small
|
||||||
|
introduction.
|
||||||
|
|
||||||
|
The code generator thinks it has an infinite amount of registers. Our processor
|
||||||
|
has a limited amount of registers. Therefore we must reduce the amount of
|
||||||
|
registers until there are less enough to fit into the processors registers.
|
||||||
|
|
||||||
|
Registers can interfere or not interfere. If two imaginary registers interfere
|
||||||
|
they cannot be placed into the same psysical register. Reduction of registers
|
||||||
|
is done by:
|
||||||
|
|
||||||
|
- "coalescing" Two registers that do not interfere are combined
|
||||||
|
into one register.
|
||||||
|
- "spilling" A register is changed into a memory location and the generated
|
||||||
|
code is modified to use the memory location instead of the register.
|
||||||
|
|
||||||
|
Register allocation is a graph colouring problem. Each register is a colour, and
|
||||||
|
if two registers interfere there is a connection between them in the graph.
|
||||||
|
|
||||||
|
In addition to the imaginary registers in the code generator, the psysical
|
||||||
|
CPU registers are also present in this graph. This allows us to make
|
||||||
|
interferences between imaginary registers and cpu registers. This is very
|
||||||
|
usefull for describing archtectural constrains, like for example that
|
||||||
|
the div instruction modifies edx, so variables that are in use at that time
|
||||||
|
cannot be stored into edx. This can be modelled by making edx interfere
|
||||||
|
with those variables.
|
||||||
|
|
||||||
|
*******************************************************************************}
|
||||||
|
|
||||||
|
|
||||||
unit rgobj;
|
unit rgobj;
|
||||||
|
|
||||||
interface
|
interface
|
||||||
@ -59,6 +100,14 @@ unit rgobj;
|
|||||||
tpushedsaved = array[firstreg..lastreg] of tpushedsavedloc;
|
tpushedsaved = array[firstreg..lastreg] of tpushedsavedloc;
|
||||||
Tpushedsavedint = array[first_supreg..last_supreg] of Tpushedsavedloc;
|
Tpushedsavedint = array[first_supreg..last_supreg] of Tpushedsavedloc;
|
||||||
|
|
||||||
|
Tinterferencebitmap=array[Tsuperregister] of set of Tsuperregister;
|
||||||
|
Tinterferenceadjlist=array[Tsuperregister] of Pstring;
|
||||||
|
Tinterferencegraph=record
|
||||||
|
bitmap:Tinterferencebitmap;
|
||||||
|
adjlist:Tinterferenceadjlist;
|
||||||
|
end;
|
||||||
|
Pinterferencegraph=^Tinterferencegraph;
|
||||||
|
|
||||||
{#
|
{#
|
||||||
This class implements the abstract register allocator
|
This class implements the abstract register allocator
|
||||||
It is used by the code generator to allocate and free
|
It is used by the code generator to allocate and free
|
||||||
@ -237,6 +286,9 @@ unit rgobj;
|
|||||||
procedure saveUnusedState(var state: pointer);virtual;
|
procedure saveUnusedState(var state: pointer);virtual;
|
||||||
procedure restoreUnusedState(var state: pointer);virtual;
|
procedure restoreUnusedState(var state: pointer);virtual;
|
||||||
protected
|
protected
|
||||||
|
{$ifdef newra}
|
||||||
|
igraph:Tinterferencegraph;
|
||||||
|
{$endif}
|
||||||
{ the following two contain the common (generic) code for all }
|
{ the following two contain the common (generic) code for all }
|
||||||
{ get- and ungetregisterxxx functions/procedures }
|
{ get- and ungetregisterxxx functions/procedures }
|
||||||
function getregistergen(list: taasmoutput; const lowreg, highreg: Toldregister;
|
function getregistergen(list: taasmoutput; const lowreg, highreg: Toldregister;
|
||||||
@ -259,6 +311,10 @@ unit rgobj;
|
|||||||
{$ifdef TEMPREGDEBUG}
|
{$ifdef TEMPREGDEBUG}
|
||||||
procedure testregisters;
|
procedure testregisters;
|
||||||
{$endif TEMPREGDEBUGx}
|
{$endif TEMPREGDEBUGx}
|
||||||
|
{$ifdef newra}
|
||||||
|
procedure add_edge(u,v:Tsuperregister);
|
||||||
|
procedure add_edges_used(u:Tsuperregister);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -353,6 +409,9 @@ unit rgobj;
|
|||||||
fillchar(reg_user,sizeof(reg_user),0);
|
fillchar(reg_user,sizeof(reg_user),0);
|
||||||
fillchar(reg_releaser,sizeof(reg_releaser),0);
|
fillchar(reg_releaser,sizeof(reg_releaser),0);
|
||||||
{$endif TEMPREGDEBUG}
|
{$endif TEMPREGDEBUG}
|
||||||
|
{$ifdef newra}
|
||||||
|
fillchar(igraph,sizeof(igraph),0);
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -408,6 +467,9 @@ unit rgobj;
|
|||||||
list.concat(Tai_regalloc.alloc(r));
|
list.concat(Tai_regalloc.alloc(r));
|
||||||
result:=r;
|
result:=r;
|
||||||
lastintreg:=i;
|
lastintreg:=i;
|
||||||
|
{$ifdef newra}
|
||||||
|
add_edges_used(i);
|
||||||
|
{$endif}
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
until i=lastintreg;
|
until i=lastintreg;
|
||||||
@ -655,27 +717,37 @@ unit rgobj;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure trgobj.cleartempgen;
|
procedure Trgobj.cleartempgen;
|
||||||
|
|
||||||
begin
|
var i:Tsuperregister;
|
||||||
countunusedregsint:=countusableregsint;
|
|
||||||
countunusedregsfpu:=countusableregsfpu;
|
begin
|
||||||
countunusedregsmm:=countusableregsmm;
|
countunusedregsint:=countusableregsint;
|
||||||
{$ifdef newra}
|
countunusedregsfpu:=countusableregsfpu;
|
||||||
unusedregsint:=[0..255];
|
countunusedregsmm:=countusableregsmm;
|
||||||
{$else}
|
{$ifdef newra}
|
||||||
unusedregsint:=usableregsint;
|
unusedregsint:=[0..255];
|
||||||
{$endif}
|
{$else}
|
||||||
unusedregsfpu:=usableregsfpu;
|
unusedregsint:=usableregsint;
|
||||||
unusedregsmm:=usableregsmm;
|
{$endif}
|
||||||
end;
|
unusedregsfpu:=usableregsfpu;
|
||||||
|
unusedregsmm:=usableregsmm;
|
||||||
|
{$ifdef newra}
|
||||||
|
for i:=low(Tsuperregister) to high(Tsuperregister) do
|
||||||
|
if igraph.adjlist[i]<>nil then
|
||||||
|
dispose(igraph.adjlist[i]);
|
||||||
|
fillchar(igraph,sizeof(igraph),0);
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure trgobj.ungetreference(list : taasmoutput; const ref : treference);
|
procedure trgobj.ungetreference(list : taasmoutput; const ref : treference);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ungetregisterint(list,ref.base);
|
if ref.base.number<>NR_NO then
|
||||||
ungetregisterint(list,ref.index);
|
ungetregisterint(list,ref.base);
|
||||||
|
if ref.index.number<>NR_NO then
|
||||||
|
ungetregisterint(list,ref.index);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -1098,6 +1170,48 @@ unit rgobj;
|
|||||||
state := nil;
|
state := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifdef newra}
|
||||||
|
procedure Trgobj.add_edge(u,v:Tsuperregister);
|
||||||
|
|
||||||
|
{This procedure will add an edge to the virtual interference graph.}
|
||||||
|
|
||||||
|
procedure addadj(u,v:Tsuperregister);
|
||||||
|
|
||||||
|
begin
|
||||||
|
if igraph.adjlist[u]=nil then
|
||||||
|
begin
|
||||||
|
getmem(igraph.adjlist[u],16);
|
||||||
|
igraph.adjlist[u]^:='';
|
||||||
|
end
|
||||||
|
else if (length(igraph.adjlist[u]^) and 15)=15 then
|
||||||
|
reallocmem(igraph.adjlist[u],length(igraph.adjlist[u]^)+16);
|
||||||
|
igraph.adjlist[u]^:=igraph.adjlist[u]^+char(v);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if (u<>v) and not(v in igraph.bitmap[u]) then
|
||||||
|
begin
|
||||||
|
include(igraph.bitmap[u],v);
|
||||||
|
include(igraph.bitmap[v],u);
|
||||||
|
{Precoloured nodes are not stored in the interference graph.}
|
||||||
|
if not(u in [first_supreg..last_supreg]) then
|
||||||
|
addadj(u,v);
|
||||||
|
if not(v in [first_supreg..last_supreg]) then
|
||||||
|
addadj(v,u);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Trgobj.add_edges_used(u:Tsuperregister);
|
||||||
|
|
||||||
|
var i:Tsuperregister;
|
||||||
|
|
||||||
|
begin
|
||||||
|
for i:=1 to 255 do
|
||||||
|
if not(i in unusedregsint) then
|
||||||
|
add_edge(u,i);
|
||||||
|
end;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
|
|
||||||
{****************************************************************************
|
{****************************************************************************
|
||||||
TReference
|
TReference
|
||||||
@ -1228,7 +1342,11 @@ end.
|
|||||||
|
|
||||||
{
|
{
|
||||||
$Log$
|
$Log$
|
||||||
Revision 1.28 2003-03-08 13:59:16 daniel
|
Revision 1.29 2003-03-08 20:36:41 daniel
|
||||||
|
+ Added newra version of Ti386shlshrnode
|
||||||
|
+ Added interference graph construction code
|
||||||
|
|
||||||
|
Revision 1.28 2003/03/08 13:59:16 daniel
|
||||||
* Work to handle new register notation in ag386nsm
|
* Work to handle new register notation in ag386nsm
|
||||||
+ Added newra version of Ti386moddivnode
|
+ Added newra version of Ti386moddivnode
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user