mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-11 18:49:14 +02:00
* also perform "SSA" for certain loads (currently derefn, righthand side of
assignmentn and callparan), reduces number of long lived conflicts. Mainly helpful on register-starved cpus such as i386. git-svn-id: trunk@4606 -
This commit is contained in:
parent
aa9808f6ce
commit
6997121c18
@ -375,6 +375,7 @@ interface
|
||||
var
|
||||
cgop : TOpCg;
|
||||
otl,ofl : tasmlabel;
|
||||
oldflowcontrol : tflowcontrol;
|
||||
begin
|
||||
{ And,Or will only evaluate from left to right only the
|
||||
needed nodes unless full boolean evaluation is enabled }
|
||||
@ -405,8 +406,14 @@ interface
|
||||
else
|
||||
internalerror(200307044);
|
||||
end;
|
||||
{ these jumps mean we're now in a flow control construct }
|
||||
oldflowcontrol:=flowcontrol;
|
||||
include(flowcontrol,fc_inflowcontrol);
|
||||
|
||||
secondpass(right);
|
||||
maketojumpbool(current_asmdata.CurrAsmList,right,lr_load_regvars);
|
||||
|
||||
flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]);
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
@ -370,6 +370,8 @@ implementation
|
||||
current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
|
||||
secondpass(left);
|
||||
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
|
||||
|
||||
{ release memory for refcnt out parameters }
|
||||
if (parasym.varspez=vs_out) and
|
||||
(left.resulttype.def.needs_inittable) then
|
||||
|
@ -400,6 +400,11 @@ implementation
|
||||
begin
|
||||
{ set defaults }
|
||||
addconstant:=true;
|
||||
{ first secondpass second argument, because if the first arg }
|
||||
{ is used in that expression then SSL may move it to another }
|
||||
{ register }
|
||||
if assigned(tcallparanode(left).right) then
|
||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||
{ load first parameter, must be a reference }
|
||||
secondpass(tcallparanode(left).left);
|
||||
cgsize:=def_cgsize(tcallparanode(left).left.resulttype.def);
|
||||
@ -421,7 +426,6 @@ implementation
|
||||
{ second_ argument specified?, must be a s32bit in register }
|
||||
if assigned(tcallparanode(left).right) then
|
||||
begin
|
||||
secondpass(tcallparanode(tcallparanode(left).right).left);
|
||||
{ when constant, just multiply the addvalue }
|
||||
if is_constintnode(tcallparanode(tcallparanode(left).right).left) then
|
||||
addvalue:=addvalue*get_ordinal_value(tcallparanode(tcallparanode(left).right).left)
|
||||
|
@ -558,7 +558,8 @@ implementation
|
||||
else
|
||||
begin
|
||||
{ SSA support }
|
||||
maybechangeloadnodereg(left);
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
|
||||
case right.location.loc of
|
||||
LOC_CONSTANT :
|
||||
begin
|
||||
|
@ -188,6 +188,7 @@ implementation
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
begin
|
||||
maybechangeloadnodereg(current_asmdata.CurrAsmList,left,true);
|
||||
{$ifdef cpu_uses_separate_address_registers}
|
||||
if getregtype(left.location.register)<>R_ADDRESSREGISTER then
|
||||
begin
|
||||
|
@ -102,8 +102,9 @@ interface
|
||||
procedure gen_sync_regvars(list:TAsmList; var rv: tusedregvars);
|
||||
|
||||
{ if the result of n is a LOC_C(..)REGISTER, try to find the corresponding }
|
||||
{ loadn and change its location to a new register (= SSA) }
|
||||
procedure maybechangeloadnodereg(var n: tnode);
|
||||
{ loadn and change its location to a new register (= SSA). In case reload }
|
||||
{ is true, transfer the old to the new register }
|
||||
procedure maybechangeloadnodereg(list: TAsmList; var n: tnode; reload: boolean);
|
||||
|
||||
{#
|
||||
Allocate the buffers for exception management and setjmp environment.
|
||||
@ -2466,11 +2467,21 @@ implementation
|
||||
result := fen_norecurse_true;
|
||||
end;
|
||||
end;
|
||||
{ optimize the searching a bit }
|
||||
derefn,addrn,
|
||||
calln,inlinen,casen,
|
||||
addn,subn,muln,
|
||||
andn,orn,xorn,
|
||||
ltn,lten,gtn,gten,equaln,unequaln,
|
||||
slashn,divn,shrn,shln,notn,
|
||||
inn,
|
||||
asn,isn:
|
||||
result := fen_norecurse_false;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure maybechangeloadnodereg(var n: tnode);
|
||||
procedure maybechangeloadnodereg(list: TAsmList; var n: tnode; reload: boolean);
|
||||
var
|
||||
rr: treplaceregrec;
|
||||
begin
|
||||
@ -2519,6 +2530,29 @@ implementation
|
||||
if not foreachnodestatic(n,@doreplace,@rr) then
|
||||
exit;
|
||||
|
||||
if reload then
|
||||
case n.location.loc of
|
||||
LOC_CREGISTER:
|
||||
begin
|
||||
{$ifndef cpu64bit}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
cg64.a_load64_reg_reg(list,n.location.register64,joinreg64(rr.new,rr.newhi))
|
||||
else
|
||||
{$endif cpu64bit}
|
||||
cg.a_load_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new);
|
||||
end;
|
||||
LOC_CFPUREGISTER:
|
||||
cg.a_loadfpu_reg_reg(list,n.location.size,n.location.register,rr.new);
|
||||
{$ifdef SUPPORT_MMX}
|
||||
LOC_CMMXREGISTER:
|
||||
cg.a_loadmm_reg_reg(list,OS_M64,OS_M64,n.location.register,rr.new,nil);
|
||||
{$endif SUPPORT_MMX}
|
||||
LOC_CMMREGISTER:
|
||||
cg.a_loadmm_reg_reg(list,n.location.size,n.location.size,n.location.register,rr.new,nil);
|
||||
else
|
||||
internalerror(2006090920);
|
||||
end;
|
||||
|
||||
{ now that we've change the loadn/temp, also change the node result location }
|
||||
{$ifndef cpu64bit}
|
||||
if (n.location.size in [OS_64,OS_S64]) then
|
||||
|
Loading…
Reference in New Issue
Block a user