unit srPrivate; {$mode ObjFPC}{$H+} interface uses sysutils, spirv, ginodes, srNode, srType, srTypes, srLayout, srOp, srOpUtils, srReg, srVariable, srConst, srBitcast, srCFGParser; type TsrPrivate=class; TStoreNode=class(TsrNode) pPrev,pNext:TStoreNode; // src :TsrRegNode; //line:TspirvOp; // end; TStoreNodeList=specialize TNodeListClass; TsrVolatile=class(TsrNode) var pPrev,pNext:TsrVolatile; FPrivate :TsrPrivate; FSlot :PsrRegSlot; FList :TStoreNodeList; FBase :TsrRegNode; FZeroRead:Boolean; ForceBool:Boolean; // Procedure _zero_read; override; Procedure _zero_unread; override; Procedure _PrepType(node:PPrepTypeNode); override; // function ListCount:Integer; Procedure AddStore(src:TsrRegNode); Procedure PushStore(node:TStoreNode); Function PopStore:TStoreNode; Procedure RemoveAllStore; procedure PrepType(new:TsrDataType); end; ntVolatile=TsrVolatile; TsrPrivate=class(TsrDescriptor) public pPrev,pNext :TsrPrivate; pLeft,pRight:TsrPrivate; class function c(n1,n2:PPsrRegSlot):Integer; static; private // FPrivId:Integer; key:PsrRegSlot; // FLineList:TDependenceNodeList; // Procedure SetRegType(rtype:TsrDataType); function GetRegType:TsrDataType; public // Procedure _PrepType(node:PPrepTypeNode); override; function _GetStorageName:RawByteString; override; // property dtype:TsrDataType read GetRegType write SetRegType; property Source:PsrRegSlot read key; Procedure Init; inline; function GetStorageName:RawByteString; function adjust_type(new:TsrDataType):TsrDataType; Procedure UpdateRegType; Procedure PrepType(new:TsrDataType); Procedure SortLines; Procedure Optimize; procedure AddLine(pLine:TspirvOp); procedure AddLine(pLine:TspirvOp;node:TDependenceNode); procedure FetchLoad (pLine:TspirvOp;dst:TsrRegNode); Procedure FetchStore(pLine:TspirvOp;src:TsrRegNode); end; ntPrivate=TsrPrivate; PsrPrivateList=^TsrPrivateList; TsrPrivateList=object type TPrivList=specialize TNodeListClass; TVoltList=specialize TNodeListClass; var FEmit:TCustomEmit; FPrivList:TPrivList; FVoltList:TVoltList; FPrivId:Integer; procedure Init(Emit:TCustomEmit); inline; function NewVolatile(Slot:PsrRegSlot):TsrVolatile; function Fetch(pSource:PsrRegSlot):TsrPrivate; function FetchCustom(dtype:TsrDataType):TsrPrivate; function FetchArray(dtype:TsrDataType;array_count:DWORD):TsrPrivate; function First:TsrPrivate; inline; // procedure build_slot_reset(pSlot:PsrRegSlot;var orig:TsrRegNode); procedure build_slot_ctrue(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); procedure build_slot_endif(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); procedure build_slot_break(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); procedure build_slot_conti(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); procedure build_volatile_reset(orig:PsrRegsSnapshot); procedure build_volatile_ctrue(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); procedure build_volatile_endif(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); procedure build_volatile_break(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); procedure build_volatile_conti(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); procedure make_copy_slot(pSlot:PsrRegSlot); procedure make_copy_all; function PrepVolatile(dst:TspirvOp;src:TsrRegNode):TsrRegNode; Procedure RemoveAllStore; Procedure Post; end; implementation Procedure TsrVolatile._zero_read; var node:TStoreNode; begin if FZeroRead then Exit; // node:=FList.pHead; While (node<>nil) do begin node.src.mark_read(Self); node:=node.pNext; end; // FZeroRead:=True; end; Procedure TsrVolatile._zero_unread; var node:TStoreNode; begin if not FZeroRead then Exit; // node:=FList.pHead; While (node<>nil) do begin node.src.mark_unread(Self); node:=node.pNext; end; // FZeroRead:=False; end; Procedure TsrVolatile._PrepType(node:PPrepTypeNode); begin PrepType(TsrDataType(node^.rtype)); node^.dnode:=nil; end; // procedure TsrVolatile.PrepType(new:TsrDataType); var node:TStoreNode; begin new:=FPrivate.adjust_type(new); if (new=dtUnknow) then exit; node:=FList.pHead; While (node<>nil) do begin if node.src.pWriter.IsType(TsrVolatile) then Break; node.src.PrepType(ord(new)); node:=node.pNext; end; end; function TsrVolatile.ListCount:Integer; var node:TStoreNode; begin Result:=0; // node:=FList.pHead; While (node<>nil) do begin Inc(Result); // node:=node.pNext; end; end; Procedure TsrVolatile.AddStore(src:TsrRegNode); var node:TStoreNode; pLine:TspirvOp; begin if (src=nil) then Exit; if (src.IsType(TsrVectorArray)) then begin Assert(false,'AddStore:TsrVectorArray'); end; Assert(src.pLine<>nil); pLine:=src.pLine; Assert(pLine<>nil); node:=Emit.specialize New; //cache in free list? node.src :=src; //node.line:=pLine; if FZeroRead then begin src.mark_read(Self); end; FList.Push_head(node); end; Procedure TsrVolatile.PushStore(node:TStoreNode); begin if (node=nil) then Exit; //Assert(node.src.pLine<>nil); //Assert(node.line<>nil); if FZeroRead then begin node.src.mark_read(Self); end; FList.Push_head(node); end; Function TsrVolatile.PopStore:TStoreNode; begin Result:=FList.Pop_head; if (Result<>nil) then if FZeroRead then begin Result.src.mark_unread(Self); end; end; Procedure TsrVolatile.RemoveAllStore; var node:TStoreNode; begin repeat node:=PopStore; until (node=nil); end; // Procedure TsrPrivate._PrepType(node:PPrepTypeNode); begin PrepType(TsrDataType(node^.rtype)); node^.dnode:=nil; end; function TsrPrivate._GetStorageName:RawByteString; begin Result:=GetStorageName; end; // class function TsrPrivate.c(n1,n2:PPsrRegSlot):Integer; begin Result:=ord(n1^>n2^)-ord(n1^nil) then begin if (Source^.isBoolOnly) then begin Exit(dtBool); end; end; if (FType<>nil) then begin Exit(FType.dtype); end; Result:=new; end; Procedure TsrPrivate.SetRegType(rtype:TsrDataType); var pTypeList:PsrTypeList; begin pTypeList:=Emit.GetTypeList; Ftype:=pTypeList^.Fetch(rtype); UpdateRegType; end; function TsrPrivate.GetRegType:TsrDataType; begin Result:=FType.dtype; end; Procedure TsrPrivate.UpdateRegType; var pBitcastList:PsrBitcastList; node:TDependenceNode; pLine:TspirvOp; Value:TsrNode; dst:TsrRegNode; old,rtype:TsrDataType; ConstList:PsrConstList; cst:TsrConst; begin rtype:=FType.dtype; pBitcastList:=Emit.GetBitcastList; node:=FLineList.pHead; While (node<>nil) do begin pLine:=node.pNode; Case pLine.OpId of Op.OpLoad: begin Value:=pLine.pDst; Value.PrepType(ord(rtype)); pLine.pType:=Ftype; dst:=Value.specialize AsType; if (dst<>nil) then begin old:=dst.dtype; if (old<>dtUnknow) and (rtype<>old) then begin //OpLoad -> new -> dst dst:=pBitcastList^.FetchDstr(rtype,dst); pLine.pDst:=dst; end; end; end; Op.OpStore: begin Value:=pLine.ParamNode(1).Value; Value.PrepType(ord(rtype)); dst:=Value.specialize AsType; if (dst<>nil) then begin // if dst.is_const then begin cst:=dst.pWriter; if (dst.dtype<>cst.dtype) then begin ConstList:=Emit.GetConstList; // cst:=ConstList^.Bitcast(dst.dtype,cst); dst.pWriter:=cst; end; end; // old:=dst.dtype; if (old<>dtUnknow) and (rtype<>old) then begin //OpStore <- new <- dst dst:=pBitcastList^.FetchRead(rtype,dst); pLine.ParamNode(1).Value:=dst; end; end; end; else; end; node:=node.pNext; end; end; Procedure TsrPrivate.PrepType(new:TsrDataType); var old:TsrDataType; begin new:=adjust_type(new); if (new=dtUnknow) then exit; old:=GetRegType; if is_unprep_type(old,new,True) then begin SetRegType(new); end; end; { procedure _update_store_line(pLine:TspirvOp); var pReg:TsrRegNode; pCur:TspirvOp; begin if (pLine.OpId<>Op.OpStore) then Exit; pReg:=RegDown(pLine.ParamNode(1).Value.specialize AsType); if (pReg=nil) then Exit; pCur:=pReg.pLine; if (pLine<>pCur) and (MaxLine(pLine,pCur)=pCur) then //pCur>pLine begin pLine.Remove; pCur.InsertAfter(pLine); end; end; } Procedure TsrPrivate.SortLines; var dnode,dnext:TDependenceNode; //pLine:array[0..1] of TspirvOp; nswp:Boolean; begin //indexing dnode:=FLineList.pHead; While (dnode<>nil) do begin dnode.fread_count:=GetGlobalIndex(dnode.pNode); dnode:=dnode.pNext; end; //bubble sort repeat nswp:=True; dnode:=FLineList.pHead; While (dnode<>nil) do begin dnext:=dnode.pNext; if (dnext=nil) then Break; //pLine[0]:=dnode.pNode; //pLine[1]:=dnext.pNode; //_update_store_line(pLine[0]); //_update_store_line(pLine[1]); //if (MaxLine(pLine[0],pLine[1])=pLine[0]) then //dnode>dnext if (dnode.fread_count>dnext.fread_count) then begin //swap nswp:=False; FLineList.Remove(dnode); FLineList.InsertAfter(dnext,dnode); end else begin dnode:=dnext; end; end; until nswp; end; Function FindByHalfSpace(node,prev:TspirvOp):Boolean; begin Result:=False; while (node<>nil) do begin if (node=prev) then Exit(True); // if node.IsType(ntOpBlock) then if IsReal(TsrOpBlock(node).bType) then begin Exit(False); end; // node:=flow_down_prev_up(node); end; end; Procedure TsrPrivate.Optimize; var dnode,dprev:TDependenceNode; pLine:array[0..1] of TspirvOp; pRegs:array[0..1] of TsrRegNode; begin //exit; dnode:=FLineList.pTail; While (dnode<>nil) do begin dprev:=dnode.pPrev; if (dprev=nil) then Break; pLine[0]:=dnode.pNode; pLine[1]:=dprev.pNode; if (pLine[0].Parent=pLine[1].Parent) then if FindByHalfSpace(pLine[0],pLine[1]) then begin //OpStore %v ; pLine[1] ; (dprev) //OpStore %v ; pLine[0] ; (dnode) if (pLine[0].OpId=Op.OpStore) and (pLine[1].OpId=Op.OpStore) then begin //Remove dprev FLineList.Remove(dprev); pLine[1].mark([soNotUsed]); Continue; end else if (pLine[0].OpId=Op.OpStore) and (pLine[1].OpId=Op.OpLoad) then begin //%r = OpLoad %type %v ; pLine[1] ; (dprev) //OpStore %v %r ; pLine[0] ; (dnode) pRegs[0]:=RegDown(pLine[0].ParamNode(1).Value.specialize AsType); pRegs[1]:=RegDown(pLine[1].pDst.specialize AsType); if (pRegs[0]<>nil) and (pRegs[1]<>nil) and CompareReg(pRegs[0],pRegs[1]) then begin //Remove dnode FLineList.Remove(dnode); pLine[0].mark([soNotUsed]); dnode:=dprev; if (dnode.pNext<>nil) then begin dnode:=dnode.pNext; end; Continue; end; end else if (pLine[0].OpId=Op.OpLoad) and (pLine[1].OpId=Op.OpLoad) then begin //%r1 = OpLoad %type %v ; pLine[1] ; (dprev) //%r2 = OpLoad %type %v ; pLine[0] ; (dnode) pRegs[0]:=pLine[0].pDst.specialize AsType; pRegs[1]:=pLine[1].pDst.specialize AsType; if (pRegs[0]<>nil) and (pRegs[1]<>nil) then begin pRegs[0].pWriter:=pRegs[1]; //Remove dnode FLineList.Remove(dnode); dnode:=dprev; if (dnode.pNext<>nil) then begin dnode:=dnode.pNext; end; Continue; end; end; end; dnode:=dprev; end; end; procedure TsrPrivate.AddLine(pLine:TspirvOp); var node:TDependenceNode; begin node:=NewDependence; node.pNode:=pLine; FLineList.Push_tail(node); end; procedure TsrPrivate.AddLine(pLine:TspirvOp;node:TDependenceNode); begin //hack reuse node.pNode:=pLine; FLineList.Push_tail(node); end; procedure TsrPrivate.FetchLoad(pLine:TspirvOp;dst:TsrRegNode); begin Assert(dst<>nil); pLine:=Emit.OpLoad(pLine,FType,dst,FVar); AddLine(pLine); end; Procedure TsrPrivate.FetchStore(pLine:TspirvOp;src:TsrRegNode); begin if (src=nil) then Exit; pLine:=Emit.OpStore(pLine,FVar,src); AddLine(pLine); end; // procedure TsrPrivateList.Init(Emit:TCustomEmit); inline; begin FEmit:=Emit; end; function TsrPrivateList.NewVolatile(Slot:PsrRegSlot):TsrVolatile; begin Result:=FEmit.specialize New; Result.FSlot:=Slot; FVoltList.Push_tail(Result); end; function TsrPrivateList.Fetch(pSource:PsrRegSlot):TsrPrivate; begin Assert(pSource<>nil); // Result:=FEmit.specialize New; Result.Init; Result.FPrivId:=FPrivId; Inc(FPrivId); Result.key:=pSource; // FPrivList.Push_tail(Result); end; function TsrPrivateList.FetchCustom(dtype:TsrDataType):TsrPrivate; var pTypeList:PsrTypeList; begin Result:=FEmit.specialize New; Result.Init; Result.FPrivId:=FPrivId; Inc(FPrivId); // if (dtype<>dtUnknow) then begin pTypeList:=FEmit.GetTypeList; Result.Ftype:=pTypeList^.Fetch(dtype); end; // FPrivList.Push_tail(Result); end; function TsrPrivateList.FetchArray(dtype:TsrDataType;array_count:DWORD):TsrPrivate; var pTypeList:PsrTypeList; begin Result:=FEmit.specialize New; Result.Init; Result.InitVar; //// Result.FPrivId:=FPrivId; Inc(FPrivId); // if (dtype<>dtUnknow) then begin pTypeList:=FEmit.GetTypeList; Result.Ftype:=pTypeList^.Fetch(dtype); Result.Ftype:=pTypeList^.FetchArray(Result.Ftype,array_count); end; // FPrivList.Push_tail(Result); end; Function TsrPrivateList.First:TsrPrivate; begin Result:=FPrivList.pHead; end; procedure TsrPrivateList.build_slot_reset(pSlot:PsrRegSlot;var orig:TsrRegNode); begin pSlot^.current:=orig; end; procedure TsrPrivateList.build_slot_ctrue(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); begin //restore if (_next<>nil) then if (RegDownSlot(_next)<>RegDownSlot(prev)) then if _next.pWriter.IsType(ntVolatile) then begin _next.pWriter:=prev; end else begin Assert(false,'build_slot_ctrue'); end; end; procedure TsrPrivateList.build_slot_endif(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); var pLine :TSpirvOp; org,prv :TsrRegNode; cur :TsrRegNode; pVolatile:TsrVolatile; rtype :TsrDataType; cur_c_org:Boolean; cur_c_prv:Boolean; begin org:=RegDownSlot(orig); prv:=RegDownSlot(prev); cur:=RegDownSlot(pSlot^.current); cur_c_org:=CompareReg(cur,org); cur_c_prv:=CompareReg(cur,prv); if cur_c_org and cur_c_prv then begin Exit; end; org:=orig; prv:=prev; cur:=pSlot^.current; pVolatile:=NewVolatile(pSlot); { [orig] if (eval) ( [prev] ) else ( ) fork orig->prev/curr -> next [next] } rtype:=dtUnknow; if (org<>nil) then if (cur_c_org<>cur_c_prv) then //Do not add orig if both values are assigned begin pVolatile.AddStore(org); rtype:=LazyType2(rtype,org.dtype); end; // if (prv<>nil) then if (not cur_c_prv) then //Do not add prev If the value has not changed begin pVolatile.AddStore(prv); rtype:=LazyType2(rtype,prv.dtype); end; // if (cur<>nil) then begin pVolatile.AddStore(cur); pVolatile.FBase:=cur; rtype:=LazyType2(rtype,cur.dtype); end; pLine:=ctx.after; //replace next _next:=pSlot^._New(rtype,pLine); //<-The slot value will not be updated _next.pWriter:=pVolatile; ctx.AddVolatile(pVolatile,_next); pLine.AddParam(_next); //post processing //fixed line _next.CustomLine:=pLine; end; procedure TsrPrivateList.build_slot_break(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); var pLine :TSpirvOp; cur,nxt :TsrRegNode; pVolatile:TsrVolatile; new_vol :Boolean; rtype :TsrDataType; begin cur:=RegDownSlot(pSlot^.current); nxt:=RegDownSlot(_next); if CompareReg(cur,nxt) then begin Exit; end; cur:=pSlot^.current; nxt:=_next; { [orig] while () do [prev] ( if (eval) ( break; --\ ) | | )<---------/ [next] } pVolatile:=nil; //check Volatile if (pVolatile=nil) then begin pVolatile:=NewVolatile(pSlot); new_vol:=True; end else begin new_vol:=False; end; rtype:=dtUnknow; if (nxt<>nil) then begin if new_vol then begin //save if new created pVolatile.AddStore(nxt); end; rtype:=LazyType2(rtype,nxt.dtype); end; // if (cur<>nil) then begin pVolatile.AddStore(cur); pVolatile.FBase:=cur; rtype:=LazyType2(rtype,cur.dtype); end; //save Volatile if new_vol then begin pLine:=ctx.after; //replace next _next:=pSlot^._New(rtype,pLine); //<-The slot value will not be updated _next.pWriter:=pVolatile; ctx.AddVolatile(pVolatile,_next); pLine.AddParam(_next); //post processing //fixed line _next.CustomLine:=pLine; end; if (_next<>nil) then begin //update pref type if (rtype<>dtUnknow) then if (_next.dtype=dtUnknow) then begin _next.PrepType(ord(rtype)); end; end; end; procedure TsrPrivateList.build_slot_conti(var ctx:TsrVolatileContext;pSlot:PsrRegSlot;var orig,prev,_next:TsrRegNode); var pLine :TSpirvOp; cur,prv :TsrRegNode; pVolatile:TsrVolatile; new_vol :Boolean; rtype :TsrDataType; begin cur:=RegDownSlot(pSlot^.current); prv:=RegDownSlot(prev); //Assert(CompareReg(RegDownSlot(orig),RegDownSlot(prev))); if CompareReg(cur,prv) then begin Exit; end; cur:=pSlot^.current; prv:=prev; { [orig] while () do [prev] (<------------\ | if (eval) | ( | continue; --/ ) ) [next] } pVolatile:=nil; //get Volatile if (prv<>nil) then begin if prv.pWriter.IsType(ntVolatile) then begin //prev is volatile pVolatile:=prv.pWriter.specialize AsType; if (pVolatile.FSlot<>pSlot) then begin //Reset if it is another register pVolatile:=nil; end; end; end; //check Volatile if (pVolatile=nil) then begin pVolatile:=NewVolatile(pSlot); new_vol:=True; end else begin new_vol:=False; end; rtype:=dtUnknow; if (prv<>nil) then begin if new_vol then begin Assert(prv.pWriter=orig,'123'); //need to use orig to create a loopback dependency prv:=orig; //save if new created pVolatile.AddStore(prv); end; rtype:=LazyType2(rtype,prv.dtype); end; { if new_vol then begin //use orig if (orig<>nil) then begin //save if new created pVolatile.AddStore(orig); rtype:=LazyType2(rtype,orig.dtype); end; end else begin //use prev if (prv<>nil) then begin rtype:=LazyType2(rtype,prv.dtype); end; end; } // if (cur<>nil) then begin pVolatile.AddStore(cur); pVolatile.FBase:=cur; rtype:=LazyType2(rtype,cur.dtype); end; //save Volatile if new_vol then begin pLine:=ctx.befor; if (prev=nil) then begin //The input register is not defined, should it be initialized to make_copy_slot? prev:=pSlot^._New(rtype,pLine); //<-The slot value will not be updated end; //set backedge dependence prev.pWriter:=pVolatile; ctx.AddVolatile(pVolatile,prev); pLine.AddParam(prev); //post processing //fixed line prev.CustomLine:=pLine; end; if (prev<>nil) then begin //update pref type if (rtype<>dtUnknow) then if (prev.dtype=dtUnknow) then begin prev.PrepType(ord(rtype)); end; end; end; procedure TsrPrivateList.build_volatile_reset(orig:PsrRegsSnapshot); var pRegsStory:PsrRegsStory; begin pRegsStory:=FEmit.GetRegsStory; pRegsStory^.ForEachSnap(@build_slot_reset,orig); end; procedure TsrPrivateList.build_volatile_ctrue(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); var pRegsStory:PsrRegsStory; begin pRegsStory:=FEmit.GetRegsStory; pRegsStory^.ForEachSnap(@build_slot_ctrue,ctx,orig,prev,_next); end; procedure TsrPrivateList.build_volatile_endif(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); var pRegsStory:PsrRegsStory; begin pRegsStory:=FEmit.GetRegsStory; //NextVolatileID; FVolatileID:SizeUint; pRegsStory^.ForEachSnap(@build_slot_endif,ctx,orig,prev,_next); end; procedure TsrPrivateList.build_volatile_break(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); var pRegsStory:PsrRegsStory; begin pRegsStory:=FEmit.GetRegsStory; //NextVolatileID; FVolatileID:SizeUint; pRegsStory^.ForEachSnap(@build_slot_break,ctx,orig,prev,_next); end; procedure TsrPrivateList.build_volatile_conti(var ctx:TsrVolatileContext;orig,prev,_next:PsrRegsSnapshot); var pRegsStory:PsrRegsStory; begin pRegsStory:=FEmit.GetRegsStory; //NextVolatileID; FVolatileID:SizeUint; pRegsStory^.ForEachSnap(@build_slot_conti,ctx,orig,prev,_next); end; procedure TsrPrivateList.make_copy_slot(pSlot:PsrRegSlot); var cur,node:TsrRegNode; pLine:TspirvOp; begin cur:=pSlot^.current; if (cur<>nil) then begin pLine:=FEmit.curr_line; node:=pSlot^.New(cur.dtype,pLine); node.pWriter:=cur; pLine:=FEmit.PostLink(pLine,node); //post processing //fixed line node.CustomLine:=pLine; end; end; procedure TsrPrivateList.make_copy_all; var pRegsStory:PsrRegsStory; begin pRegsStory:=FEmit.GetRegsStory; pRegsStory^.ForEachSlot(@make_copy_slot); end; function get_load_from(r:TsrRegNode):TsrVariable; var pOp:TspirvOp; begin Result:=nil; pOp:=r.pWriter.specialize AsType; if (pOp=nil) then Exit; if (pOp.OpId<>Op.OpLoad) then Exit; Result:=pOp.ParamFirst.Value.specialize AsType; end; function get_load_from2(r:TsrRegNode):TsrVolatile; begin Result:=r.pWriter.specialize AsType; end; procedure _Move(dst,src:TsrVolatile); var node:TStoreNode; begin node:=src.PopStore; While (node<>nil) do begin dst.PushStore(node); node:=src.PopStore; end; end; function calc_most_used_type(V:TsrVolatile):TsrDataType; type t_table=array[TsrDataType] of Integer; var node :TStoreNode; Table:t_table; Count:Integer; i,max:TsrDataType; begin if V.ForceBool then begin Exit(dtBool); end; // Table:=Default(t_table); Count:=0; // node:=V.FList.pHead; While (node<>nil) do begin Inc(Table[RegDown(node.src).dtype]); Inc(Count); // node:=node.pNext; end; // if (Count=0) then begin Result:=dtUnknow; end else if (Count=Table[dtBool]) then begin //Result:=dtBool; Result:=dtUint32; end else begin max:=dtUnknow; For i:=Low(TsrDataType) to High(TsrDataType) do if (i<>dtBool) then begin if ((max=dtUnknow) and (Table[i]<>0)) or (Table[i]>Table[max]) then begin max:=i; end; end; Result:=max; end; end; function TsrPrivateList.PrepVolatile(dst:TspirvOp;src:TsrRegNode):TsrRegNode; //use forward only var tmp:TsrRegNode; pPrivate :TsrPrivate; pVolatile:TsrVolatile; node:TStoreNode; pLine:TspirvOp; //pTmp:TspirvOp; //vtmp:TsrVolatile; dtype:TsrDataType; begin Result:=src; if (src=nil) then Exit; if (not src.pWriter.IsType(ntVolatile)) then Exit; //move to prev Assert(dst<>nil); dst:=flow_prev_up(dst); Assert(dst<>nil); up_merge_line(dst); Assert(dst<>nil); pVolatile:=src.pWriter.specialize AsType; if pVolatile.FSlot^.iUnattach then begin pPrivate:=pVolatile.FPrivate; end else begin pPrivate:=TsrPrivate(pVolatile.FSlot^.FPrivate); end; if (pPrivate=nil) then begin pPrivate:=Fetch(pVolatile.FSlot); if pVolatile.FSlot^.iUnattach then begin pVolatile.FPrivate:=pPrivate; end else begin pVolatile.FSlot^.FPrivate:=pPrivate; end; end; dtype:=calc_most_used_type(pVolatile); dtype:=lazyType2(dtype,StoreType(src.dtype)); dtype:=lazyType2(dtype,dtFloat32); if (dtype=dtBool) and (pVolatile.FSlot^.Name='S0') then begin calc_most_used_type(pVolatile); end; pPrivate.InitVar(); pPrivate .PrepType(dtype); pVolatile.PrepType(dtype); if (pPrivate.GetRegType=dtUnknow) then begin Assert(false); end; node:=pVolatile.PopStore; While (node<>nil) do begin tmp:=RegDown(node.src); if (src<>tmp) {and (pPrivate^.pVar<>get_load_from(tmp))} then begin //pLine:=TsrRegNode(node.pNode).pLine; //pLine:=node.line; pLine:=node.src.pLine; Assert(pLine<>nil); up_merge_line(pLine); {/// if (tmp^.pWriter^.IsType(ntVolatile)) then begin vtmp:=tmp^.pWriter^.AsType(ntVolatile); Assert(vtmp<>nil); _Move(pVolatile,vtmp); tmp^.pWriter:=src; Continue; end; }/// //up_merge_line(pLine); pPrivate.FetchStore(pLine,node.src); end; node:=pVolatile.PopStore; end; //ntVolatile -> src -> next //Opload -> new Result:=src.pSlot^._New(src.dtype,dst); //<-The slot value will not be updated pPrivate.FetchLoad(dst,Result); //before reg end; procedure TsrPrivateList.RemoveAllStore; var node:TsrVolatile; begin node:=FVoltList.pHead; While (node<>nil) do begin node.RemoveAllStore; node:=node.pNext; end; end; Procedure TsrPrivateList.Post; var node:TsrPrivate; begin node:=FPrivList.pHead; While (node<>nil) do begin if node.IsUsed then begin node.SortLines; node.Optimize; node.UpdateRegType; end; node:=node.pNext; end; end; end.