mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2026-02-04 12:14:50 +01:00
* Fixed register allocator. *Lots* of fixes.
This commit is contained in:
parent
117d6934a1
commit
268bfcf784
@ -297,17 +297,16 @@ interface
|
||||
end;
|
||||
top_symbol :
|
||||
begin
|
||||
AsmWrite('dword ');
|
||||
asmwrite('dword ');
|
||||
if assigned(o.sym) then
|
||||
AsmWrite(o.sym.name);
|
||||
begin
|
||||
asmwrite(o.sym.name);
|
||||
if o.symofs=0 then
|
||||
exit;
|
||||
end;
|
||||
if o.symofs>0 then
|
||||
AsmWrite('+'+tostr(o.symofs))
|
||||
else
|
||||
if o.symofs<0 then
|
||||
AsmWrite(tostr(o.symofs))
|
||||
else
|
||||
if not(assigned(o.sym)) then
|
||||
AsmWrite('0');
|
||||
asmwrite('+');
|
||||
asmwrite(tostr(o.symofs))
|
||||
end;
|
||||
top_ref :
|
||||
begin
|
||||
@ -926,7 +925,10 @@ initialization
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.35 2003-06-03 13:01:59 daniel
|
||||
Revision 1.36 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.35 2003/06/03 13:01:59 daniel
|
||||
* Register allocator finished
|
||||
|
||||
Revision 1.34 2003/05/26 19:37:57 peter
|
||||
|
||||
@ -378,26 +378,15 @@ interface
|
||||
location_release(exprasmlist,right.location);
|
||||
cg.a_paramaddr_ref(exprasmlist,right.location.reference,paramanager.getintparaloc(exprasmlist,1));
|
||||
{$ifdef newra}
|
||||
r.enum:=R_INTREGISTER;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
r.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,r.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.saveintregvars(exprasmlist,regstopush);
|
||||
rg.saveintregvars(exprasmlist,regstopush);
|
||||
{$endif}
|
||||
cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
|
||||
paramanager.freeintparaloc(exprasmlist,2);
|
||||
paramanager.freeintparaloc(exprasmlist,1);
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
r.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.ungetregisterint(exprasmlist,r);
|
||||
end;
|
||||
rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.restoreusedintregisters(exprasmlist,pushed);
|
||||
{$endif}
|
||||
@ -1644,7 +1633,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.72 2003-06-17 16:51:30 peter
|
||||
Revision 1.73 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.72 2003/06/17 16:51:30 peter
|
||||
* cycle fixes
|
||||
|
||||
Revision 1.71 2003/06/07 18:57:04 jonas
|
||||
|
||||
@ -756,14 +756,15 @@ implementation
|
||||
(not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
if resulttype.def.size>sizeof(aword) then
|
||||
begin
|
||||
include(regs_to_push_int,RS_FUNCTION_RESULT64_LOW_REG);
|
||||
include(regs_to_push_int,RS_FUNCTION_RESULT64_HIGH_REG);
|
||||
end
|
||||
else
|
||||
if resulttype.def.deftype<>floatdef then
|
||||
if resulttype.def.size>sizeof(aword) then
|
||||
begin
|
||||
include(regs_to_push_int,RS_FUNCTION_RESULT64_LOW_REG);
|
||||
include(regs_to_push_int,RS_FUNCTION_RESULT64_HIGH_REG);
|
||||
end
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
|
||||
include(regs_to_push_int,RS_FUNCTION_RESULT_REG);
|
||||
end;
|
||||
rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
|
||||
{$endif}
|
||||
@ -787,7 +788,7 @@ implementation
|
||||
begin
|
||||
{No procedure is allowed to destroy ebp.}
|
||||
{$ifdef newra}
|
||||
regs_to_alloc:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
|
||||
regs_to_alloc:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
|
||||
if (not is_void(resulttype.def)) and
|
||||
not(paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
|
||||
begin
|
||||
@ -939,12 +940,7 @@ implementation
|
||||
end;
|
||||
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i in regs_to_alloc then
|
||||
begin
|
||||
r.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,r.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
|
||||
{$endif}
|
||||
{ call method }
|
||||
reference_reset_base(href,{$ifdef newra}vmtreg2{$else}vmtreg{$endif},
|
||||
@ -966,12 +962,7 @@ implementation
|
||||
end;
|
||||
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i in regs_to_alloc then
|
||||
begin
|
||||
r.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,r.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
|
||||
{$endif}
|
||||
{ Calling interrupt from the same code requires some
|
||||
extra code }
|
||||
@ -990,14 +981,14 @@ implementation
|
||||
if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
|
||||
begin
|
||||
helpref:=right.location.reference;
|
||||
if helpref.index.number<>NR_NO then
|
||||
if (helpref.index.number<>NR_NO) and (helpref.index.number<>NR_FRAME_POINTER_REG) then
|
||||
begin
|
||||
rg.ungetregisterint(exprasmlist,helpref.index);
|
||||
helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
|
||||
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
|
||||
right.location.reference.index,helpref.index);
|
||||
end;
|
||||
if helpref.base.number<>NR_NO then
|
||||
if (helpref.base.number<>NR_NO) and (helpref.base.number<>NR_FRAME_POINTER_REG) then
|
||||
begin
|
||||
rg.ungetregisterint(exprasmlist,helpref.base);
|
||||
helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
|
||||
@ -1021,12 +1012,7 @@ implementation
|
||||
end;
|
||||
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i in regs_to_alloc then
|
||||
begin
|
||||
r.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,r.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
|
||||
{$endif}
|
||||
{ Calling interrupt from the same code requires some
|
||||
extra code }
|
||||
@ -1097,13 +1083,7 @@ implementation
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
r.enum:=R_INTREGISTER;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i in regs_to_free then
|
||||
begin
|
||||
r.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.ungetregisterint(exprasmlist,r);
|
||||
end;
|
||||
rg.deallocexplicitregistersint(exprasmlist,regs_to_free);
|
||||
{$endif}
|
||||
{ handle function results }
|
||||
if (not is_void(resulttype.def)) then
|
||||
@ -1561,7 +1541,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.97 2003-07-05 20:21:26 jonas
|
||||
Revision 1.98 2003-07-06 15:31:20 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.97 2003/07/05 20:21:26 jonas
|
||||
* create_paraloc_info() is now called separately for the caller and
|
||||
callee info
|
||||
* fixed ppc cycle
|
||||
|
||||
@ -521,13 +521,8 @@ implementation
|
||||
cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(exprasmlist,2));
|
||||
cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(exprasmlist,1));
|
||||
{$ifdef newra}
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,hreg.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
|
||||
{$else}
|
||||
rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
|
||||
{$endif}
|
||||
@ -535,12 +530,7 @@ implementation
|
||||
paramanager.freeintparaloc(exprasmlist,2);
|
||||
paramanager.freeintparaloc(exprasmlist,1);
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.ungetregisterint(exprasmlist,hreg);
|
||||
end;
|
||||
rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.restoreusedintregisters(exprasmlist,pushed);
|
||||
{$endif}
|
||||
@ -608,25 +598,14 @@ implementation
|
||||
{$endif}
|
||||
cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(exprasmlist,1));
|
||||
{$ifdef newra}
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,hreg.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
|
||||
{$endif}
|
||||
cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
|
||||
paramanager.freeintparaloc(exprasmlist,1);
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.ungetregisterint(exprasmlist,hreg);
|
||||
end;
|
||||
rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.restoreusedintregisters(exprasmlist,pushed);
|
||||
{$endif}
|
||||
@ -710,13 +689,7 @@ implementation
|
||||
dec(href.offset,7);
|
||||
cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
|
||||
{$ifdef newra}
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,hreg.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
|
||||
{$endif}
|
||||
@ -724,12 +697,7 @@ implementation
|
||||
paramanager.freeintparaloc(exprasmlist,2);
|
||||
paramanager.freeintparaloc(exprasmlist,1);
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.ungetregisterint(exprasmlist,hreg);
|
||||
end;
|
||||
rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.restoreusedintregisters(exprasmlist,pushed);
|
||||
{$endif}
|
||||
@ -868,13 +836,7 @@ implementation
|
||||
dec(href.offset,7);
|
||||
cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(exprasmlist,1));
|
||||
{$ifdef newra}
|
||||
hreg.enum:=R_INTREGISTER;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.getexplicitregisterint(exprasmlist,hreg.number);
|
||||
end;
|
||||
rg.allocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.saveintregvars(exprasmlist,VOLATILE_INTREGISTERS);
|
||||
{$endif}
|
||||
@ -882,12 +844,7 @@ implementation
|
||||
paramanager.freeintparaloc(exprasmlist,2);
|
||||
paramanager.freeintparaloc(exprasmlist,1);
|
||||
{$ifdef newra}
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i<>RS_FRAME_POINTER_REG then
|
||||
begin
|
||||
hreg.number:=i shl 8 or R_SUBWHOLE;
|
||||
rg.ungetregisterint(exprasmlist,hreg);
|
||||
end;
|
||||
rg.deallocexplicitregistersint(exprasmlist,[first_supreg..last_supreg]-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]);
|
||||
{$else}
|
||||
rg.restoreusedintregisters(exprasmlist,pushed);
|
||||
{$endif}
|
||||
@ -924,7 +881,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.64 2003-06-17 19:24:08 jonas
|
||||
Revision 1.65 2003-07-06 15:31:20 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.64 2003/06/17 19:24:08 jonas
|
||||
* fixed conversion of fpc_*str_unique to compilerproc
|
||||
|
||||
Revision 1.63 2003/06/17 16:34:44 jonas
|
||||
|
||||
@ -401,6 +401,20 @@ implementation
|
||||
end
|
||||
else
|
||||
begin
|
||||
{$ifdef newra}
|
||||
{ transformations to 32bit or smaller }
|
||||
if (l.loc=LOC_REGISTER) and (l.size in [OS_64,OS_S64]) then
|
||||
{ if the previous was 64bit release the high register }
|
||||
begin
|
||||
rg.ungetregisterint(list,l.registerhigh);
|
||||
l.registerhigh.enum:=R_NO;
|
||||
end;
|
||||
{Do not bother to recycle the existing register. The register
|
||||
allocator eliminates unnecessary moves, so it's not needed
|
||||
and trying to recycle registers can cause problems because
|
||||
the registers changes size and may need aditional constraints.}
|
||||
hregister:=rg.getregisterint(list,dst_size);
|
||||
{$else}
|
||||
{ transformations to 32bit or smaller }
|
||||
if l.loc=LOC_REGISTER then
|
||||
begin
|
||||
@ -441,8 +455,6 @@ implementation
|
||||
hregister:=rg.getregisterint(list,dst_size);
|
||||
end;
|
||||
hregister:=rg.makeregsize(hregister,dst_size);
|
||||
{$ifdef newra}
|
||||
rg.add_constraints(hregister.number);
|
||||
{$endif}
|
||||
{ load value in new register }
|
||||
case l.loc of
|
||||
@ -1976,7 +1988,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.128 2003-07-02 22:18:04 peter
|
||||
Revision 1.129 2003-07-06 15:31:20 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.128 2003/07/02 22:18:04 peter
|
||||
* paraloc splitted in callerparaloc,calleeparaloc
|
||||
* sparc calling convention updates
|
||||
|
||||
|
||||
@ -119,9 +119,9 @@ interface
|
||||
labsym : tlabelsym;
|
||||
labsymderef : tderef;
|
||||
exceptionblock : integer;
|
||||
// internlab : tinterngotolabel;
|
||||
{ internlab : tinterngotolabel;}
|
||||
constructor create(p : tlabelsym);virtual;
|
||||
// constructor createintern(g:tinterngotolabel);
|
||||
{ constructor createintern(g:tinterngotolabel);}
|
||||
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
|
||||
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
||||
procedure derefimpl;override;
|
||||
@ -1429,7 +1429,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.78 2003-06-13 21:19:30 peter
|
||||
Revision 1.79 2003-07-06 15:31:20 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.78 2003/06/13 21:19:30 peter
|
||||
* current_procdef removed, use current_procinfo.procdef instead
|
||||
|
||||
Revision 1.77 2003/06/07 20:26:32 peter
|
||||
|
||||
@ -205,7 +205,11 @@ implementation
|
||||
Comment(V_Warning,'Location is different in secondpass: '+nodetype2str[p.nodetype]);
|
||||
end;
|
||||
|
||||
{$ifndef newra}
|
||||
{$ifdef newra}
|
||||
if rg.unusedregsint*([first_supreg..last_supreg] - [RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG])<>
|
||||
([first_supreg..last_supreg] - [RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]) then
|
||||
internalerror(200306171);
|
||||
{$else}
|
||||
{ check if all scratch registers are freed }
|
||||
for i:=1 to max_scratch_regs do
|
||||
if not(scratch_regs[i] in cg.unusedscratchregisters) then
|
||||
@ -255,7 +259,9 @@ implementation
|
||||
|
||||
procedure generatecode(var p : tnode);
|
||||
begin
|
||||
{$ifndef newra}
|
||||
rg.cleartempgen;
|
||||
{$endif}
|
||||
flowcontrol:=[];
|
||||
{ when size optimization only count occurrence }
|
||||
if cs_littlesize in aktglobalswitches then
|
||||
@ -310,7 +316,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.59 2003-07-06 10:18:47 jonas
|
||||
Revision 1.60 2003-07-06 15:31:20 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.59 2003/07/06 10:18:47 jonas
|
||||
* also generate the caller paraloc info of a procedure if it doesn't exist
|
||||
yet at the start of pass_2
|
||||
|
||||
|
||||
@ -186,11 +186,14 @@ begin
|
||||
exitproc:=@myexit;
|
||||
|
||||
{ Call the compiler with empty command, so it will take the parameters }
|
||||
Halt(compiler.Compile(''));
|
||||
{Halt(}compiler.Compile(''){)};
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.22 2003-04-22 14:33:38 peter
|
||||
Revision 1.23 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.22 2003/04/22 14:33:38 peter
|
||||
* removed some notes/hints
|
||||
|
||||
Revision 1.21 2003/02/15 22:25:50 carl
|
||||
|
||||
@ -595,7 +595,8 @@ implementation
|
||||
|
||||
{ reset the temporary memory }
|
||||
rg.cleartempgen;
|
||||
rg.used_in_proc_int:=[];
|
||||
{ exclude(rg.unusedregsint,RS_STACK_POINTER_REG);}
|
||||
rg.used_in_proc_int:=[{RS_STACK_POINTER_REG}];
|
||||
rg.used_in_proc_other:=[];
|
||||
|
||||
{ set the start offset to the start of the temp area in the stack }
|
||||
@ -1253,7 +1254,10 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.130 2003-07-05 20:15:24 jonas
|
||||
Revision 1.131 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.130 2003/07/05 20:15:24 jonas
|
||||
* set pi_do_call if range/overflow checking is on
|
||||
|
||||
Revision 1.129 2003/06/17 16:34:44 jonas
|
||||
|
||||
@ -34,14 +34,21 @@
|
||||
|
||||
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.
|
||||
Free Pascal uses a Chaitin style register allocator. We use a variant similair
|
||||
to the one described in the book "Modern compiler implementation in C" by
|
||||
Andrew W. Appel., published by Cambridge University Press.
|
||||
|
||||
The register allocator that is described by Appel uses a much improved way
|
||||
of register coalescing, called "iterated register coalescing". Instead
|
||||
of doing coalescing as a prepass to the register allocation, the coalescing
|
||||
is done inside the register allocator. This has the advantage that the
|
||||
register allocator can coalesce very aggresively without introducing spills.
|
||||
|
||||
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 processorhas a limited amount of registers. Therefore we must reduce the amount of
|
||||
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
|
||||
@ -68,6 +75,9 @@ Graph colouring is an NP complete problem. Therefore we use an approximation
|
||||
that pushes registers to colour on to a stack. This is done in the "simplify"
|
||||
procedure.
|
||||
|
||||
The register allocator first checks which registers are a candidate for
|
||||
coalescing.
|
||||
|
||||
*******************************************************************************}
|
||||
|
||||
|
||||
@ -275,6 +285,11 @@ unit rgobj;
|
||||
}
|
||||
function getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;virtual;
|
||||
|
||||
{$ifdef newra}
|
||||
procedure allocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
|
||||
procedure deallocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
|
||||
{$endif}
|
||||
|
||||
{# Deallocate any kind of register }
|
||||
procedure ungetregister(list: taasmoutput; r : tregister); virtual;
|
||||
|
||||
@ -493,7 +508,9 @@ unit rgobj;
|
||||
|
||||
punusedstate = ^tunusedstate;
|
||||
tunusedstate = record
|
||||
{$ifndef newra}
|
||||
unusedregsint : Tsupregset;
|
||||
{$endif}
|
||||
unusedregsaddr : Tsupregset;
|
||||
unusedregsfpu : tregisterset;
|
||||
unusedregsmm : tregisterset;
|
||||
@ -521,7 +538,12 @@ unit rgobj;
|
||||
resetusableregisters;
|
||||
lastintreg:=0;
|
||||
maxintreg:=first_imreg;
|
||||
cpu_registers:={Acpu_registers}last_supreg-first_supreg+1;
|
||||
{What madman decided to change the code like this: (??)
|
||||
cpu_registers:=last_supreg-first_supreg+1;
|
||||
The amount of registers available for register allocation is
|
||||
allmost allways smaller than the amount of registers that exists!
|
||||
Therefore: }
|
||||
cpu_registers:=Acpu_registers;
|
||||
{$ifdef TEMPREGDEBUG}
|
||||
fillchar(reg_user,sizeof(reg_user),0);
|
||||
fillchar(reg_releaser,sizeof(reg_releaser),0);
|
||||
@ -763,6 +785,52 @@ unit rgobj;
|
||||
getexplicitregisterint:=r2;
|
||||
end;
|
||||
|
||||
{$ifdef newra}
|
||||
procedure Trgobj.allocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
|
||||
|
||||
var reg:Tregister;
|
||||
i:Tsuperregister;
|
||||
|
||||
begin
|
||||
if unusedregsint*r=r then
|
||||
begin
|
||||
unusedregsint:=unusedregsint-r;
|
||||
used_in_proc_int:=used_in_proc_int+r;
|
||||
for i:=first_supreg to last_supreg do
|
||||
if i in r then
|
||||
begin
|
||||
add_edges_used(i);
|
||||
reg.enum:=R_INTREGISTER;
|
||||
reg.number:=i shl 8 or R_SUBWHOLE;
|
||||
list.concat(Tai_regalloc.alloc(reg));
|
||||
end;
|
||||
end
|
||||
else
|
||||
internalerror(200305061);
|
||||
end;
|
||||
|
||||
procedure Trgobj.deallocexplicitregistersint(list:Taasmoutput;r:Tsupregset);
|
||||
|
||||
var reg:Tregister;
|
||||
i:Tsuperregister;
|
||||
|
||||
begin
|
||||
if unusedregsint*r=[] then
|
||||
begin
|
||||
unusedregsint:=unusedregsint+r;
|
||||
for i:=last_supreg downto first_supreg do
|
||||
if i in r then
|
||||
begin
|
||||
reg.enum:=R_INTREGISTER;
|
||||
reg.number:=i shl 8 or R_SUBWHOLE;
|
||||
list.concat(Tai_regalloc.dealloc(reg));
|
||||
end;
|
||||
end
|
||||
else
|
||||
internalerror(200305062);
|
||||
end;
|
||||
{$endif}
|
||||
|
||||
|
||||
{ tries to allocate the passed register, if possible }
|
||||
function trgobj.getexplicitregisterfpu(list : taasmoutput; r : Toldregister) : tregister;
|
||||
@ -853,9 +921,7 @@ unit rgobj;
|
||||
exit;
|
||||
if r.enum>lastreg then
|
||||
internalerror(200301081);
|
||||
if r.enum in intregs then
|
||||
ungetregisterint(list,r)
|
||||
else if r.enum in fpuregs then
|
||||
if r.enum in fpuregs then
|
||||
ungetregisterfpu(list,r,OS_NO)
|
||||
else if r.enum in mmregs then
|
||||
ungetregistermm(list,r)
|
||||
@ -1357,7 +1423,9 @@ unit rgobj;
|
||||
procedure trgobj.saveUnusedState(var state: pointer);
|
||||
begin
|
||||
new(punusedstate(state));
|
||||
{$ifndef newra}
|
||||
punusedstate(state)^.unusedregsint := unusedregsint;
|
||||
{$endif}
|
||||
punusedstate(state)^.unusedregsfpu := unusedregsfpu;
|
||||
punusedstate(state)^.unusedregsmm := unusedregsmm;
|
||||
{$ifndef newra}
|
||||
@ -1370,7 +1438,9 @@ unit rgobj;
|
||||
|
||||
procedure trgobj.restoreUnusedState(var state: pointer);
|
||||
begin
|
||||
{$ifndef newra}
|
||||
unusedregsint := punusedstate(state)^.unusedregsint;
|
||||
{$endif}
|
||||
unusedregsfpu := punusedstate(state)^.unusedregsfpu;
|
||||
unusedregsmm := punusedstate(state)^.unusedregsmm;
|
||||
{$ifndef newra}
|
||||
@ -1643,7 +1713,9 @@ unit rgobj;
|
||||
end;
|
||||
end;
|
||||
n:=Tsuperregister(simplifyworklist[p]);
|
||||
delete(simplifyworklist,p,1);
|
||||
if length(simplifyworklist)>1 then
|
||||
simplifyworklist[p]:=simplifyworklist[length(simplifyworklist)];
|
||||
dec(simplifyworklist[0]);
|
||||
|
||||
{Push it on the selectstack.}
|
||||
selectstack:=selectstack+char(n);
|
||||
@ -1671,7 +1743,10 @@ unit rgobj;
|
||||
if not(u in [first_supreg..last_supreg]) and not move_related(u) and
|
||||
(degree[u]<cpu_registers) then
|
||||
begin
|
||||
delete(freezeworklist,pos(char(u),freezeworklist),1);
|
||||
if length(freezeworklist)>1 then
|
||||
freezeworklist[pos(char(u),freezeworklist)]:=freezeworklist[length(freezeworklist)];
|
||||
dec(freezeworklist[0]);
|
||||
{ delete(freezeworklist,pos(char(u),freezeworklist),1);}
|
||||
simplifyworklist:=simplifyworklist+char(u);
|
||||
end;
|
||||
end;
|
||||
@ -1940,6 +2015,7 @@ unit rgobj;
|
||||
if a in colourednodes then
|
||||
include(adj_colours,colour[a]);
|
||||
end;
|
||||
include(adj_colours,RS_STACK_POINTER_REG);
|
||||
{Assume a spill by default...}
|
||||
spillednodes:=spillednodes+char(n);
|
||||
{Search for a colour not in this list.}
|
||||
@ -2246,9 +2322,8 @@ unit rgobj;
|
||||
|
||||
begin
|
||||
if r.enum<=lastreg then
|
||||
internalerror(2003010803);
|
||||
internalerror(200301083);
|
||||
supreg:=r.number shr 8;
|
||||
{ takes much time }
|
||||
include(unusedregsint,supreg);
|
||||
if position=nil then
|
||||
list.insert(Tai_regalloc.dealloc(r))
|
||||
@ -2271,9 +2346,10 @@ unit rgobj;
|
||||
spill_registers:=false;
|
||||
unusedregsint:=[0..255];
|
||||
fillchar(degree,sizeof(degree),0);
|
||||
{ exclude(unusedregsint,RS_STACK_POINTER_REG);}
|
||||
if current_procinfo.framepointer.number=NR_FRAME_POINTER_REG then
|
||||
{Make sure the register allocator won't allocate registers into ebp.}
|
||||
exclude(rg.unusedregsint,RS_FRAME_POINTER_REG);
|
||||
exclude(unusedregsint,RS_FRAME_POINTER_REG);
|
||||
new(spill_temps);
|
||||
fillchar(spill_temps^,sizeof(spill_temps^),0);
|
||||
regs_to_spill_set:=[];
|
||||
@ -2459,7 +2535,10 @@ end.
|
||||
|
||||
{
|
||||
$Log$
|
||||
Revision 1.59 2003-07-06 15:00:47 jonas
|
||||
Revision 1.60 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.59 2003/07/06 15:00:47 jonas
|
||||
* fixed my previous completely broken commit. It's not perfect though,
|
||||
registers > last_supreg and < max_intreg may still be "translated"
|
||||
|
||||
|
||||
@ -3415,7 +3415,7 @@ implementation
|
||||
end;
|
||||
lastref:=defref;
|
||||
{ first, we assume that all registers are used }
|
||||
usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
|
||||
usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
|
||||
usedotherregisters:=ALL_REGISTERS;
|
||||
forwarddef:=true;
|
||||
interfacedef:=false;
|
||||
@ -3557,7 +3557,7 @@ implementation
|
||||
{ set all registers to used for simplified compilation PM }
|
||||
if simplify_ppu then
|
||||
begin
|
||||
usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG];
|
||||
usedintregisters:=VOLATILE_INTREGISTERS-[RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG];
|
||||
usedotherregisters:=ALL_REGISTERS;
|
||||
end;
|
||||
|
||||
@ -5838,7 +5838,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.154 2003-07-02 22:18:04 peter
|
||||
Revision 1.155 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.154 2003/07/02 22:18:04 peter
|
||||
* paraloc splitted in callerparaloc,calleeparaloc
|
||||
* sparc calling convention updates
|
||||
|
||||
|
||||
@ -2081,7 +2081,7 @@ implementation
|
||||
case ops of
|
||||
1:
|
||||
begin
|
||||
if oper[0].typ=top_reg then
|
||||
if (oper[0].typ=top_reg) and (oper[0].reg.enum=R_INTREGISTER) then
|
||||
begin
|
||||
supreg:=oper[0].reg.number shr 8;
|
||||
if supreg in r then
|
||||
@ -2109,7 +2109,7 @@ implementation
|
||||
Change into:
|
||||
|
||||
mov r23d,[ebp-12] ; Use a help register
|
||||
push [r23d+4*r22d] ; Replace register by helpregister }
|
||||
push [r23d+4*r22d] ; Replace register by helpregister }
|
||||
subreg:=oper[0].ref^.base.number and $ff;
|
||||
if oper[0].ref^.index.number=NR_NO then
|
||||
pos:=Tai(previous)
|
||||
@ -2156,7 +2156,7 @@ implementation
|
||||
end;
|
||||
2:
|
||||
begin
|
||||
if oper[0].typ=top_reg then
|
||||
if (oper[0].typ=top_reg) and (oper[0].reg.enum=R_INTREGISTER) then
|
||||
begin
|
||||
supreg:=oper[0].reg.number shr 8;
|
||||
subreg:=oper[0].reg.number and $ff;
|
||||
@ -2196,7 +2196,7 @@ implementation
|
||||
oper[0].ref^:=spilltemplist[supreg];
|
||||
end;
|
||||
end;
|
||||
if oper[1].typ=top_reg then
|
||||
if (oper[1].typ=top_reg) and (oper[1].reg.enum=R_INTREGISTER) then
|
||||
begin
|
||||
supreg:=oper[1].reg.number shr 8;
|
||||
subreg:=oper[1].reg.number and $ff;
|
||||
@ -2246,6 +2246,23 @@ implementation
|
||||
Change into:
|
||||
|
||||
add [ebp-12],r21d ; Replace register by reference }
|
||||
if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
|
||||
begin
|
||||
{Because 'movzx memory,register' does not exist...}
|
||||
spill_registers:=true;
|
||||
op:=opcode;
|
||||
opcode:=A_MOV;
|
||||
opsize:=reg2opsize(oper[1].reg);
|
||||
pos:=get_insert_pos(Tai(previous),oper[0].reg.number,0,0);
|
||||
rgget(list,pos,subreg,helpreg);
|
||||
helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0].reg,helpreg);
|
||||
if pos=nil then
|
||||
list.insertafter(helpins,list.first)
|
||||
else
|
||||
list.insertafter(helpins,pos.next);
|
||||
rgunget(list,helpins,helpreg);
|
||||
forward_allocation(Tai(helpins.next));
|
||||
end;
|
||||
oper[1].typ:=top_ref;
|
||||
new(oper[1].ref);
|
||||
oper[1].ref^:=spilltemplist[supreg];
|
||||
@ -2396,7 +2413,10 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.6 2003-06-14 14:53:50 jonas
|
||||
Revision 1.7 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.6 2003/06/14 14:53:50 jonas
|
||||
* fixed newra cycle for x86
|
||||
* added constants for indicating source and destination operands of the
|
||||
"move reg,reg" instruction to aasmcpu (and use those in rgobj)
|
||||
|
||||
@ -146,11 +146,9 @@ interface
|
||||
function gas_regnum_search(const s:string):Tnewregister;
|
||||
|
||||
|
||||
implementation
|
||||
implementation
|
||||
|
||||
uses
|
||||
cutils,systems,
|
||||
verbose;
|
||||
uses cutils;
|
||||
|
||||
function gas_regnum_search(const s:string):Tnewregister;
|
||||
|
||||
@ -178,7 +176,10 @@ interface
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.1 2003-05-22 21:33:08 peter
|
||||
Revision 1.2 2003-07-06 15:31:21 daniel
|
||||
* Fixed register allocator. *Lots* of fixes.
|
||||
|
||||
Revision 1.1 2003/05/22 21:33:08 peter
|
||||
* i386 att instruction table moved to separate unit
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user