From 6997121c189d1633fb465a31e51d52ce1112ee88 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 10 Sep 2006 16:21:50 +0000 Subject: [PATCH] * 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 - --- compiler/ncgadd.pas | 7 +++++++ compiler/ncgcal.pas | 2 ++ compiler/ncginl.pas | 6 +++++- compiler/ncgld.pas | 3 ++- compiler/ncgmem.pas | 1 + compiler/ncgutil.pas | 40 +++++++++++++++++++++++++++++++++++++--- 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/compiler/ncgadd.pas b/compiler/ncgadd.pas index 2bcf2fe4ca..e63114064d 100644 --- a/compiler/ncgadd.pas +++ b/compiler/ncgadd.pas @@ -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 diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 2c217c76e6..2ec3d37f5d 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -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 diff --git a/compiler/ncginl.pas b/compiler/ncginl.pas index d182376c43..13759aa0d7 100644 --- a/compiler/ncginl.pas +++ b/compiler/ncginl.pas @@ -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) diff --git a/compiler/ncgld.pas b/compiler/ncgld.pas index 056304c114..0e104da84c 100644 --- a/compiler/ncgld.pas +++ b/compiler/ncgld.pas @@ -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 diff --git a/compiler/ncgmem.pas b/compiler/ncgmem.pas index 39b82840ac..bfe66772bc 100644 --- a/compiler/ncgmem.pas +++ b/compiler/ncgmem.pas @@ -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 diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 8e06e7920a..6413b500b2 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -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