diff --git a/chip/ps4_pssl.pas b/chip/ps4_pssl.pas index 53f7d27c..127b137c 100644 --- a/chip/ps4_pssl.pas +++ b/chip/ps4_pssl.pas @@ -1244,8 +1244,7 @@ type ENCODING:bit6; ADDR:Byte; //(vbindex) - DATA0:Byte; //(vsrc0) - DATA1:Byte; //(vsrc1) + DATA:array[0..1] of Byte; //(vsrc0),(vsrc1) VDST:Byte; end; @@ -3869,7 +3868,7 @@ begin TBUFFER_LOAD_FORMAT_X :str:='TBUFFER_LOAD_FORMAT_X'; TBUFFER_LOAD_FORMAT_XY :str:='TBUFFER_LOAD_FORMAT_XY'; TBUFFER_LOAD_FORMAT_XYZ :str:='TBUFFER_LOAD_FORMAT_XYZ'; - TBUFFER_LOAD_FORMAT_XYZW :str:='TBUFFER_LOAD_FORMAT_XYZ'; + TBUFFER_LOAD_FORMAT_XYZW :str:='TBUFFER_LOAD_FORMAT_XYZW'; TBUFFER_STORE_FORMAT_X :str:='TBUFFER_STORE_FORMAT_X'; TBUFFER_STORE_FORMAT_XY :str:='TBUFFER_STORE_FORMAT_XY'; @@ -4056,22 +4055,22 @@ begin 2,3,4: begin str:=str+'v['+IntToStr(SPI.MIMG.VDATA)+':'+IntToStr(SPI.MIMG.VDATA+t-1)+']'; - str:=str+', '; - str:=str+'v['+IntToStr(SPI.MIMG.VADDR)+':'+IntToStr(SPI.MIMG.VADDR+t-1)+']'; end; else begin str:=str+_get_vdst8(SPI.MIMG.VDATA); - str:=str+', '; - str:=str+_get_vdst8(SPI.MIMG.VADDR); end; end; str:=str+', '; //operand #2 - str:=str+'s['+IntToStr(SPI.MIMG.SRSRC*4)+':'+IntToStr(SPI.MIMG.SRSRC*4+7)+']'; + str:=str+'v['+IntToStr(SPI.MIMG.VADDR)+':'+IntToStr(SPI.MIMG.VADDR+2)+']'; + str:=str+', '; //operand #3 + str:=str+'s['+IntToStr(SPI.MIMG.SRSRC*4)+':'+IntToStr(SPI.MIMG.SRSRC*4+7)+']'; + + //operand #4 Case SPI.MIMG.OP of IMAGE_SAMPLE..IMAGE_SAMPLE_C_CD_CL_O: begin @@ -4376,19 +4375,50 @@ begin //VDST vbindex vsrc0 vsrc1 OFFSET0 OFFSET1 GDS - str:=str+_get_vdst8(SPI.DS.VDST); - str:=str+', '; + //vdst + Case SPI.DS.OP of + DS_ADD_RTN_U32..DS_WRXCHG_RTN_B32, + DS_CMPST_RTN_B32..DS_READ_B32, + DS_READ_I8..DS_ORDERED_COUNT: + begin + str:=str+_get_vdst8(SPI.DS.VDST); + str:=str+', '; + end; + + DS_WRXCHG2_RTN_B32 , + DS_WRXCHG2ST64_RTN_B32, + DS_READ2_B32 , + DS_READ2ST64_B32 , + DS_ADD_RTN_U64..DS_WRXCHG_RTN_B64, + DS_CMPST_RTN_B64..DS_READ_B64, + DS_CONDXCHG32_RTN_B64: + begin + str:=str+_get_vdst8_cnt(SPI.DS.VDST,2); + str:=str+', '; + end; + + DS_WRXCHG2_RTN_B64 , + DS_WRXCHG2ST64_RTN_B64, + DS_READ2_B64 , + DS_READ2ST64_B64 : + begin + str:=str+_get_vdst8_cnt(SPI.DS.VDST,4); + str:=str+', '; + end; + + else; + end; //vbindex str:=str+_get_vdst8(SPI.DS.ADDR); str:=str+', '; //vsrc0 - str:=str+_get_vdst8(SPI.DS.DATA0); + str:=str+_get_vdst8(SPI.DS.DATA[0]); str:=str+', '; //vsrc1 - str:=str+_get_vdst8(SPI.DS.DATA1); + str:=str+_get_vdst8(SPI.DS.DATA[1]); str:=str+' OFFSET:0x'+HexStr(WORD(SPI.DS.OFFSET),4); diff --git a/fpPS4.lpi b/fpPS4.lpi index aea1b988..e073abb1 100644 --- a/fpPS4.lpi +++ b/fpPS4.lpi @@ -1252,10 +1252,6 @@ - - - - diff --git a/spirv/SprvEmit.pas b/spirv/SprvEmit.pas index c7bd32fa..8bb7c4b1 100644 --- a/spirv/SprvEmit.pas +++ b/spirv/SprvEmit.pas @@ -59,6 +59,8 @@ type Procedure InitCs(RSRC1:TCOMPUTE_PGM_RSRC1; RSRC2:TCOMPUTE_PGM_RSRC2); + Procedure cs_set_initial_exec; + Procedure SET_NUM_THREADS(NTX:TCOMPUTE_NUM_THREAD_X; NTY:TCOMPUTE_NUM_THREAD_Y; NTZ:TCOMPUTE_NUM_THREAD_Z); @@ -706,6 +708,53 @@ begin AddCapability(Capability.Shader); end; +Procedure TSprvEmit.cs_set_initial_exec; +var + total:PtrUint; + val:PtrUint; + + vec:TsrRegNode; + src:array[0..2] of TsrRegNode; +begin + if not Config.UseExtendedEXECMask then Exit; + + total:=FLocalSize.x*FLocalSize.y*FLocalSize.z; + val:=not PtrUint(0); + + if (total<64) then + begin + val:=(PtrUint(1) shl total)-1; + end else + if ((total mod 64)=0) then + begin + val:=not PtrUint(0); + end else + if (total>64) then + begin + Assert(false,'TODO: big unaligned total LocalSize'); + end; + + SetConst_q(get_exec0,dtUnknow,val and (not DWORD(0))); + SetConst_q(get_exec1,dtUnknow,val shr 32); + + vec:=AddInput(@RegsStory.FUnattach,dtVec3u,itThreadId,0); + + src[0]:=RegsStory.FUnattach.New(dtUint32); + src[1]:=RegsStory.FUnattach.New(dtUint32); + src[2]:=RegsStory.FUnattach.New(dtUint32); + + OpExtract(init_line,src[0],vec,0); + OpExtract(init_line,src[1],vec,1); + OpExtract(init_line,src[2],vec,2); + + FThread_id:=OpIMulTo(OpIMulTo(src[0],src[1]),src[2]); + + if (total>64) then + begin + FThread_id:=OpAndTo(FThread_id,63); + end; +end; + Procedure TSprvEmit.SET_NUM_THREADS(NTX:TCOMPUTE_NUM_THREAD_X; NTY:TCOMPUTE_NUM_THREAD_Y; NTZ:TCOMPUTE_NUM_THREAD_Z); @@ -721,6 +770,8 @@ begin if (FLocalSize.x=0) then FLocalSize.x:=1; if (FLocalSize.y=0) then FLocalSize.y:=1; if (FLocalSize.z=0) then FLocalSize.z:=1; + // + cs_set_initial_exec; end; Procedure TSprvEmit.InitCustomGs(); diff --git a/spirv/emit_ds.pas b/spirv/emit_ds.pas index 35585b4f..901760cf 100644 --- a/spirv/emit_ds.pas +++ b/spirv/emit_ds.pas @@ -193,25 +193,19 @@ begin lvl_0.size :=stride; lvl_0.offset:=offset; - //region_addr = (OFFSET + vbindex) & alignment if vbindex.is_const then begin + //#static + //i = #(OFFSET + vbindex) & alignment + lvl_0.offset:=lvl_0.offset + vbindex.AsConst.GetData; - lvl_0.offset:=lvl_0.offset and (not (stride-1)); + lvl_0.offset:=lvl_0.offset and (not (stride-1)); //4,8 Result:=pLayout.Fetch(@lvl_0,nil,cflags(atomic)); end else - if ((lvl_0.offset mod stride)=0) then - begin - //i = OFFSET + (vbindex / stride) - - lvl_1.pIndex:=OpIDivTo(vbindex,stride); - lvl_1.stride:=stride; - - Result:=pLayout.Fetch(@lvl_0,@lvl_1,cflags(atomic)); - end else begin + //#dynamic //i = (vbindex + OFFSET) / stride lvl_1.pIndex:=OpIAddTo(vbindex,lvl_0.offset); @@ -236,14 +230,14 @@ begin if (rtype.BitSize=64) then begin - vsrc:=fetch_vdst8_64(FSPI.DS.DATA0,dtUint64); + vsrc:=fetch_vdst8_64(FSPI.DS.DATA[0],dtUint64); end else if (rtype.BitSize=32) then begin - vsrc:=fetch_vdst8(FSPI.DS.DATA0,rtype); + vsrc:=fetch_vdst8(FSPI.DS.DATA[0],rtype); end else begin - vsrc:=fetch_vdst8(FSPI.DS.DATA0,dtUnknow); + vsrc:=fetch_vdst8(FSPI.DS.DATA[0],dtUnknow); end; case rtype of @@ -260,10 +254,10 @@ end; //vbindex, vsrc0[], vsrc1[] [OFFSET0:<0..255>] [OFFSET1:<0..255>] [GDS:< 0|1>] procedure TEmit_DS.emit_DS_WRITE2(rtype:TsrDataType;extra_stride:Word); var - pChain:array[0..1] of TsrChain; + pChain:array[0..3] of TsrChain; vbindex:TsrRegNode; - vsrc:array[0..1] of TsrRegNode; + vsrc:array[0..3] of TsrRegNode; i,hi:Byte; begin @@ -273,15 +267,41 @@ begin if (rtype.BitSize=64) then begin + for i:=0 to hi do begin - vsrc[i]:=fetch_vdst8_64(PBYTE(@FSPI.DS.DATA0)[i],dtUint64); + vsrc[i*2+0]:=fetch_vdst8(FSPI.DS.DATA[i]+0,dtUint32); + vsrc[i*2+1]:=fetch_vdst8(FSPI.DS.DATA[i]+1,dtUint32); end; + + for i:=0 to hi do + begin + pChain[i*2+0]:=fetch_ds_chain(vbindex,dtUint32,dtUnknow,FSPI.DS.OFFSET[i]*(8)*extra_stride+0); + pChain[i*2+1]:=fetch_ds_chain(vbindex,dtUint32,dtUnknow,FSPI.DS.OFFSET[i]*(8)*extra_stride+4); + end; + + for i:=0 to hi do + begin + FetchStore(pChain[i*2+0],vsrc[i*2+0]); + FetchStore(pChain[i*2+1],vsrc[i*2+1]); + end; + + exit; + + { + Assert(false,'DS_WRITE2 64'); + + for i:=0 to hi do + begin + vsrc[i]:=fetch_vdst8_64(FSPI.DS.DATA[i],dtUint64); + end; + } + end else begin for i:=0 to hi do begin - vsrc[i]:=fetch_vdst8(PBYTE(@FSPI.DS.DATA0)[i],rtype); + vsrc[i]:=fetch_vdst8(FSPI.DS.DATA[i],rtype); end; end; @@ -338,10 +358,10 @@ end; procedure TEmit_DS.emit_DS_READ2(rtype:TsrDataType;extra_stride:Word); var - pChain:array[0..1] of TsrChain; + pChain:array[0..3] of TsrChain; vbindex:TsrRegNode; - vdst:array[0..1] of TsrRegNode; + vdst:array[0..3] of TsrRegNode; dst:array[0..3] of PsrRegSlot; @@ -351,6 +371,33 @@ begin hi:=ord(FSPI.DS.OFFSET[0]<>FSPI.DS.OFFSET[1]); + if (rtype.BitSize=64) then + begin + + for i:=0 to hi do + begin + pChain[i*2+0]:=fetch_ds_chain(vbindex,dtUint32,dtUnknow,FSPI.DS.OFFSET[i]*(8)*extra_stride+0); + pChain[i*2+1]:=fetch_ds_chain(vbindex,dtUint32,dtUnknow,FSPI.DS.OFFSET[i]*(8)*extra_stride+4); + end; + + for i:=0 to hi do + begin + vdst[i*2+0]:=FetchLoad(pChain[i*2+0],dtUint32); + vdst[i*2+1]:=FetchLoad(pChain[i*2+1],dtUint32); + end; + + for i:=0 to hi do + begin + dst[i*2+0]:=get_vdst8(FSPI.DS.VDST+i*2+0); + dst[i*2+1]:=get_vdst8(FSPI.DS.VDST+i*2+1); + + MakeCopy(dst[i*2+0],vdst[i*2+0]); + MakeCopy(dst[i*2+1],vdst[i*2+1]); + end; + + exit; + end; + for i:=0 to hi do begin pChain[i]:=fetch_ds_chain(vbindex,rtype,dtUnknow,FSPI.DS.OFFSET[i]*(rtype.BitSize div 8)*extra_stride); @@ -398,14 +445,14 @@ begin if (rtype.BitSize=64) then begin - vsrc:=fetch_vdst8_64(FSPI.DS.DATA0,dtUint64); + vsrc:=fetch_vdst8_64(FSPI.DS.DATA[0],dtUint64); end else if (rtype.BitSize=32) then begin - vsrc:=fetch_vdst8(FSPI.DS.DATA0,rtype); + vsrc:=fetch_vdst8(FSPI.DS.DATA[0],rtype); end else begin - vsrc:=fetch_vdst8(FSPI.DS.DATA0,dtUnknow); + vsrc:=fetch_vdst8(FSPI.DS.DATA[0],dtUnknow); end; case rtype of diff --git a/spirv/emit_exp.pas b/spirv/emit_exp.pas index d0a411b5..fae51996 100644 --- a/spirv/emit_exp.pas +++ b/spirv/emit_exp.pas @@ -8,7 +8,8 @@ uses sysutils, ps4_pssl, si_ci_vi_merged_enum, - srCFGLabel, + srCFGCursor, + srCFGParser, srConfig, srFlow, srType, @@ -220,12 +221,12 @@ begin if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then begin parent:=AllocBlockOp; - parent.SetInfo(btOther,Cursor.Adr,Cursor.Adr); + parent.SetInfo(btOther); - PushBlockOp(line,parent); + PushBlockOp(line,parent,Default(TsrCursor)); Inc(push_count); - exc:=MakeRead(get_exec0,dtBool); //It means that lane_id=0 + exc:=GetThreadBit(get_exec0,get_exec1,dtBool); node:=AddSpirvOp(srOpInternal.OpMakeExp); node.AddParam(exc); //<-fetch read end; @@ -246,9 +247,9 @@ begin end; pOpBlock:=AllocBlockOp; //down - pOpBlock.SetInfo(btOther,Cursor.Adr,Cursor.Adr); + pOpBlock.SetInfo(btOther); - PushBlockOp(line,pOpBlock); + PushBlockOp(line,pOpBlock,Default(TsrCursor)); Inc(push_count); if (parent<>nil) then diff --git a/spirv/emit_fetch.pas b/spirv/emit_fetch.pas index 5b156afb..e6eef43e 100644 --- a/spirv/emit_fetch.pas +++ b/spirv/emit_fetch.pas @@ -54,9 +54,7 @@ type function fetch_vdst8(VDST:Word;rtype:TsrDataType):TsrRegNode; function fetch_vdst8_64(VDST:Word;rtype:TsrDataType):TsrRegNode; // - procedure MakeCopy64(dst0,dst1:PsrRegSlot;src:TsrRegNode); - // - procedure OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); + procedure OpCmpV(OpId:DWORD;dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); procedure OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); procedure OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:TsrRegNode); // @@ -260,7 +258,7 @@ begin if (pImm=nil) then Exit; if (pImm.AsUint32<>8) then Exit; - reg:=RegDown(pSelect.ParamNode(2).AsReg); + reg:=RegDown(pSelect.ParamNode(1).AsReg); if (reg=nil) then Exit; pBitwiseAnd:=reg.pWriter.specialize AsType; @@ -281,7 +279,7 @@ begin end; //final - reg:=RegDown(pSelect.ParamNode(1).AsReg); + reg:=RegDown(pSelect.ParamNode(2).AsReg); if (reg=nil) then Exit; regs[0]:=reg; @@ -513,7 +511,6 @@ end; function TEmitFetch.fetch_vdst8_64(VDST:Word;rtype:TsrDataType):TsrRegNode; var src:array[0..1] of TsrRegNode; - dst:TsrRegNode; begin src[0]:=fetch_vdst8(VDST+0,dtUint32); src[1]:=fetch_vdst8(VDST+1,dtUint32); @@ -523,31 +520,12 @@ begin Assert(False); end; - dst:=NewReg(dtVec2u); - OpMakeCon(line,dst,@src); - - Result:=BitcastList.FetchRead(rtype,dst); + Result:=fetch64(@src,rtype); end; // -procedure TEmitFetch.MakeCopy64(dst0,dst1:PsrRegSlot;src:TsrRegNode); -var - dst:TsrRegNode; - node:array[0..1] of TsrRegNode; -begin - dst:=BitcastList.FetchRead(dtVec2u,src); - - node[0]:=dst0^.New(dtUint32,line); - node[1]:=dst1^.New(dtUint32,line); - - OpExtract(line,node[0],dst,0); - OpExtract(line,node[1],dst,1); -end; - -// - -procedure TEmitFetch.OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); +procedure TEmitFetch.OpCmpV(OpId:DWORD;dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); Var tmp:TsrRegNode; exc:TsrRegNode; @@ -565,8 +543,11 @@ begin _Op2(line,OpId,tmp,src0,src1); - exc:=MakeRead(get_exec0,dtBool); - OpLogicalAnd(dst,tmp,exc); + exc:=GetThreadBit(get_exec0,get_exec1,dtBool); + + exc:=OpLogicalAndTo(tmp,exc); + + SetThreadBit(dst0,dst1,exc); end; procedure TEmitFetch.OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); diff --git a/spirv/emit_op.pas b/spirv/emit_op.pas index 4b401da5..32b68188 100644 --- a/spirv/emit_op.pas +++ b/spirv/emit_op.pas @@ -12,7 +12,7 @@ uses srConst, srReg, srOp, - srCFGLabel, + srCFGParser, srOpInternal, srOpUtils, srCacheOp, @@ -20,6 +20,15 @@ uses type TEmitOp=class(TEmitInterface) + // + procedure MakeCopy64(dst0,dst1:PsrRegSlot;src:TsrRegNode); + function GetThreadBit(exe0,exe1:PsrRegSlot;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode; + procedure SetThreadBit(exe0,exe1:PsrRegSlot;val:TsrRegNode); + // + function fetch_vccnz (ppLine:PPspirvOp):TsrRegNode; + function fetch_execnz(ppLine:PPspirvOp):TsrRegNode; + function fetch_execnz_tid(ppLine:PPspirvOp):TsrRegNode; + function fetch_scc :TsrRegNode; // function _Op1(pLine:TspirvOp;OpId:DWORD;dst,src:TsrRegNode):TspirvOp; function _Op2(pLine:TspirvOp;OpId:DWORD;dst,src0,src1:TsrRegNode):TspirvOp; @@ -73,8 +82,8 @@ type procedure OpFmaI32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode); procedure OpFmaU32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode); // - procedure OpSelect(dst:PsrRegSlot;src_false,src_true,cond:TsrRegNode); - function OpSelectTo(src_false,src_true,cond:TsrRegNode):TsrRegNode; + procedure OpSelect(dst:PsrRegSlot;cond,src_true,src_false:TsrRegNode); + function OpSelectTo(cond,src_true,src_false:TsrRegNode):TsrRegNode; // procedure OpIAddCar(pLine:TspirvOp;dst,car,src0,src1:TsrRegNode); procedure OpIAddExt(dst,car:PsrRegSlot;src0,src1:TsrRegNode;rtype:TsrDataType); @@ -91,6 +100,7 @@ type // function OpBFITo (src0,src1,src2,src3:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; function OpBFUETo(src0,src1,src2:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; + function OpBFSETo(src0,src1,src2:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; // procedure OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:TsrRegNode); // @@ -111,6 +121,8 @@ type function OpMakeCon(pLine:TspirvOp;dst:TsrRegNode;src:PPsrRegNode):TspirvOp; function OpMakeVec(pLine:TspirvOp;rtype:TsrDataType;src:PPsrRegNode):TsrRegNode; function OpMakeCub(pLine:TspirvOp;rtype:TsrDataType;src:PPsrRegNode):TsrRegNode; + function fetch64 (src:PPsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode; + function fetch64 (src0,src1:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode; function OpSampledImage(pLine:TspirvOp;Tgrp,Sgrp:TsrNode;dtype:TsrDataType;info:TsrTypeImageInfo):TsrRegSampledImage; // procedure OpIAdd(dst:PsrRegSlot;src0,src1:TsrRegNode); @@ -163,6 +175,8 @@ type function OpOrTo (src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; function OpAndTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; function OpAndTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode; + function OpLogicalOrTo (src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; + function OpLogicalAndTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; // function OpIsSSignTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; function OpIEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; @@ -209,6 +223,123 @@ end; // +procedure TEmitOp.MakeCopy64(dst0,dst1:PsrRegSlot;src:TsrRegNode); +var + dst:TsrRegNode; + node:array[0..1] of TsrRegNode; +begin + dst:=BitcastList.FetchRead(dtVec2u,src); + + node[0]:=dst0^.New(dtUint32,line); + node[1]:=dst1^.New(dtUint32,line); + + OpExtract(line,node[0],dst,0); + OpExtract(line,node[1],dst,1); +end; + +function TEmitOp.GetThreadBit(exe0,exe1:PsrRegSlot;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode; +var + mask:TsrRegNode; +begin + if Config.UseExtendedEXECMask and (FExecutionModel=ExecutionModel.GLCompute) then + begin + mask:=fetch64(MakeRead(exe0,dtUint32),MakeRead(exe1,dtUint32),dtUint64,ppLine); + + Result:=OpShrTo(mask,FThread_id,ppLine); + Result:=OpUToU (Result,dtUint32,ppLine); + Result:=OpAndTo(Result,1,ppLine); + Result.PrepType(ord(dtUint32)); + Result:=BitcastList.FetchRead(rtype,Result); + + //Result:=OpBFUETo(mask,FThread_id,NewImm_i(dtUint32,1)); + //Result:=OpUToU(Result,dtUint32); + //Result:=BitcastList.FetchRead(rtype,Result); + end else + begin + //It means that lane_id=0 + Result:=MakeRead(exe0,rtype); + end; +end; + +procedure TEmitOp.SetThreadBit(exe0,exe1:PsrRegSlot;val:TsrRegNode); +var + mask,mask2:TsrRegNode; +begin + if Config.UseExtendedEXECMask and (FExecutionModel=ExecutionModel.GLCompute) then + begin + + val:=BitcastList.FetchRead(dtUint32,val); + val:=OpUToU (val,dtUint64); + val:=OpShlTo(val,FThread_id); + + mask:=fetch64(MakeRead(exe0,dtUint32),MakeRead(exe1,dtUint32),dtUint64); + + mask2:=OpShlTo(NewImm_i(dtUint64,1),FThread_id); + mask2:=OpNotTo(mask2); + mask2.PrepType(ord(dtUint64)); + + mask:=OpAndTo(mask,mask2); + mask.PrepType(ord(dtUint64)); + + mask:=OpOrTo(mask,val); + mask.PrepType(ord(dtUint64)); + + MakeCopy64(exe0,exe1,mask); + + //val:=BitcastList.FetchRead(dtUint32,val); + //val:=OpUToU(val,dtUint64); + //mask:=fetch64(exe0^.current,exe1^.current,dtUint64); + //mask:=OpBFITo(mask,val,FThread_id,NewImm_i(dtUint32,1)); + //MakeCopy64(exe0,exe1,mask); + // + end else + begin + //It means that lane_id=0 + MakeCopy (exe0,val); + SetConst_q(exe1,dtUnknow,0); //set zero + end; +end; + +// + +function TEmitOp.fetch_vccnz(ppLine:PPspirvOp):TsrRegNode; +var + src:array[0..1] of TsrRegNode; +begin + //It means that (vcc0 != 0) || (vcc1 != 0) + + src[0]:=MakeRead(get_vcc0,dtBool); //implict cast (int != 0) + src[1]:=MakeRead(get_vcc1,dtBool); //implict cast (int != 0) + + Result:=OpLogicalOrTo(src[0],src[1],ppLine); +end; + +function TEmitOp.fetch_execnz(ppLine:PPspirvOp):TsrRegNode; +var + src:array[0..1] of TsrRegNode; +begin + //It means that (exec0 != 0) || (exec1 != 0) + + src[0]:=MakeRead(get_exec0,dtBool); //implict cast (int != 0) + src[1]:=MakeRead(get_exec1,dtBool); //implict cast (int != 0) + + Result:=OpLogicalOrTo(src[0],src[1],ppLine); +end; + +function TEmitOp.fetch_execnz_tid(ppLine:PPspirvOp):TsrRegNode; +begin + //It means that (exec[thread_id:] == 0) + + Result:=GetThreadBit(get_exec0,get_exec1,dtBool,ppLine); +end; + +function TEmitOp.fetch_scc:TsrRegNode; +begin + Result:=MakeRead(get_scc,dtBool); +end; + +// + function TEmitOp._Op1(pLine:TspirvOp;OpId:DWORD;dst,src:TsrRegNode):TspirvOp; Var node:TspirvOp; @@ -640,14 +771,14 @@ end; // -procedure TEmitOp.OpSelect(dst:PsrRegSlot;src_false,src_true,cond:TsrRegNode); +procedure TEmitOp.OpSelect(dst:PsrRegSlot;cond,src_true,src_false:TsrRegNode); begin - Op3(Op.OpSelect,LazyType2(src_false.dtype,src_true.dtype),dst,cond,src_true,src_false); + Op3(Op.OpSelect,LazyType2(src_true.dtype,src_false.dtype),dst,cond,src_true,src_false); end; -function TEmitOp.OpSelectTo(src_false,src_true,cond:TsrRegNode):TsrRegNode; +function TEmitOp.OpSelectTo(cond,src_true,src_false:TsrRegNode):TsrRegNode; begin - Result:=NewReg(LazyType2(src_false.dtype,src_true.dtype)); + Result:=NewReg(LazyType2(src_true.dtype,src_false.dtype)); // _Op3(line,Op.OpSelect,Result,cond,src_true,src_false); end; @@ -795,6 +926,12 @@ begin _set_line(ppLine,_Op3(_get_line(ppLine),Op.OpBitFieldUExtract,Result,src0,src1,src2)); end; +function TEmitOp.OpBFSETo(src0,src1,src2:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; +begin + Result:=NewReg(src0.dtype); + _set_line(ppLine,_Op3(_get_line(ppLine),Op.OpBitFieldSExtract,Result,src0,src1,src2)); +end; + // procedure TEmitOp.OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:TsrRegNode); @@ -1022,6 +1159,65 @@ begin end; end; +type + t_bridge_info=record + val:TsrRegNode; + pos:PtrUint; + end; + +function get_bridge(src:TsrRegNode):t_bridge_info; +var + pLine:TSpirvOp; +begin + Result:=Default(t_bridge_info); + + pLine:=src.pWriter.specialize AsType; + if (pLine=nil) then Exit; + if (pLine.OpId<>Op.OpCompositeExtract) then Exit; + + if not pLine.ParamNode(1).TryGetValue(Result.pos) then Exit; + + Result.val:=pLine.ParamNode(0).AsReg; +end; + +function TEmitOp.fetch64(src:PPsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode; +var + bri:array[0..1] of t_bridge_info; + dst:TsrRegNode; +begin + bri[0]:=get_bridge(src[0]); + bri[1]:=get_bridge(src[1]); + + dst:=nil; + + if (bri[0].val<>nil) and + (bri[0].val=bri[1].val) and + (bri[0].pos=0) and + (bri[1].pos=1) then + if (bri[0].val.dtype.Count=2) then + begin + dst:=bri[0].val; + end; + + if (dst=nil) then + begin + dst:=NewReg(dtVec2u); + _set_line(ppLine,OpMakeCon(_get_line(ppLine),dst,src)); + end; + + Result:=BitcastList.FetchRead(rtype,dst); +end; + +function TEmitOp.fetch64(src0,src1:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode; +var + src:array[0..1] of TsrRegNode; +begin + src[0]:=src0; + src[1]:=src1; + + Result:=fetch64(@src,rtype,ppLine); +end; + Function FindByHalfSpace(node:TspirvOp;pDst:TsrNode):Boolean; begin Result:=False; @@ -1030,7 +1226,7 @@ begin if (node.pDst=pDst) then Exit(True); // if node.IsType(ntOpBlock) then - if IsReal(TsrOpBlock(node).Block.bType) then + if IsReal(TsrOpBlock(node).bType) then begin Exit(False); end; @@ -1439,6 +1635,20 @@ end; // +function TEmitOp.OpLogicalOrTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; +begin + Result:=NewReg(dtBool); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpLogicalOr,Result,src0,src1)); //post type +end; + +function TEmitOp.OpLogicalAndTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; +begin + Result:=NewReg(dtBool); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpLogicalAnd,Result,src0,src1)); //post type +end; + +// + function TEmitOp.OpIsSSignTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode; var zero:TsrRegNode; diff --git a/spirv/emit_post.pas b/spirv/emit_post.pas index a9497944..f3d8a136 100644 --- a/spirv/emit_post.pas +++ b/spirv/emit_post.pas @@ -247,6 +247,32 @@ begin until false; end; +function CompareTypeOp(OpId:DWORD;rtype1,rtype2:TsrDataType):Boolean; +var + relax:Boolean; +begin + Case OpId of + Op.OpLoad , + Op.OpImageRead , + Op.OpImageWrite , + Op.OpBitFieldSExtract , + Op.OpBitFieldUExtract , + Op.OpSelect , + Op.OpIAddCarry , + Op.OpISubBorrow , + Op.OpUMulExtended , + Op.OpSMulExtended , + Op.OpCompositeConstruct:relax:=False; + else + relax:=True; + end; + + Case relax of + True :Result:=CompareType(rtype1,rtype2); + False:Result:=(rtype1=rtype2); + end; +end; + function TSprvEmit_post.RegCollapse(pLine:TspirvOp;var node:TsrRegNode):Integer; var rold,rnew:TsrRegNode; @@ -260,7 +286,7 @@ begin if (rold<>rnew) then //is change? begin - if (rnew.dtype=dtUnknow) or CompareType(rnew.dtype,rold.dtype) then + if (rnew.dtype=dtUnknow) or CompareTypeOp(pLine.OpId,rnew.dtype,rold.dtype) then begin rnew.PrepType(ord(rold.dtype)); if (rnew.dtype<>dtUnknow) then @@ -291,6 +317,8 @@ begin Result:=0; if (node=nil) then Exit; + //if not (node.IsUsed) then Exit; + old:=node; node:=RegDown(old); @@ -609,6 +637,15 @@ function TSprvEmit_post.OnOpStep4(node:TspirvOp):Integer; //forward begin Result:=0; + { + //prior + if node.is_post then + begin + Result:=Result+EnumLineRegs(@RegVResolve,node); + Exit; + end; + } + if node.is_cleared then Exit; if node.can_clear then @@ -972,6 +1009,11 @@ begin rtGDS:max:=64*1024; end; + if (max=0) then + begin + Assert(false,'Access to LDS/GDS and the maximum is 0?'); + end; + if (Align(_offset,pChain.stride)>max) then begin Assert(false,'LDS/GDS big addresing?'); @@ -1006,7 +1048,10 @@ begin //patch dtype dtype:=F.pField.Fdtype.Child; end; - frValueInArray :ShiftIndex(pChain,F,_offset); + frValueInArray : + begin + ShiftIndex(pChain,F,_offset); + end; end; until false; diff --git a/spirv/emit_post_op.pas b/spirv/emit_post_op.pas index b582a209..8c880b72 100644 --- a/spirv/emit_post_op.pas +++ b/spirv/emit_post_op.pas @@ -9,7 +9,7 @@ uses bittype, Half16, spirv, - srCFGLabel, + srCFGParser, srNode, srType, srTypes, @@ -181,6 +181,8 @@ begin dtBool :Result:=dtBool; dtInt32, dtUint32:Result:=dtUint32; + dtInt64, + dtUint64:Result:=dtUint64; else Result:=dtUnknow; end; @@ -196,7 +198,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -204,7 +206,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -346,7 +348,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -354,7 +356,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -482,7 +484,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -490,7 +492,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -646,7 +648,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -654,7 +656,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -710,7 +712,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -800,7 +802,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -850,7 +852,7 @@ begin Op.OpLabel, Op.OpSelectionMerge, Op.OpBranch, - Op.OpBranchConditional:node.mark_not_used(True); + Op.OpBranchConditional:node.mark([soNotUsed,soForce]); else; end; // @@ -904,6 +906,9 @@ var cst :TsrConst; begin Result:=0; + + //exit; + src:=RegDown(node.ParamNode(0).AsReg); if (src=nil) then Exit; @@ -927,10 +932,10 @@ begin //Get merge block pMerg:=pCond.Parent; - Assert(pMerg.Block.bType=btMerg); + Assert(pMerg.bType=btMerg); //set type - pMerg.Block.bType:=btOther; + pMerg.bType:=btOther; _restore(pCond.vctx); @@ -938,7 +943,7 @@ begin //PrivateList.build_volatile_ctrue(pCond.pAfter,pCond.Regs.orig,pCond.Regs.prev,pCond.Regs.next); //set type - pCond.Block.bType:=btOther; + pCond.bType:=btOther; //clear instructions mark_not_used_branch_op(pMerg); @@ -991,7 +996,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1038,7 +1043,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1075,7 +1080,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1084,7 +1089,7 @@ var begin Assert(dtype=dtFloat32); dst.pWriter:=NewImm_s(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1092,7 +1097,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1240,7 +1245,7 @@ begin dst.pWriter:=pc; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1294,7 +1299,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1302,7 +1307,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1381,7 +1386,7 @@ var begin Assert(dtype=dtFloat32); dst.pWriter:=NewImm_s(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1422,7 +1427,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1430,7 +1435,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1476,7 +1481,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1510,7 +1515,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1600,7 +1605,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1735,7 +1740,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1800,7 +1805,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1808,7 +1813,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1856,7 +1861,7 @@ begin //else - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; rmax:=OpUMaxTo(src[0],src[1],@node); //update line @@ -1889,7 +1894,7 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin dst.pWriter:=NewImm_q(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -1897,7 +1902,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -2005,12 +2010,14 @@ begin dst.pWriter:=cret; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end else begin + src:=node.ParamNode(1).AsReg; + pLine:=src.pLine; vint6:=NewImm_i(dtInt32,6); @@ -2018,32 +2025,21 @@ begin Case count of 1: begin - rvec[0]:=NewReg(dtInt32); - - pLine:=_Op3(pLine,Op.OpBitFieldSExtract,rvec[0],src,NewImm_i(dtInt32, 0),vint6); - - src:=rvec[0]; + src:=OpBFSETo(src,NewImm_i(dtInt32,0),vint6,@pLine); end; 2: begin - rvec[0]:=NewReg(dtInt32); - rvec[1]:=NewReg(dtInt32); - - pLine:=_Op3(pLine,Op.OpBitFieldSExtract,rvec[0],src,NewImm_i(dtInt32, 0),vint6); - pLine:=_Op3(pLine,Op.OpBitFieldSExtract,rvec[1],src,NewImm_i(dtInt32, 8),vint6); + rvec[0]:=OpBFSETo(src,NewImm_i(dtInt32,0),vint6,@pLine); + rvec[1]:=OpBFSETo(src,NewImm_i(dtInt32,8),vint6,@pLine); src:=NewReg(dtVec2i); pLine:=OpMakeCon(pLine,src,@rvec); end; 3: begin - rvec[0]:=NewReg(dtInt32); - rvec[1]:=NewReg(dtInt32); - rvec[2]:=NewReg(dtInt32); - - pLine:=_Op3(pLine,Op.OpBitFieldSExtract,rvec[0],src,NewImm_i(dtInt32, 0),vint6); - pLine:=_Op3(pLine,Op.OpBitFieldSExtract,rvec[1],src,NewImm_i(dtInt32, 8),vint6); - pLine:=_Op3(pLine,Op.OpBitFieldSExtract,rvec[2],src,NewImm_i(dtInt32,16),vint6); + rvec[0]:=OpBFSETo(src,NewImm_i(dtInt32, 0),vint6,@pLine); + rvec[1]:=OpBFSETo(src,NewImm_i(dtInt32, 8),vint6,@pLine); + rvec[2]:=OpBFSETo(src,NewImm_i(dtInt32,16),vint6,@pLine); src:=NewReg(dtVec3i); pLine:=OpMakeCon(pLine,src,@rvec); @@ -2055,7 +2051,7 @@ begin dst.dtype :=src.dtype; dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); @@ -2331,7 +2327,7 @@ begin dst.pWriter:=rsl; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Exit; @@ -2402,7 +2398,7 @@ begin Assert(False); end; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; end; @@ -2445,7 +2441,7 @@ begin _Op4(pLine,Op.OpBitFieldInsert,dst,src[1],src[0],rIndex,rCount); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Exit; @@ -2466,7 +2462,7 @@ begin _Op2(pLine,Op.OpBitwiseOr,dst,src[0],src[1]); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; end; @@ -2761,7 +2757,7 @@ begin MakeVecComp(node,dtVec3f,dst,@src); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Result:=1; end; @@ -2774,7 +2770,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -2797,7 +2793,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -2820,7 +2816,7 @@ var procedure _SetReg(src:TsrRegNode); begin dst.pWriter:=src; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -2843,7 +2839,7 @@ var begin Assert(dtype=dtFloat32); dst.pWriter:=NewImm_s(dtype,value,node); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; Inc(Result); end; @@ -2940,7 +2936,7 @@ begin MakeVecComp(node,rtype,dst,@src); - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; end; @@ -2950,7 +2946,7 @@ begin if is_term_op(flow_down_prev_up(node)) then begin - node.mark_not_used; + node.mark([soNotUsed]); Inc(Result); end; @@ -2963,7 +2959,6 @@ var pChild:TsrOpBlock; pBegOp,pEndOp,pMrgOp:TspirvOp; exc:TsrRegNode; - b_adr:TSrcAdr; begin Result:=1; @@ -2974,7 +2969,7 @@ begin if exc.is_const then begin - node.mark_not_used; + node.mark([soNotUsed]); Case exc.AsConst.AsBool of True : //is always store @@ -3011,7 +3006,7 @@ begin Op.OpNop:; Op.OpKill:; else - node.mark_not_used(True); + node.mark([soNotUsed,soForce]); end; end; node:=node.Next; @@ -3024,9 +3019,7 @@ begin //reread exc:=node.ParamNode(0).AsReg; - node.mark_not_used; - - b_adr:=pOpBlock.Block.b_adr; + node.mark([soNotUsed]); pLine:=node.Next; if (pLine=nil) then //kill or nop @@ -3036,11 +3029,8 @@ begin pEndOp:=NewLabelOp(False); //end pMrgOp:=pEndOp; //merge - pBegOp.Adr:=b_adr; - pEndOp.Adr:=b_adr; - pOpBlock.SetLabels(pBegOp,pEndOp,pMrgOp); - pOpBlock.Block.bType:=btCond; + pOpBlock.bType:=btCond; pOpBlock.SetCond(exc,false); //reverse pLine:=node; @@ -3049,7 +3039,7 @@ begin pLine:=AddSpirvOp (pLine,pBegOp); pChild:=AllocBlockOp; //create new - pChild.SetInfo(btOther,b_adr,b_adr); + pChild.SetInfo(btOther); pChild.dummy.OpId:=Op.OpKill; //set kill to dummy pOpBlock.pBody:=pChild; @@ -3067,15 +3057,11 @@ begin pEndOp:=NewLabelOp(False); //end pMrgOp:=NewLabelOp(False); //merge - pBegOp.Adr:=b_adr; - pEndOp.Adr:=b_adr; - pMrgOp.Adr:=b_adr; - pOpBlock.SetLabels(pBegOp,pEndOp,pMrgOp); - pOpBlock.Block.bType:=btCond; + pOpBlock.bType:=btCond; pOpBlock.SetCond(exc,false); //reverse - pOpBlock.pElse.Block.bType:=btElse; + pOpBlock.pElse.bType:=btElse; pLine:=node; pLine:=OpCondMerge (pLine,pMrgOp); @@ -3083,7 +3069,7 @@ begin pLine:=AddSpirvOp (pLine,pBegOp); pChild:=AllocBlockOp; //create new - pChild.SetInfo(btOther,b_adr,b_adr); + pChild.SetInfo(btOther); pChild.dummy.OpId:=Op.OpKill; //set kill to dummy pOpBlock.pBody:=pChild; @@ -3124,7 +3110,7 @@ begin if (src[0]=nil) or (src[1]=nil) then Exit; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; if (car.IsUsed) then //carry is use @@ -3155,7 +3141,7 @@ begin if (src[0]=nil) or (src[1]=nil) then Exit; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; if (bor.IsUsed) then //borrow is use @@ -3186,7 +3172,7 @@ begin if (src[0]=nil) or (src[0]=nil) or (src[1]=nil) then Exit; - node.mark_not_used; + node.mark([soNotUsed]); node.pDst:=nil; num4 :=NewImm_q(dtUint32, 4,node); diff --git a/spirv/emit_print.pas b/spirv/emit_print.pas index fbc5107c..e8192a45 100644 --- a/spirv/emit_print.pas +++ b/spirv/emit_print.pas @@ -29,7 +29,7 @@ type procedure PrintConst; procedure PrintVariable; procedure PrintFunc; - procedure PrintOp(node:TSpirvOp;print_offset:Boolean); + procedure PrintOp(node:TSpirvOp); end; implementation @@ -91,7 +91,7 @@ begin begin pBlock:=node.Parent; Write(Space(pBlock.Level)); - PrintOp(node,false); + PrintOp(node); end; node:=flow_down_next_up(node); end; @@ -187,7 +187,7 @@ begin end; end; -procedure TSprvEmit_print.PrintOp(node:TSpirvOp;print_offset:Boolean); +procedure TSprvEmit_print.PrintOp(node:TSpirvOp); var Param:POpParamNode; Info:Op.TOpInfo; @@ -225,15 +225,7 @@ begin Param:=Param.Next; end; - if (node.OpId=Op.OpLabel) then - begin - print_offset:=true; - end; - - Case print_offset of - True :Writeln(' ;0x',HexStr(Node.Adr.Offdw*4,4){,' (',node.Order,')'}); - False:Writeln; - end; + Writeln; end; diff --git a/spirv/emit_sop1.pas b/spirv/emit_sop1.pas index 8c0d6dc1..872977de 100644 --- a/spirv/emit_sop1.pas +++ b/spirv/emit_sop1.pas @@ -8,7 +8,7 @@ uses sysutils, ps4_pssl, spirv, - srCFGLabel, + srCFGParser, srFlow, srType, srConst, @@ -119,6 +119,10 @@ begin SetConst_b(get_scc,src0.AsConst.AsBool or src1.AsConst.AsBool); end else begin + //force type + src0:=BitcastList.FetchRead(dtBool,src0); + src1:=BitcastList.FetchRead(dtBool,src1); + OpLogicalOr(get_scc,src0,src1); //implict cast (int != 0) end; end; @@ -176,16 +180,12 @@ Var newptr:Pointer; begin - While (CheckBlockEnd) do; - //ret if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(false); newptr:=GetFuncPtr(@src); set_code_ptr(newptr,btMain); - - While (CheckBlockBeg) do; end; procedure TEmit_SOP1.emit_S_SWAPPC_B64; diff --git a/spirv/emit_sop2.pas b/spirv/emit_sop2.pas index 5c339a41..60ebeb7b 100644 --- a/spirv/emit_sop2.pas +++ b/spirv/emit_sop2.pas @@ -73,7 +73,7 @@ begin a:=OpEqualTo(x,y); b:=OpNotEqualTo(d,x); - OpBitwiseAnd(car,a,b); + OpLogicalAnd(car,a,b); end; procedure TEmit_SOP2.emit_S_ADD_U32; @@ -118,7 +118,7 @@ begin a:=OpNotEqualTo(x,y); b:=OpNotEqualTo(d,x); - OpBitwiseAnd(bor,a,b); + OpLogicalAnd(bor,a,b); end; procedure TEmit_SOP2.emit_S_SUB_U32; @@ -207,6 +207,10 @@ begin SetConst_b(get_scc,src0.AsConst.AsBool or src1.AsConst.AsBool); end else begin + //force type + src0:=BitcastList.FetchRead(dtBool,src0); + src1:=BitcastList.FetchRead(dtBool,src1); + OpLogicalOr(get_scc,src0,src1); //implict cast (int != 0) end; end; @@ -431,7 +435,8 @@ begin src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUnknow); scc:=MakeRead(get_scc,dtBool); - OpSelect(dst,src[0],src[1],scc); + //dst,cond,src_true,src_false + OpSelect(dst,scc,src[0],src[1]); end; procedure TEmit_SOP2.emit_S_CSELECT_B64; //sdst[2] = SCC ? ssrc0[2] : ssrc1[2] @@ -447,8 +452,9 @@ begin scc:=MakeRead(get_scc,dtBool); - OpSelect(dst[0],src0[0],src1[0],scc); - OpSelect(dst[1],src0[1],src1[1],scc); + //dst,cond,src_true,src_false + OpSelect(dst[0],scc,src0[0],src1[0]); + OpSelect(dst[1],scc,src0[1],src1[1]); end; //offset = ssrc1[4:0].u and 31 diff --git a/spirv/emit_sopk.pas b/spirv/emit_sopk.pas index 9200a12a..979c72f6 100644 --- a/spirv/emit_sopk.pas +++ b/spirv/emit_sopk.pas @@ -73,7 +73,7 @@ begin a:=OpLogicalNotTo(a); end; - OpBitwiseAnd(car,a,b); + OpLogicalAnd(car,a,b); end; procedure TEmit_SOPK.emit_S_MULK_I32; //sdst.s = (sdst.s * signExtend(imm16.s)) & 0xFFFFFFFF diff --git a/spirv/emit_sopp.pas b/spirv/emit_sopp.pas index bbf99c76..e2b7ffa0 100644 --- a/spirv/emit_sopp.pas +++ b/spirv/emit_sopp.pas @@ -8,12 +8,7 @@ uses sysutils, ps4_pssl, srType, - srCFGParser, - srCFGLabel, - srCFGCursor, - srFlow, srConst, - srReg, srOp, srOpUtils, spirv, @@ -22,295 +17,11 @@ uses type TEmit_SOPP=class(TEmitFetch) procedure emit_SOPP; - procedure emit_S_BRANCH_COND(cond:TsrCondition;invert:Boolean); - procedure emit_S_BRANCH; - procedure emit_loop_branch(b_adr:TSrcAdr;pCurr:TsrOpBlock); - function FetchCond(Adr:TSrcAdr):TsrOpBlock; - function FetchElse(Adr:TSrcAdr):Boolean; - function IsInLoop(Adr:TSrcAdr):Boolean; - function IsUnknow(Adr:TSrcAdr):Boolean; - function get_inline_end_addr(adr:TSrcAdr):TSrcAdr; - procedure emit_block_unknow(adr:TSrcAdr); procedure emit_S_BARRIER; end; implementation -function TEmit_SOPP.get_inline_end_addr(adr:TSrcAdr):TSrcAdr; -var - cInline:TsrCursor; -begin - cInline:=fetch_cursor_ptr(adr.get_code_ptr,btInline); - Result :=cInline.pCode.FTop.pELabel.Adr; //get end of code -end; - -function _up_to_real(t:TsrOpBlock):TsrOpBlock; -begin - repeat - if not t.IsType(ntOpBlock) then Break; - if IsReal(t.Block.bType) then Break; - t:=t.Parent; - until false; - Result:=t; -end; - -function TEmit_SOPP.FetchCond(Adr:TSrcAdr):TsrOpBlock; -var - pOpBlock:TsrOpBlock; -begin - Result:=nil; - - pOpBlock:=Main.pBlock.FindUpCond; - if (pOpBlock=nil) then Exit; - - if (pOpBlock.Block.b_adr.get_code_ptr=Adr.get_code_ptr) then - begin - Result:=pOpBlock; - end else - begin - //special case - if (pOpBlock.Block.b_adr.get_code_ptr=Cursor.prev_adr.get_code_ptr) then - if (pOpBlock.Block.e_adr.get_code_ptr=Adr.get_code_ptr) then - begin - Result:=pOpBlock; - end; - end; - -end; - -function TEmit_SOPP.FetchElse(Adr:TSrcAdr):Boolean; -var - pOpBlock:TsrOpBlock; - pElse :TsrOpBlock; -begin - Result:=False; - - pOpBlock:=Main.pBlock.FindUpCond; - if (pOpBlock=nil) then Exit; - - pElse:=pOpBlock.pElse; - if (pElse<>nil) then - begin - if (pElse.Block.e_adr.get_code_ptr=Adr.get_code_ptr) then - begin - Result:=True; - end; - end; -end; - -function TEmit_SOPP.IsInLoop(Adr:TSrcAdr):Boolean; -var - pOpBlock:TsrOpBlock; -begin - Result:=false; - - pOpBlock:=Main.pBlock.FindUpLoop; - if (pOpBlock=nil) then Exit(False); - - if (pOpBlock.Block.b_adr.get_code_ptr=adr.get_code_ptr) then //is continue? - begin - Result:=True; - end else - if (pOpBlock.Block.e_adr.get_code_ptr=adr.get_code_ptr) then //is break? - begin - Result:=True; - end else - begin - Result:=False; - end; -end; - -function TEmit_SOPP.IsUnknow(Adr:TSrcAdr):Boolean; -var - pLabel:TsrLabel; -begin - pLabel:=FindLabel(Adr); - Assert(pLabel<>nil); - - Result:=pLabel.IsType(ltUnknow); -end; - -procedure TEmit_SOPP.emit_S_BRANCH_COND(cond:TsrCondition;invert:Boolean); -var - c_adr,b_adr:TSrcAdr; - pLabel:TsrLabel; - - pCond:TsrOpBlock; - - pBegOp,pEndOp:TspirvOp; - - src:TsrRegNode; -begin - if (FSPI.SOPP.SIMM=0) then - begin - Exit; //skip - end; - - pLabel:=FindLabel(Cursor.prev_adr); - if (pLabel<>nil) then - begin - if (ltGoto in pLabel.lType) then Exit; - end; - - While (CheckBlockBeg) do; - - c_adr:=Cursor.Adr; - b_adr:=c_adr; - b_adr.Offdw:=get_branch_offset(FSPI); - - pLabel:=FindLabel(b_adr); - Assert(pLabel<>nil); - - pCond:=FetchCond(c_adr); - Assert(pCond<>nil,'Goto Unknow'); - - src:=ConvertCond(cond,pCond.vctx.Befor).pNode; - - pBegOp:=pCond.Labels.pBegOp; - pEndOp:=pCond.Labels.pEndOp; - - pCond.SetCond(src,invert); - - //OpBranchConditional - - //The instruction specifies which block to skip, so need to invert the condition! - //Since the main condition is this condition equal to zero, then we need to invert it again! - Case invert of - True: //invert of invert of invert! - begin - pCond.Labels.pBcnOp.AddParam(src); - pCond.Labels.pBcnOp.AddParam(pEndOp.pDst); //True - pCond.Labels.pBcnOp.AddParam(pBegOp.pDst); //False - end; - False: //invert of invert! - begin - pCond.Labels.pBcnOp.AddParam(src); - pCond.Labels.pBcnOp.AddParam(pBegOp.pDst); //True - pCond.Labels.pBcnOp.AddParam(pEndOp.pDst); //False - end; - end; - - if (pCond.Block.e_adr.get_code_ptr=b_adr.get_code_ptr) then - begin - //if (eval) {} - end else - begin - emit_loop_branch(b_adr,pCond.pBody); - end; -end; - -procedure TEmit_SOPP.emit_block_unknow(adr:TSrcAdr); -var - pOpChild:TsrOpBlock; - Info:TsrBlockInfo; -begin - Info:=Default(TsrBlockInfo); - - Info.b_adr:=adr; - Info.e_adr:=get_inline_end_addr(adr); - Info.bType:=btInline; - - //down group - pOpChild:=AllocBlockOp; - pOpChild.SetInfo(Info); - PushBlockOp(line,pOpChild); - - set_code_ptr(adr.get_code_ptr,btInline); -end; - -procedure TEmit_SOPP.emit_loop_branch(b_adr:TSrcAdr;pCurr:TsrOpBlock); -var - pOpLabel:TspirvOp; - - pLoop:TsrOpBlock; - - FVolMark:TsrVolMark; - - bnew:Boolean; -begin - pLoop:=Main.pBlock.FindUpLoop; - Assert(pLoop<>nil,'Goto Unknow'); - //break/continue - - pOpLabel:=nil; - - FVolMark:=vmNone; - if (pLoop.Block.b_adr.get_code_ptr=b_adr.get_code_ptr) then //is continue? - begin - pOpLabel:=pLoop.Labels.pMrgOp; //-> OpLoopMerge end -> OpLoopMerge before - pLoop.Cond.FUseCont:=True; - FVolMark:=vmConti; - end else - if (pLoop.Block.e_adr.get_code_ptr=b_adr.get_code_ptr) then //is break? - begin - pOpLabel:=pLoop.Labels.pEndOp; - FVolMark:=vmBreak; - end else - begin - Assert(false,'break/continue'); - end; - - Assert(pOpLabel<>nil); - - bnew:=true; - if pCurr.IsEndOf(Cursor.Adr) then //is last - begin - Case pCurr.Block.bType of - btSetpc:; - else - begin - bnew:=false; - end; - end; - end; - - //calc volatile - case FVolMark of - vmBreak:PrivateList.build_volatile_break(pLoop.vctx,pLoop.Regs.orig,pLoop.Regs.prev,pLoop.Regs.next); - vmConti:PrivateList.build_volatile_conti(pLoop.vctx,pLoop.Regs.orig,pLoop.Regs.prev,pLoop.Regs.next); - end; - - //mark hints - mark_end_of(FVolMark); - - OpBranch(pCurr.line,pOpLabel); - if bnew then - begin - AddSpirvOp(pCurr.line,NewLabelOp(True)); - end; -end; - -procedure TEmit_SOPP.emit_S_BRANCH; -var - pLabel:TsrLabel; - c_adr,b_adr:TSrcAdr; -begin - if (FSPI.SOPP.SIMM=0) then - begin - Exit; //skip - end; - - pLabel:=FindLabel(Cursor.prev_adr); - if (pLabel<>nil) then - begin - if (ltGoto in pLabel.lType) then Exit; - end; - - While (CheckBlockBeg) do; - - c_adr:=Cursor.Adr; - b_adr:=c_adr; - b_adr.Offdw:=get_branch_offset(FSPI); - - if FetchElse(b_adr) then - begin - //{} else {} - end else - begin - emit_loop_branch(b_adr,Main.pBlock); - end; -end; - procedure TEmit_SOPP.emit_S_BARRIER; Var node:TspirvOp; @@ -351,14 +62,14 @@ begin mark_end_of(vmEndpg); end; - S_CBRANCH_SCC0 :emit_S_BRANCH_COND(cScc0 ,false); - S_CBRANCH_SCC1 :emit_S_BRANCH_COND(cScc0 ,true); - S_CBRANCH_VCCZ :emit_S_BRANCH_COND(cVccz ,false); //It means that lane_id=0 - S_CBRANCH_VCCNZ :emit_S_BRANCH_COND(cVccz ,true); //It means that lane_id=0 - S_CBRANCH_EXECZ :emit_S_BRANCH_COND(cExecz,false); //It means that lane_id=0 - S_CBRANCH_EXECNZ:emit_S_BRANCH_COND(cExecz,true); //It means that lane_id=0 + S_CBRANCH_SCC0 :; //It means that (scc == 0) + S_CBRANCH_SCC1 :; //It means that (scc == 1) + S_CBRANCH_VCCZ :; //It means that (vcc0 == 0) && (vcc1 == 0) + S_CBRANCH_VCCNZ :; //It means that (vcc0 != 0) || (vcc1 != 0) + S_CBRANCH_EXECZ :; //It means that (exec0 == 0) && (exec1 == 0) + S_CBRANCH_EXECNZ:; //It means that (exec0 != 0) || (exec1 != 0) - S_BRANCH :emit_S_BRANCH; + S_BRANCH :; S_BARRIER :emit_S_BARRIER; diff --git a/spirv/emit_vbuf_store.pas b/spirv/emit_vbuf_store.pas index ead3fa87..1723ae15 100644 --- a/spirv/emit_vbuf_store.pas +++ b/spirv/emit_vbuf_store.pas @@ -168,11 +168,13 @@ begin cond:=OpCmpTo(Op.OpSLessThan,t3,NewImm_q(dtUint32,$38800000)); //(t3 < 0x38800000) - t1:=OpSelectTo(t1,NewImm_q(dtUint32,0),cond); //if (t3 < 0x38800000) t1 = 0; // Flush-to-zero + //cond,src_true,src_false + t1:=OpSelectTo(cond,NewImm_q(dtUint32,0),t1); //if (t3 < 0x38800000) t1 = 0; // Flush-to-zero cond:=OpCmpTo(Op.OpSGreaterThan,t3,NewImm_q(dtUint32,$47000000)); //(t3 > 0x47000000) - t1:=OpSelectTo(t1,NewImm_q(dtUint32,$3FF),cond); //if (t3 > 0x47000000) t1 = 0x3FF; // Clamp-to-max + //cond,src_true,src_false + t1:=OpSelectTo(cond,NewImm_q(dtUint32,$3FF),t1); //if (t3 > 0x47000000) t1 = 0x3FF; // Clamp-to-max Result:=t1; end; @@ -195,11 +197,13 @@ begin cond:=OpCmpTo(Op.OpSLessThan,t3,NewImm_q(dtUint32,$38800000)); //(t3 < 0x38800000) - t1:=OpSelectTo(t1,NewImm_q(dtUint32,0),cond); //if (t3 < 0x38800000) t1 = 0; // Flush-to-zero + //cond,src_true,src_false + t1:=OpSelectTo(cond,NewImm_q(dtUint32,0),t1); //if (t3 < 0x38800000) t1 = 0; // Flush-to-zero cond:=OpCmpTo(Op.OpSGreaterThan,t3,NewImm_q(dtUint32,$87000000)); //(t3 > 0x87000000) - t1:=OpSelectTo(t1,NewImm_q(dtUint32,$7FF),cond); //if (t3 > 0x47000000) t1 = 0x7FF; // Clamp-to-max + //cond,src_true,src_false + t1:=OpSelectTo(cond,NewImm_q(dtUint32,$7FF),t1); //if (t3 > 0x47000000) t1 = 0x7FF; // Clamp-to-max Result:=t1; end; diff --git a/spirv/emit_vop1.pas b/spirv/emit_vop1.pas index a3435de3..7e9e48aa 100644 --- a/spirv/emit_vop1.pas +++ b/spirv/emit_vop1.pas @@ -363,6 +363,9 @@ Var pos:TsrRegNode; cnd:TsrRegNode; begin + // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) + // position + dst:=get_vdst8(FSPI.VOP1.VDST); src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUint32); @@ -371,10 +374,11 @@ begin pos:=OpISubTo(NewImm_i(dtUint32,31),msb); - cnd:=OpIEqualTo(src,NewImm_i(dtUint32,0)); + // Select 0xFFFFFFFF if src was 0 + cnd:=OpINotEqualTo(src,NewImm_i(dtUint32,0)); - // True, False - OpSelect(dst,NewImm_q(dtUint32,High(DWORD)),pos,cnd); + //dst,cond,src_true,src_false + OpSelect(dst,cnd,pos,NewImm_q(dtUint32,High(DWORD))); end; procedure TEmit_VOP1.emit_V_FFBL_B32; diff --git a/spirv/emit_vop2.pas b/spirv/emit_vop2.pas index b1bf0cfd..8d0338e6 100644 --- a/spirv/emit_vop2.pas +++ b/spirv/emit_vop2.pas @@ -67,18 +67,19 @@ begin end; end; -procedure TEmit_VOP2.emit_V_CNDMASK_B32; +procedure TEmit_VOP2.emit_V_CNDMASK_B32; //vdst = smask[thread_id:] ? vsrc1 : vsrc0 Var dst:PsrRegSlot; src:array[0..2] of TsrRegNode; begin dst:=get_vdst8(FSPI.VOP2.VDST); - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow); - src[2]:=MakeRead(get_vcc0,dtBool); + src[0]:=fetch_ssrc9 (FSPI.VOP2.SRC0 ,dtUnknow); + src[1]:=fetch_vsrc8 (FSPI.VOP2.VSRC1,dtUnknow); + src[2]:=GetThreadBit(get_vcc0,get_vcc1,dtBool); - OpSelect(dst,src[0],src[1],src[2]); + //dst,cond,src_true,src_false + OpSelect(dst,src[2],src[1],src[0]); end; procedure TEmit_VOP2.emit_V_AND_B32; @@ -143,7 +144,7 @@ begin src[1]:=OpAndTo(src[1],31); src[1].PrepType(ord(dtUInt32)); - Op2(OpId,src[0].dtype,dst,src[0],src[1]); + Op2(OpId,rtype,dst,src[0],src[1]); end; procedure TEmit_VOP2.emit_V_ADD_I32; //vdst = vsrc0.s + vsrc1.s; sdst[thread_id:] = carry_out & EXEC @@ -225,7 +226,7 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - src[2]:=MakeRead(get_vcc0,dtUInt32); + src[2]:=GetThreadBit(get_vcc0,get_vcc1,dtUInt32); src[2]:=OpAndTo(src[2],1); src[2].PrepType(ord(dtUInt32)); @@ -283,7 +284,7 @@ begin end; end; - src[2]:=MakeRead(get_vcc0,dtUInt32); + src[2]:=GetThreadBit(get_vcc0,get_vcc1,dtUInt32); src[2]:=OpAndTo(src[2],1); src[2].PrepType(ord(dtUInt32)); @@ -360,7 +361,8 @@ begin mul:=NewReg(dtFloat32); _Op2(line,Op.OpFMul,mul,src[0],src[1]); - OpSelect(dst,mul,zero,cmp); //false,true,cond + //dst,cond,src_true,src_false + OpSelect(dst,cmp,zero,mul); end; procedure TEmit_VOP2.emit_V_CVT_PKRTZ_F16_F32; @@ -376,29 +378,23 @@ begin OpConvFloatToHalf2(dst,src[0],src[1]); end; -procedure TEmit_VOP2.emit_V_MUL_I32_I24; +procedure TEmit_VOP2.emit_V_MUL_I32_I24; //vdst = (vsrc0[23:0].s * vsrc1[23:0].s) Var dst:PsrRegSlot; src:array[0..1] of TsrRegNode; - bit24:TsrRegNode; begin dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtInt32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtInt32); - bit24:=NewImm_q(dtUInt32,$FFFFFF); - - src[0]:=OpAndTo(src[0],bit24); - src[0].PrepType(ord(dtInt32)); - - src[1]:=OpAndTo(src[1],bit24); - src[1].PrepType(ord(dtInt32)); + src[0]:=OpBFSETo(src[0],NewImm_i(dtInt32,0),NewImm_i(dtInt32,24)); + src[1]:=OpBFSETo(src[1],NewImm_i(dtInt32,0),NewImm_i(dtInt32,24)); OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP2.emit_V_MUL_U32_U24; +procedure TEmit_VOP2.emit_V_MUL_U32_U24; //vdst = (vsrc0[23:0].u * vsrc1[23:0].u) Var dst:PsrRegSlot; src:array[0..1] of TsrRegNode; @@ -457,7 +453,8 @@ begin mul:=MakeRead(dst,dtFloat32); - OpSelect(dst,mul,zero,cmp); //false,true,cond + //dst,cond,src_true,src_false + OpSelect(dst,cmp,zero,mul); end; procedure TEmit_VOP2.emit_V_MADAK_F32; //vdst = vsrc0.f * vsrc1.f + kadd.f diff --git a/spirv/emit_vop3.pas b/spirv/emit_vop3.pas index 984b5b3a..93898b4c 100644 --- a/spirv/emit_vop3.pas +++ b/spirv/emit_vop3.pas @@ -91,14 +91,12 @@ begin emit_src_abs_bit(@src,2,rtype); emit_src_neg_bit(@src,2,rtype); - OpCmpV(OpId,dst[0],src[0],src[1]); - - SetConst_q(dst[1],dtUnknow,0); //set zero + OpCmpV(OpId,dst[0],dst[1],src[0],src[1]); if x then begin - MakeCopy (get_exec0,dst[0]^.current); - SetConst_q(get_exec1,dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + MakeCopy(get_exec1,dst[1]^.current); end; end; @@ -221,7 +219,7 @@ begin end; end; -procedure TEmit_VOP3.emit_V_CNDMASK_B32; +procedure TEmit_VOP3.emit_V_CNDMASK_B32; //vdst = smask[thread_id:] ? vsrc1 : vsrc0 Var dst:PsrRegSlot; src:array[0..2] of TsrRegNode; @@ -245,12 +243,13 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,rtype); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,rtype); - src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtBool); + src[2]:=GetThreadBit(get_ssrc9(FSPI.VOP3a.SRC2),get_ssrc9(FSPI.VOP3a.SRC2+1),dtBool); emit_src_abs_bit(@src,2,rtype); emit_src_neg_bit(@src,2,rtype); - OpSelect(dst,src[0],src[1],src[2]); + //dst,cond,src_true,src_false + OpSelect(dst,src[2],src[1],src[0]); end; procedure TEmit_VOP3.emit_V_MUL_LEGACY_F32; @@ -276,7 +275,8 @@ begin mul:=NewReg(dtFloat32); _Op2(line,Op.OpFMul,mul,src[0],src[1]); - OpSelect(dst,mul,zero,cmp); //false,true,cond + //dst,cond,src_true,src_false + OpSelect(dst,cmp,zero,mul); emit_dst_omod__f(dst,dtFloat32); emit_dst_clamp_f(dst,dtFloat32); @@ -395,7 +395,7 @@ begin src[1]:=OpAndTo(src[1],31); src[1].PrepType(ord(dtUInt32)); - Op2(OpId,src[0].dtype,dst,src[0],src[1]); + Op2(OpId,rtype,dst,src[0],src[1]); end; procedure TEmit_VOP3.emit_V_MUL_LO(rtype:TsrDataType); @@ -416,11 +416,10 @@ begin OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP3.emit_V_MUL_I32_I24; +procedure TEmit_VOP3.emit_V_MUL_I32_I24; //vdst = (vsrc0[23:0].s * vsrc1[23:0].s) Var dst:PsrRegSlot; src:array[0..1] of TsrRegNode; - bit24:TsrRegNode; begin dst:=get_vdst8(FSPI.VOP3a.VDST); @@ -432,13 +431,8 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtInt32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); - bit24:=NewImm_q(dtUInt32,$FFFFFF); - - src[0]:=OpAndTo(src[0],bit24); - src[0].PrepType(ord(dtInt32)); - - src[1]:=OpAndTo(src[1],bit24); - src[1].PrepType(ord(dtInt32)); + src[0]:=OpBFSETo(src[0],NewImm_i(dtInt32,0),NewImm_i(dtInt32,24)); + src[1]:=OpBFSETo(src[1],NewImm_i(dtInt32,0),NewImm_i(dtInt32,24)); OpIMul(dst,src[0],src[1]); end; @@ -757,14 +751,14 @@ begin mul:=MakeRead(dst,dtFloat32); - OpSelect(dst,mul,zero,cmp); //false,true,cond + //dst,cond,src_true,src_false + OpSelect(dst,cmp,zero,mul); end; -procedure TEmit_VOP3.emit_V_MAD_I32_I24; +procedure TEmit_VOP3.emit_V_MAD_I32_I24; //vdst.i = vsrc0[23:0].i * vsrc1[23:0].i + vsrc2.i Var dst:PsrRegSlot; src:array[0..2] of TsrRegNode; - bit24:TsrRegNode; begin dst:=get_vdst8(FSPI.VOP3a.VDST); @@ -777,18 +771,13 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtInt32); - bit24:=NewImm_q(dtUInt32,$FFFFFF); - - src[0]:=OpAndTo(src[0],bit24); - src[0].PrepType(ord(dtInt32)); - - src[1]:=OpAndTo(src[1],bit24); - src[1].PrepType(ord(dtInt32)); + src[0]:=OpBFSETo(src[0],NewImm_i(dtInt32,0),NewImm_i(dtInt32,24)); + src[1]:=OpBFSETo(src[1],NewImm_i(dtInt32,0),NewImm_i(dtInt32,24)); OpFmaI32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP3.emit_V_MAD_U32_U24; +procedure TEmit_VOP3.emit_V_MAD_U32_U24; //vdst.u = vsrc0[23:0].u * vsrc1[23:0].u + vsrc2.u Var dst:PsrRegSlot; src:array[0..2] of TsrRegNode; @@ -821,7 +810,8 @@ procedure TEmit_VOP3.emit_V_MAD_U64_U32; Var dst:array[0..1] of PsrRegSlot; src:array[0..2] of TsrRegNode; - mul,sum,car,exc:TsrRegNode; + mul,sum,car:TsrRegNode; + //exc:TsrRegNode; begin dst[0]:=get_vdst8(FSPI.VOP3a.VDST+0); dst[1]:=get_vdst8(FSPI.VOP3a.VDST+1); diff --git a/spirv/emit_vopc.pas b/spirv/emit_vopc.pas index 2ce3a37f..e135c7ca 100644 --- a/spirv/emit_vopc.pas +++ b/spirv/emit_vopc.pas @@ -32,14 +32,12 @@ begin src[0]:=fetch_ssrc9(FSPI.VOPC.SRC0 ,rtype); src[1]:=fetch_vsrc8(FSPI.VOPC.VSRC1,rtype); - OpCmpV(OpId,dst[0],src[0],src[1]); - - SetConst_q(dst[1],dtUnknow,0); //set zero + OpCmpV(OpId,dst[0],dst[1],src[0],src[1]); if x then begin - MakeCopy (get_exec0,dst[0]^.current); - SetConst_q(get_exec1,dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + MakeCopy(get_exec1,dst[1]^.current); end; end; diff --git a/spirv/pssl-spirv.lpi b/spirv/pssl-spirv.lpi index 7280bb6b..3e985f69 100644 --- a/spirv/pssl-spirv.lpi +++ b/spirv/pssl-spirv.lpi @@ -25,7 +25,7 @@ - + @@ -250,54 +250,50 @@ - + - + - + - + - + - + - + - + - + - - - - - - + + - + diff --git a/spirv/srBuffer.pas b/spirv/srBuffer.pas index 1cc8ece1..c056513c 100644 --- a/spirv/srBuffer.pas +++ b/spirv/srBuffer.pas @@ -435,9 +435,14 @@ var begin Result:=Default(TFieldFetchValue); + Assert(_stride<>0); + Assert(_size <>0); + _count:=_size div _stride; _size :=_count*_stride; //align + Assert(_count<>0); + //find intersec node:=FindIntersect(_offset,_size); diff --git a/spirv/srCFGCursor.pas b/spirv/srCFGCursor.pas index 29db3c7c..f8a2cff7 100644 --- a/spirv/srCFGCursor.pas +++ b/spirv/srCFGCursor.pas @@ -6,27 +6,31 @@ interface uses sysutils, - srCFGLabel, srCFGParser, ginodes, srNode; type PsrCursor=^TsrCursor; - TsrCursor=object(TsrLCursor) - pCode :TsrCodeBlock; - pBlock:TsrCFGBlock; - procedure Init(Code:TsrCodeBlock); + TsrCursor=object + pCode:TsrCodeRegion; + pNode:TsrSourceNode; + b_adr:TSrcAdr; + e_adr:TSrcAdr; + fnext:Boolean; + procedure Init(Code:TsrCodeRegion;node:TsrSourceNode;base:Pointer); + procedure UpdateAdr; + function AsBlock:TsrSourceBlock; function PopBlock:Boolean; end; - TsrCodeList=specialize TNodeQueueClass; + TsrCodeList=specialize TNodeQueueClass; PsrCodeHeap=^TsrCodeHeap; TsrCodeHeap=object(TsrCodeList) FEmit:TCustomEmit; Procedure Init(Emit:TCustomEmit); - function FindByPtr (base:Pointer):TsrCodeBlock; + function FindByPtr (base:Pointer):TsrCodeRegion; function FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor; end; @@ -39,15 +43,15 @@ begin FEmit:=Emit; end; -function TsrCodeHeap.FindByPtr(base:Pointer):TsrCodeBlock; +function TsrCodeHeap.FindByPtr(base:Pointer):TsrCodeRegion; var - node:TsrCodeBlock; + node:TsrCodeRegion; begin Result:=nil; node:=pHead; While (node<>nil) do begin - if node.IsContain(base) then + if (PtrUint(node.Body)<=PtrUint(base)) and ((PtrUint(node.Body)+node.Size)>PtrUint(base)) then begin Exit(node); end; @@ -57,53 +61,78 @@ end; function TsrCodeHeap.FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor; var - pCode:TsrCodeBlock; - adr:TSrcAdr; + pCode:TsrCodeRegion; + pNode:TsrSourceNode; p_err:Integer; begin pCode:=FindByPtr(base); - if (pCode=nil) then - begin - pCode:=FEmit.specialize New; - pCode.FTop:=FEmit.specialize New; - pCode.FEmit:=FEmit; - pCode.Body :=base; - pCode.DMem :=FEmit.GetDmem(base); - // - p_err:=parse_code_cfg(bType,pCode); + if (pCode<>nil) then + begin + pNode:=pCode.FindByPtr(base); + end else + begin + pNode:=nil; + end; + + if (pNode=nil) then + begin + p_err:=parse_code_cfg2(pCode,bType,base,FEmit.GetDmem(base),FEmit); if (p_err>1) then begin Assert(False,'parse_code_cfg:'+IntToStr(p_err)); end; // Push_tail(pCode); + // + pNode:=pCode.FindByPtr(base); end; - Result:=Default(TsrCursor); - Result.Init(pCode); - - adr:=Default(TSrcAdr); - adr.pCode:=TsrLabelBlock(pCode); - adr.Offdw:=(Pointer(base)-Pointer(pCode.Body)) div 4; - - Result.Adr:=adr; - Result.pBlock:=Result.pBlock.WorkBlock(adr); + Result.Init(pCode,pNode,base); end; -procedure TsrCursor.Init(Code:TsrCodeBlock); +procedure TsrCursor.Init(Code:TsrCodeRegion;node:TsrSourceNode;base:Pointer); begin - inherited Init(TsrLabelBlock(Code)); - pCode :=Code; - pBlock:=Code.FTop; + pCode:=Code; + pNode:=node; + // + b_adr.pCode :=Code; + b_adr.Offset:=0; + e_adr:=b_adr; + // + UpdateAdr; + // + fnext:=(e_adr.get_code_ptr=base); +end; + +procedure TsrCursor.UpdateAdr; +begin + if (pNode<>nil) then + begin + if pNode.InheritsFrom(TsrSourceAdr) then + begin + b_adr:=TsrSourceAdr(pNode).b_adr; + e_adr:=TsrSourceAdr(pNode).e_adr; + end; + end; +end; + +function TsrCursor.AsBlock:TsrSourceBlock; +begin + Result:=nil; + if (pNode<>nil) then + if (pNode.ntype=TsrSourceBlock) then + begin + Exit(TsrSourceBlock(pNode)); + end; end; function TsrCursor.PopBlock:Boolean; begin Result:=False; - if (pBlock=nil) then Exit; - if (pBlock.pParent=nil) then Exit; - pBlock:=pBlock.pParent; + if (pNode=nil) then Exit; + if (pNode.pParent=nil) then Exit; + pNode:=pNode.pParent; Result:=True; end; diff --git a/spirv/srCFGLabel.pas b/spirv/srCFGLabel.pas deleted file mode 100644 index e09a1632..00000000 --- a/spirv/srCFGLabel.pas +++ /dev/null @@ -1,358 +0,0 @@ -unit srCFGLabel; - -{$mode ObjFPC}{$H+} - -interface - -uses - ps4_pssl, - ginodes, - srNode; - -type - TsrLabelBlock=class; - - PSrcAdr=^TSrcAdr; - TSrcAdr=object - pCode:TsrLabelBlock; - Offdw:PtrUInt; - function get_code_ptr:PDWORD; - function get_dmem_ptr:PDWORD; - end; - - TsrLCursor=object(TShaderParser) - private - pCode:TsrLabelBlock; - function get_src_adr:TSrcAdr; - Procedure set_src_adr(src:TSrcAdr); - public - prev_adr:TSrcAdr; - procedure Init(Code:TsrLabelBlock); - property Adr:TSrcAdr read get_src_adr write set_src_adr; - Function Next(Var SPI:TSPI):Integer; - end; - - TsrLabelType=(ltUnknow, - ltGoto, - ltContinue, - ltBreak); - - TsrSetLabelType=Set of TsrLabelType; - - TsrBlockType=(btMain,btSetpc,btCond,btElse,btLoop,btMerg,btExec,btInline,btOther); - - TsrCondition=( - cNone, - cFalse, - cTrue, - cScc0, - cScc1, - cVccz, - cVccnz, - cExecz, - cExecnz - ); - -const - InvertCond:array[TsrCondition] of TsrCondition=( - cNone, //cNone, - cTrue, //cFalse, - cFalse, //cTrue, - cScc1, //cScc0, - cScc0, //cScc1, - cVccnz, //cVccz, - cVccz, //cVccnz, - cExecnz, //cExecz, - cExecz //cExecnz - ); - -type - TsrLabel=class - public - pLeft,pRight:TsrLabel; - private - key:TSrcAdr; - public - lType:TsrSetLabelType; - class function c(n1,n2:PSrcAdr):Integer; static; - property Adr:TSrcAdr read key; - Procedure AddType(t:TsrLabelType); - Procedure RemType(t:TsrLabelType); - function IsType (t:TsrLabelType):Boolean; - end; - - TsrStatementType=( - sCond, - sGoto, - sVar, - sStore, - sLoad, - sBreak, - sNot, - sOr, - sAnd - ); - - //sCond TsrCondition - //sGoto [sLabel]:TsrLabel [sNext]:TsrLabel [cond]:sCond/sLoad/sNot/sOr/sAnd - - //sVar id - - //sStore [var]:sVar [false]:sCond/sLoad/sNot/sOr/sAnd - //sLoad [var]:sVar - - //sBreak - - //sNot [cond]:sCond/sLoad/sNot/sOr - - //sOr [cond]:sCond/sLoad/sNot/sOr/sAnd [cond]:sCond/sLoad/sNot/sOr/sAnd - //sAnd [cond]:sCond/sLoad/sNot/sOr/sAnd [cond]:sCond/sLoad/sNot/sOr/sAnd - - TsrStatement=class - pPrev :TsrStatement; - pNext :TsrStatement; - // - sType :TsrStatementType; - sLabel:TsrLabel; - sNext :TsrLabel; - pSrc :TsrStatement; - pDst :TsrStatement; - // - pCache:TObject; - u:record - Case Byte of - 0:(id :PtrUint); - 1:(cond:TsrCondition); - end; - end; - - TsrLabels=specialize TNodeTreeClass; - - TsrLabelBlock=class - FEmit:TCustomEmit; - Body:Pointer; - DMem:Pointer; - Size:ptruint; - FLabels:TsrLabels; - FVarId:Ptruint; - Function FindLabel (Adr:TSrcAdr):TsrLabel; - Function FetchLabel(Adr:TSrcAdr):TsrLabel; - Function IsContain (P:Pointer):Boolean; - // - Function NewCond(cond:TsrCondition):TsrStatement; - Function NewGoto(sLabel,sNext:TsrLabel;pCond:TsrStatement):TsrStatement; - Function NewVar:TsrStatement; - Function NewStore(pVar,pCond:TsrStatement):TsrStatement; - Function NewLoad (pVar:TsrStatement):TsrStatement; - Function NewBreak(sLabel:TsrLabel):TsrStatement; - Function NewNot (pCond:TsrStatement):TsrStatement; - Function NewOr (pCond1,pCond2:TsrStatement):TsrStatement; - Function NewAnd (pCond1,pCond2:TsrStatement):TsrStatement; - end; - -function get_branch_offset(var FSPI:TSPI):ptrint; - -function IsReal(b:TsrBlockType):Boolean; - -implementation - -function IsReal(b:TsrBlockType):Boolean; -begin - case b of - btMain, - btSetpc, - btCond, - btElse, - btLoop:Result:=True; - else - Result:=False; - end; -end; - -function TSrcAdr.get_code_ptr:PDWORD; -begin - if (pCode=nil) then - begin - Result:=nil; - end else - begin - Result:=PDWORD(pCode.Body); - end; - // - Result:=PDWORD(Result)+Offdw; -end; - -function TSrcAdr.get_dmem_ptr:PDWORD; -begin - if (pCode=nil) then - begin - Result:=nil - end else - begin - Result:=PDWORD(pCode.DMem); - end; - // - Result:=PDWORD(Result)+Offdw; -end; - - -procedure TsrLCursor.Init(Code:TsrLabelBlock); -begin - pCode :=Code; - Body :=Code.DMem; - OFFSET_DW:=0; - prev_adr :=Adr; -end; - -Function TsrLCursor.Next(Var SPI:TSPI):Integer; -begin - prev_adr:=Adr; - Result:=inherited Next(SPI); -end; - -function TsrLCursor.get_src_adr:TSrcAdr; -begin - Result:=Default(TSrcAdr); - Result.pCode:=pCode; - Result.Offdw:=OFFSET_DW; -end; - -Procedure TsrLCursor.set_src_adr(src:TSrcAdr); -begin - pCode :=src.pCode; - Body :=pCode.DMem; - OFFSET_DW:=src.Offdw; -end; - -class function TsrLabel.c(n1,n2:PSrcAdr):Integer; -var - p1,p2:Pointer; -begin - p1:=n1^.get_code_ptr; - p2:=n2^.get_code_ptr; - Result:=ord(p1>p2)-ord(p1; - Result.key:=Adr; - FLabels.Insert(Result); - end; -end; - -Function TsrLabelBlock.IsContain(P:Pointer):Boolean; -begin - Result:=(Body<=P) and ((Body+Size)>P); -end; - -Function TsrLabelBlock.NewCond(cond:TsrCondition):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType :=sCond; - Result.u.cond:=cond; -end; - -Function TsrLabelBlock.NewGoto(sLabel,sNext:TsrLabel;pCond:TsrStatement):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType :=sGoto; - Result.sLabel:=sLabel; - Result.sNext :=sNext; - Result.pSrc :=pCond; -end; - -Function TsrLabelBlock.NewVar:TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType:=sVar; - Result.u.id :=FVarId; - Inc(FVarId); -end; - -Function TsrLabelBlock.NewStore(pVar,pCond:TsrStatement):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType:=sStore; - Result.pDst :=pVar; - Result.pSrc :=pCond; -end; - -Function TsrLabelBlock.NewLoad(pVar:TsrStatement):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType:=sLoad; - Result.pSrc :=pVar; - Result.u.id :=FVarId; - Inc(FVarId); -end; - -Function TsrLabelBlock.NewBreak(sLabel:TsrLabel):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType :=sBreak; - Result.sLabel:=sLabel; -end; - -Function TsrLabelBlock.NewNot(pCond:TsrStatement):TsrStatement; -begin - case pCond.sType of - sCond:Result:=NewCond(InvertCond[pCond.u.cond]); - else - begin - Result:=FEmit.specialize New; - Result.sType:=sNot; - Result.pSrc :=pCond; - end; - end; -end; - -Function TsrLabelBlock.NewOr(pCond1,pCond2:TsrStatement):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType:=sOr; - Result.pSrc :=pCond1; - Result.pDst :=pCond2; -end; - -Function TsrLabelBlock.NewAnd(pCond1,pCond2:TsrStatement):TsrStatement; -begin - Result:=FEmit.specialize New; - Result.sType:=sAnd; - Result.pSrc :=pCond1; - Result.pDst :=pCond2; -end; - -end. - diff --git a/spirv/srCFGParser.pas b/spirv/srCFGParser.pas index d2091817..c58af6b5 100644 --- a/spirv/srCFGParser.pas +++ b/spirv/srCFGParser.pas @@ -9,498 +9,272 @@ uses ps4_pssl, ginodes, srNode, - srCFGLabel; + srConfig; type - TsrCFGBlock=class; + TsrCodeRegion=class; - TsrCFGBlockList=specialize TNodeListClass; - - TsrStatementList=specialize TNodeListClass; - - TsrCFGBlock=class - pParent,pPrev,pNext:TsrCFGBlock; - - FList:TsrCFGBlockList; - - pIf :TsrCFGBlock; - pElse:TsrCFGBlock; - - pBLabel:TsrLabel; - pELabel:TsrLabel; - - pCond:TsrStatement; - - FBefore:TsrStatementList; - FAfter :TsrStatementList; - - FStart :TsrStatementList; - FEnded :TsrStatementList; - - EndFixed:Boolean; - - bType:TsrBlockType; - - order:Integer; - - function beg_adr:TSrcAdr; - function end_adr:TSrcAdr; - function First:TsrCFGBlock; - function Last :TsrCFGBlock; - function pReal:TsrCFGBlock; - function IsEndOf (Adr:TSrcAdr):Boolean; - function IsBigOf (Adr:TSrcAdr):Boolean; - function IsContain(Adr:TSrcAdr):Boolean; - function IsInside (Adr:TSrcAdr):Boolean; - function FindBlock(Adr:TSrcAdr):TsrCFGBlock; - function DownBlock(Adr:TSrcAdr):TsrCFGBlock; - function WorkBlock(Adr:TSrcAdr):TsrCFGBlock; - function FindNext (Adr:TSrcAdr):TsrCFGBlock; - function FindPrev (Adr:TSrcAdr):TsrCFGBlock; - function UpBlock (Adr:TSrcAdr):TsrCFGBlock; - function FindUpLoop:TsrCFGBlock; - Procedure Push_front (new:TsrCFGBlock;_first:TsrCFGBlock=nil;_last:TsrCFGBlock=nil); - Procedure Push_back (new:TsrCFGBlock;_first:TsrCFGBlock=nil;_last:TsrCFGBlock=nil); - Procedure Insert_after(node,new:TsrCFGBlock;_first:TsrCFGBlock=nil;_last:TsrCFGBlock=nil); - Procedure MoveTo(_parent,_first,_last:TsrCFGBlock); - Procedure InsertAfterTo(_parent,_after,_first,_last:TsrCFGBlock); - Procedure MoveFromByRange(_parent:TsrCFGBlock;b_adr,e_adr:TSrcAdr); - function ExistByRange(b_adr,e_adr:TSrcAdr):Boolean; - function get_level:DWORD; + PSrcAdr=^TSrcAdr; + TSrcAdr=object + pCode :TsrCodeRegion; + Offset:PtrUInt; + function get_code_ptr:PDWORD; + function get_dmem_ptr:PDWORD; end; - TsrCodeBlock=class(TsrLabelBlock) - pNext:TsrCodeBlock; - //---- - FTop:TsrCFGBlock; + TsrSourceNode=class; + + TsrSourceNodeType=class of TsrSourceNode; + + TsrSourceBlock=class; + + TsrSourceNode=class + pParent:TsrSourceBlock; + pPrev,pNext:TsrSourceNode; + // + order:PtrUint; + // + function ntype:TsrSourceNodeType; inline; + function First:TsrSourceNode; virtual; + function Last :TsrSourceNode; virtual; + function get_level:DWORD; end; - TsrUnknowGoto=class - pPrev,pNext:TsrUnknowGoto; - goto_stmt :TsrStatement; - label_stmt:TsrLabel; + TsrSourceNodeList=specialize TNodeListClass; + + // + + TsrSourceAdr=class(TsrSourceNode) + key :TSrcAdr; //b_adr + e_adr:TSrcAdr; + property b_adr:TSrcAdr read key write key; + class function c(n1,n2:PSrcAdr):Integer; static; end; - TsrUnknowGotoList=specialize TNodeListClass; + TsrSourceLabel=class(TsrSourceAdr) + pLeft,pRight:TsrSourceLabel; + links_count:PtrUint; + end; - TsrCFGParser=object - FCursor:TsrLCursor; - pCode :TsrCodeBlock; - pBlock :TsrCFGBlock; - FUnknowGotoList:TsrUnknowGotoList; + TsrSourceLabelTree=specialize TNodeTreeClass; + + TsrSourceInstruction=class(TsrSourceAdr) + pLeft,pRight:TsrSourceInstruction; + // FSPI:TSPI; - order:Integer; - procedure AddUnknowGoto(goto_stmt,next_stmt,label_stmt:TsrLabel;cond:TsrCondition); - procedure _print_label(Adr:TSrcAdr); - function get_str_prefix(node:TsrCFGBlock;adr:TSrcAdr):RawByteString; - procedure Print(); - function Parse():Integer; - function FindUpCond(cond:TsrCondition;Adr:TSrcAdr):TsrCFGBlock; - procedure OpenExec; - procedure CloseExec(Before:Boolean); - function NextParse:Integer; - Procedure Finalize; - function CheckBlockEnd:Boolean; - function emit_SOP1:Boolean; - function emit_SOPP:Boolean; - Function NewBlock:TsrCFGBlock; - Procedure PushBlock(New:TsrCFGBlock); - function PopBlock:Boolean; - function FindUpperLoop(branch_adr:TSrcAdr;var r_child,r_parent:TsrCFGBlock):Integer; - function FindLowerLoop(branch_adr:TSrcAdr;var r_child,r_parent:TsrCFGBlock):Integer; - procedure emit_S_BRANCH(cond:TsrCondition); - procedure ExecPass; - procedure ExecConvert(node:TsrCFGBlock); - procedure ExecDivide(adr:TSrcAdr); - procedure GotoPass; - function BlockOf(stmt:TsrLabel):TsrCFGBlock; - function LevelOf(stmt:TsrLabel):DWORD; - function IsDirectlyRelated(goto_stmt,label_stmt:TsrLabel):Boolean; - function IsIndirectlyRelated(goto_stmt,label_stmt:TsrLabel):Boolean; - function AreSiblings(stmt:TsrCFGBlock;label_stmt:TsrLabel):Boolean; - function AreSiblings(stmt,label_stmt:TsrLabel):Boolean; - function SiblingFromNephew(uncle,nephew:TsrLabel):TsrCFGBlock; - function AreOrdered(left_sibling:TsrCFGBlock;right_sibling:TsrLabel):Boolean; - function AreOrdered(left_sibling,right_sibling:TsrLabel):Boolean; - function NeedsLift(goto_stmt,label_stmt:TsrLabel):Boolean; - procedure RemoveGoto(goto_stmt:TsrStatement;label_stmt:TsrLabel); - procedure EliminateAsConditional(goto_stmt:TsrStatement;label_stmt:TsrLabel); - procedure EliminateAsLoop(goto_stmt:TsrStatement;label_stmt:TsrLabel); - function MoveOutward(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; - function MoveOutwardIf(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; - function MoveOutwardLoop(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; - function MoveInward(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; - function Lift(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; + // + used:Boolean; end; -function last_block:TsrCFGBlock; -function is_valid(v:TsrCFGBlock):Boolean; + TsrSourceInstructionTree=specialize TNodeTreeClass; -function parse_code_cfg(bType:TsrBlockType;pCode:TsrCodeBlock):Integer; + // + + TsrCondition=( + cNone, + cFalse, + cTrue, + cScc0, + cScc1, + cVccz, + cVccnz, + cExecz, + cExecnz, + cTidz, + cTidnz + ); + + TsrStatementType=( + sCond, + sCopy, + sVar, + sStore, + sBreak, + sNot, + sOr, + sAnd + ); + + //sCond TsrCondition + //sCopy [self] [false]:sCond/sCopy/sNot/sOr/sAnd + + //sVar id + + //sStore [var]:sVar [false]:sCond/sCopy/sNot/sOr/sAnd + + //sBreak + + //sNot [cond]:sCond/sCopy/sNot/sOr + + //sOr [cond]:sCond/sCopy/sNot/sOr/sAnd [cond]:sCond/sLoad/sNot/sOr/sAnd + //sAnd [cond]:sCond/sCopy/sNot/sOr/sAnd [cond]:sCond/sLoad/sNot/sOr/sAnd + + TsrStatement=class(TsrSourceNode) + sType:TsrStatementType; + pSrc :TsrStatement; + pDst :TsrStatement; + // + pCache:TObject; + u:record + Case Byte of + 0:(id :PtrUint); + 1:(cond:TsrCondition); + end; + end; + + TsrSourceGoto=class(TsrSourceNode) + FGoto:record + pPrev,pNext:TsrSourceGoto; + end; + // + pCond :TsrStatement; + pLabel:TsrSourceLabel; + end; + + TsrGotoList=object + pHead,pTail:TsrSourceGoto; + //pMiddle:TsrSourceGoto; + procedure Push_head(Node:TsrSourceGoto); + procedure Push_tail(Node:TsrSourceGoto); + procedure InsertAfter (node,new:TsrSourceGoto); + procedure InsertBefore(node,new:TsrSourceGoto); + function Pop_tail:TsrSourceGoto; + procedure Remove(node:TsrSourceGoto); + end; + + // + + TsrBlockType=(btMain,btSetpc,btCond,btElse,btLoop,btMerg,btExec,btInline,btOther); + + TsrSourceBlock=class(TsrSourceNode) + FList:TsrSourceNodeList; + FInit:TsrSourceNodeList; + pCond:TsrStatement; + bType:TsrBlockType; + // + pIf :TsrSourceBlock; + pElse:TsrSourceBlock; + // + function pReal:TsrSourceBlock; + function First:TsrSourceNode; override; + function Last :TsrSourceNode; override; + procedure Push_head(Node:TsrSourceNode); + procedure Push_tail(Node:TsrSourceNode); + function Pop_head:TsrSourceNode; + function Pop_tail:TsrSourceNode; + procedure InsertAfter(node,new:TsrSourceNode); + procedure InsertBefore(node,new:TsrSourceNode); + procedure Remove(node:TsrSourceNode); + Procedure splice(node_first,node_last:TsrSourceNode); + end; + + // + + TsrCodeRegion=class + pNext :TsrCodeRegion; + // + FEmit :TCustomEmit; + Body :Pointer; + DMem :Pointer; + Size :PtrUint; + // + FTop :TsrSourceBlock; + // + function FindByPtr(base:Pointer):TsrSourceNode; + end; + +function get_branch_offset(var FSPI:TSPI):ptrint; +function IsReal(b:TsrBlockType):Boolean; +function parse_code_cfg2(var pCode:TsrCodeRegion;bType:TsrBlockType;Body,Dmem:Pointer;FEmit:TCustomEmit):Integer; implementation -uses - srConfig; +type + TsrCFGParser2=object + FEmit:TCustomEmit; + pCode:TsrCodeRegion; + pCurr:TsrSourceNode; + order:PtrUint; + VarId:Ptruint; + // + FLabelTree:TsrSourceLabelTree; + FInstructionTree:TsrSourceInstructionTree; + FGotoList:TsrGotoList; + FGotoFree:TsrGotoList; + // + Function NewInstruction(b_adr,e_adr:TSrcAdr;var FSPI:TSPI):TsrSourceInstruction; + Function NewLabel (Adr:TSrcAdr):TsrSourceLabel; + Function NewGoto (Cond:TsrCondition;Adr:TSrcAdr):TsrSourceGoto; + Function NewGoto (pCond:TsrStatement;pLabel:TsrSourceLabel):TsrSourceGoto; + procedure FreeGoto (node:TsrSourceGoto); + Function NewBlock (bType:TsrBlockType):TsrSourceBlock; + // + Function NewCond (cond:TsrCondition):TsrStatement; + Function NewCopy (pCond:TsrStatement):TsrStatement; + Function NewVar :TsrStatement; + Function NewStore(pVar,pCond:TsrStatement):TsrStatement; + Function NewBreak:TsrStatement; + Function NewNot (pCond:TsrStatement):TsrStatement; + Function NewOr (pCond1,pCond2:TsrStatement):TsrStatement; + Function NewAnd (pCond1,pCond2:TsrStatement):TsrStatement; + // + procedure EmitGoto(instr:TsrSourceInstruction;Adr:TSrcAdr); + function Parse:Integer; + procedure EmitLabels; + procedure GotoPass; + procedure InitMovePass; + procedure RemoveGoto(goto_stmt:TsrSourceGoto;simple_pass:Boolean); + procedure EliminateAsConditional(goto_stmt:TsrSourceGoto); + procedure EliminateAsLoop (goto_stmt:TsrSourceGoto); + function MoveOutward (goto_stmt:TsrSourceGoto):TsrSourceGoto; + function MoveOutwardIf (goto_stmt:TsrSourceGoto):TsrSourceGoto; + function MoveOutwardElse (goto_stmt:TsrSourceGoto):TsrSourceGoto; + function MoveOutwardLoop (goto_stmt:TsrSourceGoto):TsrSourceGoto; + function MoveOutwardSwitch (goto_stmt:TsrSourceGoto):TsrSourceGoto; + function MoveInward (goto_stmt:TsrSourceGoto):TsrSourceGoto; + function Lift (goto_stmt:TsrSourceGoto):TsrSourceGoto; + procedure ExecPass; + procedure Print; + end; -function parse_code_cfg(bType:TsrBlockType;pCode:TsrCodeBlock):Integer; -var - LParser:TsrCFGParser; +function get_branch_offset(var FSPI:TSPI):ptrint; begin - pCode.FTop.bType:=bType; + Result:=FSPI.OFFSET_DW+Smallint(FSPI.SOPP.SIMM)+1; +end; - LParser:=Default(TsrCFGParser); - LParser.pCode:=pCode; - Result:=LParser.Parse(); - - if PsrConfig(pCode.FEmit.GetConfig)^.PrintCfg then - begin - LParser.Print(); +function IsReal(b:TsrBlockType):Boolean; +begin + case b of + btMain, + btSetpc, + btCond, + btElse, + btLoop:Result:=True; + else + Result:=False; end; end; -function TsrCFGBlock.beg_adr:TSrcAdr; -var - node:TsrCFGBlock; +function TsrSourceNode.ntype:TsrSourceNodeType; inline; begin - node:=Self; - Result:=Default(TSrcAdr); - // - while (node<>nil) do - begin - if (node.pBLabel=nil) then - begin - if (node.pPrev=nil) then - begin - node:=node.pParent; - end else - begin - node:=node.pPrev; - end; - end else - begin - Exit(node.pBLabel.Adr); - end; - end; + Result:=TsrSourceNodeType(ClassType); end; -function TsrCFGBlock.end_adr:TSrcAdr; -var - node:TsrCFGBlock; +function TsrSourceNode.First:TsrSourceNode; begin - node:=Self; - Result:=Default(TSrcAdr); - Result.Offdw:=High(PtrUInt) div 4; - // - while (node<>nil) do - begin - if (node.pELabel=nil) then - begin - if (node.pNext=nil) then - begin - node:=node.pParent; - end else - begin - node:=node.pNext; - end; - end else - begin - Exit(node.pELabel.Adr); - end; - end; -end; - -function TsrCFGBlock.First:TsrCFGBlock; -begin - Result:=FList.pHead; -end; - -function TsrCFGBlock.Last:TsrCFGBlock; -begin - Result:=FList.pTail; -end; - -function TsrCFGBlock.pReal:TsrCFGBlock; -begin - if (Self=nil) then Exit(nil); - Result:=Self; - while (Result<>nil) do - begin - if IsReal(Result.bType) then Break; - Result:=Result.pParent; - end; -end; - -function TsrCFGBlock.IsEndOf(Adr:TSrcAdr):Boolean; -begin - Result:=False; - if (pELabel<>nil) then - begin - Result:=(pELabel.Adr.get_code_ptr<=Adr.get_code_ptr); - end; -end; - -function TsrCFGBlock.IsBigOf(Adr:TSrcAdr):Boolean; -begin - Result:=False; - if (pELabel<>nil) then - begin - Result:=(pELabel.Adr.get_code_ptrnil) then - begin - b:=(pBLabel.Adr.get_code_ptr<=Adr.get_code_ptr); - end; - e:=true; - if (pELabel<>nil) then - begin - e:=(pELabel.Adr.get_code_ptr>Adr.get_code_ptr); - end; - Result:=b and e; -end; - -function TsrCFGBlock.IsInside(Adr:TSrcAdr):Boolean; -var - b,e:Boolean; -begin - b:=true; - if (pBLabel<>nil) then - begin - b:=(pBLabel.Adr.get_code_ptrnil) then - begin - e:=(pELabel.Adr.get_code_ptr>Adr.get_code_ptr); - end; - Result:=b and e; -end; - -function TsrCFGBlock.FindBlock(Adr:TSrcAdr):TsrCFGBlock; -var - node:TsrCFGBlock; -begin - Result:=nil; - node:=First; - While (node<>nil) do - begin - if node.IsContain(Adr) then Exit(node); - node:=node.pNext; - end; -end; - -function TsrCFGBlock.DownBlock(Adr:TSrcAdr):TsrCFGBlock; -var - next:TsrCFGBlock; -begin - Result:=Self; - repeat - next:=Result.FindBlock(Adr); - if (next=nil) then Exit; - Result:=next; - until false; -end; - -function TsrCFGBlock.WorkBlock(Adr:TSrcAdr):TsrCFGBlock; -var - next:TsrCFGBlock; -begin - Result:=Self; - repeat - next:=Result.FindBlock(Adr); - if (next=nil) then Exit; - if (next.beg_adr.get_code_ptr=Adr.get_code_ptr) then Exit; - Result:=next; - until false; -end; - -function last_block:TsrCFGBlock; -begin - Result:=TsrCFGBlock(Pointer(High(ptruint))); -end; - -function is_valid(v:TsrCFGBlock):Boolean; -begin - Result:=(v<>nil) and (v<>last_block); -end; - -function TsrCFGBlock.FindNext(Adr:TSrcAdr):TsrCFGBlock; -var - node:TsrCFGBlock; -begin - Result:=nil; - node:=First; - While (node<>nil) do - begin - if (node.beg_adr.get_code_ptr>Adr.get_code_ptr) then - begin - Exit(node); - end; - node:=node.pNext; - end; - Result:=last_block; -end; - -function TsrCFGBlock.FindPrev(Adr:TSrcAdr):TsrCFGBlock; -var - node:TsrCFGBlock; -begin - Result:=last_block; - node:=Last; - While (node<>nil) do - begin - if (node.end_adr.get_code_ptr<=Adr.get_code_ptr) then - begin - Exit(node); - end; - node:=node.pPrev; - end; Result:=nil; end; -function TsrCFGBlock.UpBlock(Adr:TSrcAdr):TsrCFGBlock; -var - next:TsrCFGBlock; -begin - Result:=Self; - While (Result.IsEndOf(Adr)) do - begin - next:=Result.pParent; - if (next=nil) then Exit; - Result:=next; - end; -end; - -function TsrCFGBlock.FindUpLoop:TsrCFGBlock; -var - node:TsrCFGBlock; +function TsrSourceNode.Last:TsrSourceNode; begin Result:=nil; - node:=Self; - While (node<>nil) do - begin - if (node.bType=btLoop) then Exit(node); - node:=node.pParent; - end; end; -Procedure TsrCFGBlock.Push_front(new:TsrCFGBlock;_first:TsrCFGBlock=nil;_last:TsrCFGBlock=nil); -begin - if (New=nil) then Exit; - new.pParent:=Self; - MoveTo(new,_first,_last); - FList.Push_head(new); -end; - -Procedure TsrCFGBlock.Push_back(new:TsrCFGBlock;_first:TsrCFGBlock=nil;_last:TsrCFGBlock=nil); -begin - if (New=nil) then Exit; - new.pParent:=Self; - MoveTo(new,_first,_last); - FList.Push_tail(new); -end; - -Procedure TsrCFGBlock.Insert_after(node,new:TsrCFGBlock;_first:TsrCFGBlock=nil;_last:TsrCFGBlock=nil); -begin - if (New=nil) then Exit; - new.pParent:=Self; - MoveTo(new,_first,_last); - // - if (node=nil) then - begin - FList.Push_head(new); - end else - if (node=last_block) then - begin - FList.Push_tail(new); - end else - begin - FList.InsertAfter(node,new); - end; -end; - -Procedure TsrCFGBlock.MoveTo(_parent,_first,_last:TsrCFGBlock); +function TsrSourceNode.get_level:DWORD; var - next:TsrCFGBlock; + node:TsrSourceBlock; begin - While (_first<>nil) do - begin - Assert(_first.pParent=Self); - next:=_first.pNext; - FList.Remove(_first); - _parent.FList.Push_tail(_first); - _first.pParent:=_parent; - if (_first=_last) then Break; - _first:=next; - end; -end; - -Procedure TsrCFGBlock.InsertAfterTo(_parent,_after,_first,_last:TsrCFGBlock); -var - next:TsrCFGBlock; -begin - While (_first<>nil) do - begin - Assert(_first.pParent=Self); - next:=_first.pNext; - FList.Remove(_first); - _parent.FList.InsertAfter(_after,_first); - _after:=_first; - _first.pParent:=_parent; - if (_first=_last) then Break; - _first:=next; - end; -end; - -Procedure TsrCFGBlock.MoveFromByRange(_parent:TsrCFGBlock;b_adr,e_adr:TSrcAdr); -var - node:TsrCFGBlock; - next:TsrCFGBlock; -begin - node:=_parent.First; - While (node<>nil) do - begin - next:=node.pNext; - if (node.beg_adr.get_code_ptr>=b_adr.get_code_ptr) then - if (node.end_adr.get_code_ptr<=e_adr.get_code_ptr) then - begin - _parent.FList.Remove(node); - Self.FList.Push_tail(node); - node.pParent:=Self; - end; - node:=next; - end; -end; - -function TsrCFGBlock.ExistByRange(b_adr,e_adr:TSrcAdr):Boolean; -var - node:TsrCFGBlock; -begin - Result:=False; - node:=First; - While (node<>nil) do - begin - if (node.beg_adr.get_code_ptr>=b_adr.get_code_ptr) then - if (node.end_adr.get_code_ptr<=e_adr.get_code_ptr) then - begin - Exit(True); - end; - node:=node.pNext; - end; -end; - -function TsrCFGBlock.get_level:DWORD; -var - node:TsrCFGBlock; -begin - node:=Self; + node:=pParent; Result:=0; While (node<>nil) do begin @@ -512,487 +286,574 @@ begin end; end; -procedure TsrCFGParser.AddUnknowGoto(goto_stmt,next_stmt,label_stmt:TsrLabel;cond:TsrCondition); +/// + +class function TsrSourceAdr.c(n1,n2:PSrcAdr):Integer; var - pCond:TsrStatement; - pGoto:TsrStatement; - - G:TsrUnknowGoto; + ptr1,ptr2:Pointer; begin - goto_stmt.AddType(ltGoto); - - pCond:=pCode.NewCond(cond); - pGoto:=pCode.NewGoto(goto_stmt,next_stmt,pCond); - - G:=pCode.FEmit.specialize New; - G.goto_stmt :=pGoto; - G.label_stmt:=label_stmt; - - FUnknowGotoList.Push_tail(G); + ptr1:=n1^.get_code_ptr; + ptr2:=n2^.get_code_ptr; + Result:=ord(ptr1>ptr2)-ord(ptr1nil) then + if (pHead=nil) then begin - Write('label_',HexStr(Adr.Offdw*4,4),': ;'); - - if (ltUnknow in pLabel.lType) then Write('ltUnknow '); - if (ltGoto in pLabel.lType) then Write('ltGoto '); - if (ltContinue in pLabel.lType) then Write('ltContinue '); - if (ltBreak in pLabel.lType) then Write('ltBreak '); - - writeln; - end; -end; - -function Base64(b:Byte):Char; -begin - case (b and 63) of - 0..25:Result:=Char(b+Byte('A')-0); - 26..51:Result:=Char(b+Byte('a')-26); - 52..61:Result:=Char(b+Byte('0')-52); - 62:Result:='+'; - 63:Result:='-'; - end; -end; - -Function RevOrder(pBlock:TsrCFGBlock):RawByteString; -begin - Result:=''; - while (pBlock<>nil) do + pTail:=node; + node.FGoto.pNext:=nil; + end else begin - if isReal(pBlock.bType) then + pHead.FGoto.pPrev:=node; + node.FGoto.pNext:=pHead; + end; + node.FGoto.pPrev:=nil; + pHead:=node; +end; + +procedure TsrGotoList.Push_tail(Node:TsrSourceGoto); +begin + if (pTail=nil) then + begin + pHead:=node; + node.FGoto.pPrev:=nil; + end else + begin + pTail.FGoto.pNext:=node; + node.FGoto.pPrev:=pTail; + end; + node.FGoto.pNext:=nil; + pTail:=node; +end; + +procedure TsrGotoList.InsertAfter(node,new:TsrSourceGoto); +begin + new.FGoto.pPrev:=node; + if (node.FGoto.pNext=nil) then + begin + new.FGoto.pNext:=nil; + pTail:=new; + end else + begin + Assert(node.FGoto.pNext.FGoto.pPrev=node); + new.FGoto.pNext:=node.FGoto.pNext; + node.FGoto.pNext.FGoto.pPrev:=new; + end; + node.FGoto.pNext:=new; +end; + +procedure TsrGotoList.InsertBefore(node,new:TsrSourceGoto); +begin + new.FGoto.pNext:=node; + if (node.FGoto.pPrev=nil) then + begin + new.FGoto.pPrev:=nil; + pHead:=new; + end else + begin + Assert(node.FGoto.pPrev.FGoto.pNext=node); + new.FGoto.pPrev:=node.FGoto.pPrev; + node.FGoto.pPrev.FGoto.pNext:=new; + end; + node.FGoto.pPrev:=new; +end; + +function TsrGotoList.Pop_tail:TsrSourceGoto; +begin + if (pTail=nil) then + begin + Result:=nil; + end else + begin + Result:=pTail; + pTail:=pTail.FGoto.pPrev; + if (pTail=nil) then begin - Result:=Base64(pBlock.order)+Result; + pHead:=nil; + end else + begin + pTail.FGoto.pNext:=nil; end; - pBlock:=pBlock.pParent; + Result.FGoto.pPrev:=nil; + Result.FGoto.pNext:=nil; end; - Result:=' '+Result+' '; +end; + +procedure TsrGotoList.Remove(node:TsrSourceGoto); +begin + if (node.FGoto.pPrev=nil) then + begin + if (pHead=node) then + begin + pHead:=node.FGoto.pNext; + end; + end else + begin + Assert(node.FGoto.pPrev.FGoto.pNext=node); + node.FGoto.pPrev.FGoto.pNext:=node.FGoto.pNext; + end; + if (node.FGoto.pNext=nil) then + begin + if (pTail=node) then + begin + pTail:=node.FGoto.pPrev; + end; + end else + begin + Assert(node.FGoto.pNext.FGoto.pPrev=node); + node.FGoto.pNext.FGoto.pPrev:=node.FGoto.pPrev; + end; + node.FGoto.pPrev:=nil; + node.FGoto.pNext:=nil; +end; + +/// + +function TsrSourceBlock.pReal:TsrSourceBlock; +begin + if (Self=nil) then Exit(nil); + Result:=Self; + while (Result<>nil) do + begin + if IsReal(Result.bType) then Break; + Result:=Result.pParent; + end; +end; + +function TsrSourceBlock.First:TsrSourceNode; +begin + Result:=FList.pHead; +end; + +function TsrSourceBlock.Last:TsrSourceNode; +begin + Result:=FList.pTail; +end; + +procedure TsrSourceBlock.Push_head(Node:TsrSourceNode); +begin + Assert(Node.pParent=nil); + FList.Push_head(Node); + Node.pParent:=Self; +end; + +procedure TsrSourceBlock.Push_tail(Node:TsrSourceNode); +begin + Assert(Node.pParent=nil); + FList.Push_tail(Node); + Node.pParent:=Self; +end; + +function TsrSourceBlock.Pop_head:TsrSourceNode; +begin + Result:=FList.Pop_head; + if (Result<>nil) then + begin + Result.pParent:=nil; + end; +end; + +function TsrSourceBlock.Pop_tail:TsrSourceNode; +begin + Result:=FList.Pop_tail; + if (Result<>nil) then + begin + Result.pParent:=nil; + end; +end; + +procedure TsrSourceBlock.InsertAfter(node,new:TsrSourceNode); +begin + Assert(node<>nil); + Assert(node.pParent=Self); + Assert(new.pParent=nil); + // + FList.InsertAfter(Node,new); + new.pParent:=Self; +end; + +procedure TsrSourceBlock.InsertBefore(node,new:TsrSourceNode); +begin + Assert(node<>nil); + Assert(node.pParent=Self); + Assert(new.pParent=nil); + // + FList.InsertBefore(Node,new); + new.pParent:=Self; +end; + +procedure TsrSourceBlock.Remove(node:TsrSourceNode); +begin + Assert(node<>nil); + Assert(node.pParent=Self); + // + FList.Remove(node); + node.pParent:=nil; + node.pPrev :=nil; + node.pNext :=nil; +end; + +Procedure TsrSourceBlock.splice(node_first,node_last:TsrSourceNode); //[node_first..node_last) +var + node:TsrSourceNode; + next:TsrSourceNode; + parent:TsrSourceBlock; +begin + Assert(node_first<>nil); + + if (node_last<>nil) then + begin + Assert(node_first.pParent=node_last.pParent); + end; + + parent:=node_first.pParent; + node:=node_first; + While (node<>nil) and (node<>node_last) do + begin + Assert(parent=node.pParent); + next:=node.pNext; + parent.Remove(node); + Push_tail(node); + node:=next; + end; +end; + +/// + +Function TsrCFGParser2.NewInstruction(b_adr,e_adr:TSrcAdr;var FSPI:TSPI):TsrSourceInstruction; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.b_adr:=b_adr; + Result.e_adr:=e_adr; + Result.FSPI :=FSPI; + Result.used :=True; +end; + +Function TsrCFGParser2.NewLabel(Adr:TSrcAdr):TsrSourceLabel; +begin + Result:=FLabelTree.Find(@Adr); + if (Result=nil) then + begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.b_adr:=Adr; + Result.e_adr:=Adr; + // + FLabelTree.Insert(Result); + end; + Inc(Result.links_count); +end; + +Function TsrCFGParser2.NewGoto(Cond:TsrCondition;Adr:TSrcAdr):TsrSourceGoto; +begin + Result:=FGotoFree.Pop_tail; + if (Result=nil) then + begin + Result:=FEmit.specialize New; + end; + Inc(order); + Result.order :=order; + Result.pCond :=NewCond(Cond); + Result.pLabel:=NewLabel(Adr); +end; + +Function TsrCFGParser2.NewGoto(pCond:TsrStatement;pLabel:TsrSourceLabel):TsrSourceGoto; +begin + Result:=FGotoFree.Pop_tail; + if (Result=nil) then + begin + Result:=FEmit.specialize New; + end; + Inc(order); + Result.order :=order; + Result.pCond :=pCond; + Result.pLabel:=pLabel; +end; + +procedure TsrCFGParser2.FreeGoto(node:TsrSourceGoto); +begin + FGotoList.Remove(node); + if (node.pParent<>nil) then + begin + node.pParent.Remove(node); + end; + FGotoFree.Push_tail(node); +end; + +Function TsrCFGParser2.NewBlock(bType:TsrBlockType):TsrSourceBlock; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.bType:=bType; +end; + +Function TsrCFGParser2.NewCond(cond:TsrCondition):TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order :=order; + Result.sType :=sCond; + Result.u.cond:=cond; +end; + +Function TsrCFGParser2.NewCopy(pCond:TsrStatement):TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sCopy; + Result.pDst :=Result; + Result.pSrc :=pCond; + Result.u.id :=VarId; + Inc(VarId); +end; + +Function TsrCFGParser2.NewVar:TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sVar; + Result.u.id :=VarId; + Inc(VarId); +end; + +Function TsrCFGParser2.NewStore(pVar,pCond:TsrStatement):TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sStore; + Result.pDst :=pVar; + Result.pSrc :=pCond; +end; + +Function TsrCFGParser2.NewBreak:TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sBreak; end; const - CondStr:array[TsrCondition] of RawByteString=( - 'None', - 'False', - 'True', - 'Scc0', - 'Scc1', - 'Vccz', - 'Vccnz', - 'Execz', - 'Execnz' + InvertCond:array[TsrCondition] of TsrCondition=( + cNone, //cNone, + cTrue, //cFalse, + cFalse, //cTrue, + cScc1, //cScc0, + cScc0, //cScc1, + cVccnz, //cVccz, + cVccz, //cVccnz, + cExecnz, //cExecz, + cExecz, //cExecnz, + cTidnz, //cTidz, + cTidz //cTidnz ); -function GetCondStr(node:TsrStatement):RawByteString; +Function TsrCFGParser2.NewNot(pCond:TsrStatement):TsrStatement; begin - Result:=''; - while (node<>nil) do + case pCond.sType of + sCond:Result:=NewCond(InvertCond[pCond.u.cond]); + else + begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sNot; + Result.pSrc :=pCond; + end; + end; +end; + +Function TsrCFGParser2.NewOr(pCond1,pCond2:TsrStatement):TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sOr; + Result.pSrc :=pCond1; + Result.pDst :=pCond2; +end; + +Function TsrCFGParser2.NewAnd(pCond1,pCond2:TsrStatement):TsrStatement; +begin + Result:=FEmit.specialize New; + Inc(order); + Result.order:=order; + Result.sType:=sAnd; + Result.pSrc :=pCond1; + Result.pDst :=pCond2; +end; + +/// + +function TSrcAdr.get_code_ptr:PDWORD; +begin + if (pCode=nil) then begin - case node.sType of - sCond :begin Result:=Result+CondStr[node.u.cond]; Break; end; - //sGoto :; - sVar :begin Result:=Result+'V'+IntToStr(node.u.id); Break; end; - //sStore:; - sLoad :begin Result:=Result+'L'+IntToStr(node.u.id); Break; end; - //sBreak:; - sNot :begin Result:='!'+Result; node:=node.pSrc; end; - sOr :begin Result:=Result+'('+GetCondStr(node.pSrc)+' || '+GetCondStr(node.pDst)+')'; Break; end; - sAnd :begin Result:=Result+'('+GetCondStr(node.pSrc)+' && '+GetCondStr(node.pDst)+')'; Break; end; - else Break; - end; - end; -end; - -function GetStatment(node:TsrStatement):RawByteString; -begin - Result:=''; - case node.sType of - //sCond :' - //sGoto :; - //sVar :' - sStore:Result:=GetCondStr(node.pDst)+' = '+GetCondStr(node.pSrc); - sLoad :Result:=GetCondStr(node) +' = '+GetCondStr(node.pSrc); - sBreak:Result:='break'; - //sNot:; - //sOr:; - //sAnd:; - else; - end; -end; - -procedure PrintStatmentList(const prefix:RawByteString;List:TsrStatementList); -var - node:TsrStatement; -begin - node:=List.pHead; - while (node<>nil) do - begin - case node.sType of - sCond:; //skip - sNot :; //skip - sOr :; //skip - sAnd :; //skip - else - Writeln(prefix,GetStatment(node)+';'); - end; - // - node:=node.pNext; - end; -end; - -procedure PrintDown(const prefix:RawByteString;node:TsrCFGBlock); -begin - case node.bType of - btCond:Writeln(prefix,'if (',GetCondStr(node.pCond),') {'); - btLoop:Writeln(prefix,'do {'); - else; - end; -end; - -procedure PrintUp(const prefix:RawByteString;node:TsrCFGBlock); -begin - case node.bType of - btCond:begin - if (node.pElse=nil) then - begin - Writeln(prefix,'};'); - end else - begin - Writeln(prefix,'} else {'); - end; - end; - btElse:Writeln(prefix,'};'); - btLoop:begin - if (node.pCond=nil) then - begin - Writeln(prefix,' break;'); - Writeln(prefix,'} while (true);'); - end else - begin - Writeln(prefix,'} while (',GetCondStr(node.pCond),');'); - end; - end; - else; - end; -end; - -function TsrCFGParser.get_str_prefix(node:TsrCFGBlock;adr:TSrcAdr):RawByteString; -const - print_block_id=False; -begin - if print_block_id then - begin - Result:=' '+HexStr(adr.Offdw*4,3)+RevOrder(node); + Result:=nil; end else begin - Result:=' '+HexStr(adr.Offdw*4,3)+Space(node.get_level); + Result:=pCode.Body; + end; + // + Result:=Pointer(Result)+Offset; +end; + +function TSrcAdr.get_dmem_ptr:PDWORD; +begin + if (pCode=nil) then + begin + Result:=nil + end else + begin + Result:=pCode.DMem; + end; + // + Result:=Pointer(Result)+Offset; +end; + +/// + +function ToAdr(pCode:TsrCodeRegion;Offset:PtrUInt):TSrcAdr; inline; +begin + Result.pCode :=pCode ; + Result.Offset:=Offset; +end; + +procedure TsrCFGParser2.EmitGoto(instr:TsrSourceInstruction;Adr:TSrcAdr); +var + node:TsrSourceGoto; +begin + instr.used:=False; + // + Adr.Offset:=Adr.Offset+(Smallint(instr.FSPI.SOPP.SIMM)*SizeOf(DWORD)); + // + Case instr.FSPI.SOPP.OP of + S_CBRANCH_SCC0 :node:=NewGoto(cScc0 ,Adr); + S_CBRANCH_SCC1 :node:=NewGoto(cScc1 ,Adr); + S_CBRANCH_VCCZ :node:=NewGoto(cVccz ,Adr); + S_CBRANCH_VCCNZ :node:=NewGoto(cVccnz ,Adr); + S_CBRANCH_EXECZ :node:=NewGoto(cExecz ,Adr); + S_CBRANCH_EXECNZ:node:=NewGoto(cExecnz,Adr); + S_BRANCH :node:=NewGoto(cTrue ,Adr); + else + Assert(false); + end; + // + pCurr.pParent.Push_tail(node); + pCurr:=node; + // + if (Smallint(instr.FSPI.SOPP.SIMM)<0) then + begin + //prior to cycles in revers + FGotoList.Push_head(node); + // + + { + if (FGotoList.pMiddle=nil) then + begin + FGotoList.pMiddle:=node; + end; + } + + end else + if (node.pCond.u.cond=cTrue) then + begin + FGotoList.Push_tail(node); + + { + //middle unconditional in revers + if (FGotoList.pMiddle=nil) then + begin + FGotoList.pMiddle:=node; + // + FGotoList.Push_head(node); + end else + begin + //FGotoList.InsertBefore(FGotoList.pMiddle,node); + FGotoList.InsertAfter(FGotoList.pMiddle,node); + end; + } + + end else + begin + FGotoList.Push_tail(node); end; end; -procedure TsrCFGParser.Print(); +function TsrCFGParser2.Parse:Integer; var - prefix:RawByteString; - node,next:TsrCFGBlock; - Adr:TSrcAdr; - i:Integer; -begin - FCursor.Init(TsrLabelBlock(pCode)); - pBlock:=pCode.FTop; - - prefix:=get_str_prefix(pBlock,FCursor.Adr); - - PrintStatmentList(prefix,pBlock.FBefore); - PrintStatmentList(prefix,pBlock.FStart); - - repeat - Adr:=FCursor.Adr; - - //pBlock:=pBlock.DownBlock(Adr); - - node:=pBlock; - repeat - next:=node.FindBlock(Adr); - if (next=nil) then Break; - // - prefix:=get_str_prefix(node,Adr); - - PrintStatmentList(prefix,next.FBefore); - PrintDown(prefix,next); - // - prefix:=get_str_prefix(next,Adr); - - PrintStatmentList(prefix,next.FStart); - // - node:=next; - until false; - pBlock:=node; - - _print_label(Adr); - - prefix:=get_str_prefix(pBlock,Adr); - Write(prefix); - - FSPI:=Default(TSPI); - i:=FCursor.Next(FSPI); - Case i of - 0,1:begin - - Case FSPI.CMD.EN of - W_SOP1:if emit_SOP1 then i:=1; - end; - - print_spi(FSPI); - - Adr:=FCursor.Adr; - - //pBlock:=pBlock.UpBlock(Adr); - - node:=pBlock; - While (node.IsEndOf(Adr)) do - begin - next:=node.pParent; - if (next=nil) then Break; - // - prefix:=get_str_prefix(node,Adr); - - PrintStatmentList(prefix,node.FEnded); - // - prefix:=get_str_prefix(next,Adr); - - PrintUp(prefix,node); - PrintStatmentList(prefix,node.FAfter); - // - node:=next; - end; - pBlock:=node; - - end; - end; - - until (i<>0); - _print_label(Adr); -end; - -function TsrCFGParser.Parse():Integer; + FCursor:TShaderParser; + b_adr,e_adr:TSrcAdr; + FSPI:TSPI; + node:TsrSourceInstruction; begin if (pCode=nil) then Exit(4); - FCursor.Init(TsrLabelBlock(pCode)); - pBlock:=pCode.FTop; - pCode.FTop.pBLabel:=pCode.FetchLabel(FCursor.Adr); + + //init first label + pCurr:=NewLabel(ToAdr(pCode,0)); + pCode.FTop.Push_tail(pCurr); + + FCursor:=Default(TShaderParser); + FCursor.Body:=pCode.Dmem; + + FSPI:=Default(TSPI); + repeat - Result:=NextParse; - Case Result of - 0:; - 1:Break; - else - Break; + b_adr:=ToAdr(pCode,FCursor.OFFSET_DW*SizeOf(DWORD)); + // + Result:=FCursor.Next(FSPI); + if (Result=-1) then Break; + // + e_adr:=ToAdr(pCode,FCursor.OFFSET_DW*SizeOf(DWORD)); + // + node:=NewInstruction(b_adr,e_adr,FSPI); + // + pCurr.pParent.Push_tail(node); + pCurr:=node; + // + FInstructionTree.Insert(node); + // + Case FSPI.CMD.EN of + W_SOP1: + Case FSPI.SOP1.OP of + S_SETPC_B64: + if (pCurr.pParent.bType=btSetpc) then + begin + Result:=1; + Break; + end; + end; + W_SOPP: + Case FSPI.SOPP.OP of + S_CBRANCH_SCC0 :EmitGoto(node,e_adr); + S_CBRANCH_SCC1 :EmitGoto(node,e_adr); + S_CBRANCH_VCCZ :EmitGoto(node,e_adr); + S_CBRANCH_VCCNZ :EmitGoto(node,e_adr); + S_CBRANCH_EXECZ :EmitGoto(node,e_adr); + S_CBRANCH_EXECNZ:EmitGoto(node,e_adr); + S_BRANCH :EmitGoto(node,e_adr); + else; + end; end; + // + if (Result<>0) then Break; + // until false; // - ExecPass; - // - GotoPass; + pCode.Size:=FCursor.OFFSET_DW*SizeOf(DWORD); end; -function GetExecFlow(var FSPI:TSPI):TsrCondition; -begin - Case FSPI.CMD.EN of - W_VOP1 : - Case FSPI.VOP1.OP of - V_NOP :Result:=cNone; - V_READFIRSTLANE_B32:Result:=cFalse; - else - Result:=cTrue; - end; - //W_VOPC -> used separately - W_VOP3 : - Case FSPI.VOP3a.OP of - //VOP3c -> used separately - 0..255 :Result:=cFalse; - 384+V_NOP :Result:=cNone; - 256+V_READLANE_B32 :Result:=cFalse; - 256+V_WRITELANE_B32 :Result:=cFalse; - 384+V_READFIRSTLANE_B32:Result:=cFalse; - else - Result:=cTrue; - end; - W_DS : - Case FSPI.DS.OP of - DS_NOP:Result:=cNone; - else - Result:=cTrue; - end; - W_MUBUF :Result:=cTrue; - W_MTBUF :Result:=cTrue; - //W_EXP -> used separately - W_MIMG :Result:=cTrue; - W_VOP2 : - Case FSPI.VOP2.OP of - V_READLANE_B32 :Result:=cFalse; - V_WRITELANE_B32:Result:=cFalse; - else - Result:=cTrue; - end; - W_SOPP : - Case FSPI.SOPP.OP of - S_NOP :Result:=cNone; - S_WAITCNT:Result:=cNone; - else - Result:=cFalse; - end; - else - Result:=cFalse; - end; -end; - -function TsrCFGParser.FindUpCond(cond:TsrCondition;Adr:TSrcAdr):TsrCFGBlock; -var - node:TsrCFGBlock; -begin - Result:=nil; - node:=pBlock; - While (node<>nil) do - begin - if (node.beg_adr.get_code_ptr<>Adr.get_code_ptr) then - begin - //early exit - Exit(nil); - end; - // - if (node.bType=btCond) then - if (node.pCond<>nil) then - if (node.pCond.sType=sCond) then - if (node.pCond.u.cond=cond) then - begin - Exit(node); - end; - // - node:=node.pParent; - end; -end; - -procedure TsrCFGParser.OpenExec; -var - node:TsrCFGBlock; -begin - if (pBlock.bType=btExec) then - begin - //is opened - Exit; - end; - - node:=NewBlock; - node.pBLabel:=pCode.FetchLabel(FCursor.prev_adr); - node.bType:=btExec; - PushBlock(node); - - if (FindUpCond(cExecnz,FCursor.prev_adr)<>nil) then - begin - //nested cond - node.pCond:=nil; - end else - begin - node.pCond:=pCode.NewCond(cExecnz); - end; -end; - -procedure TsrCFGParser.CloseExec(Before:Boolean); -var - node:TsrCFGBlock; -begin - if (pBlock.bType<>btExec) then - begin - //is not opened - Exit; - end; - - node:=pBlock; - - if Before then - begin - node.pELabel:=pCode.FetchLabel(FCursor.prev_adr); - end else - begin - node.pELabel:=pCode.FetchLabel(FCursor.Adr); - end; - - PopBlock; -end; - -procedure TsrCFGParser.ExecConvert(node:TsrCFGBlock); -var - parent :TsrCFGBlock; - if_stmt:TsrCFGBlock; - if_merg:TsrCFGBlock; -begin - parent:=node.pParent; - if_stmt:=node; - - if (if_stmt.pCond=nil) then - begin - //nested cond - if_stmt.InsertAfterTo(parent,if_stmt,if_stmt.First,nil); - parent.FList.Remove(if_stmt); - Exit; - end; - - if_stmt.bType:=btCond; - - if_merg:=NewBlock; - if_merg.pBLabel:=if_stmt.pBLabel; - if_merg.pELabel:=if_stmt.pELabel; - if_merg.bType:=btMerg; - - parent.Insert_after(if_stmt,if_merg); - parent.MoveTo(if_merg,if_stmt,if_stmt); -end; - -procedure TsrCFGParser.ExecDivide(Adr:TSrcAdr); -var - parent:TsrCFGBlock; - node :TsrCFGBlock; - new :TsrCFGBlock; - pLabel:TsrLabel; -begin - node:=pCode.FTop.DownBlock(adr); - if (node<>nil) then - if (node.bType=btExec) then - if (node.beg_adr.get_code_ptr<>Adr.get_code_ptr) and - (node.end_adr.get_code_ptr<>Adr.get_code_ptr) then - begin - parent:=node.pParent; - pLabel:=pCode.FetchLabel(Adr); - - //[B..C] - node.pELabel:=pLabel; - - //[C..E] - new:=NewBlock; - new.pBLabel:=pLabel; - new.pELabel:=node.pELabel; - new.bType:=btExec; - - if (node.pCond<>nil) then - begin - new.pCond:=pCode.NewCond(cExecnz); - end; - - parent.Insert_after(node,new); - - if (pBlock=node) then - begin - //change current - pBlock:=new; - end; - - end; -end; - -function flow_down_next_up(node:TsrCFGBlock):TsrCFGBlock; +function flow_down_next_up(node:TsrSourceNode):TsrSourceNode; begin Result:=node.First; //down if (Result=nil) then @@ -1004,971 +865,545 @@ begin end; end; -procedure TsrCFGParser.ExecPass; -var - node,prev:TsrCFGBlock; +function flow_next_up(node:TsrSourceNode):TsrSourceNode; begin - if (pCode.FTop=nil) then Exit; - node:=pCode.FTop.First; - While (node<>nil) do - begin - //test - Assert(node.beg_adr.get_code_ptr<=node.end_adr.get_code_ptr,'WTF'); - - Assert(node.pBLabel<>nil,'WTF'); - Assert(node.pELabel<>nil,'WTF'); - - if (node.bType=btExec) then - begin - ExecConvert(node); - end; - - prev:=node; - node:=flow_down_next_up(node); - - //test - if (node<>nil) then - begin - if (node.pParent<>prev) then - begin - Assert(prev.end_adr.get_code_ptr<=node.beg_adr.get_code_ptr,'WTF'); - end; - end; - - end; -end; - -function TsrCFGParser.NextParse:Integer; -begin - FSPI:=Default(TSPI); - // - Result:=FCursor.Next(FSPI); - // - Case Result of - 0,1:; - else Exit; - end; - // - case GetExecFlow(FSPI) of - cFalse:CloseExec(True); - cTrue :OpenExec; - else; - end; - // - Case FSPI.CMD.EN of - W_SOP1:if emit_SOP1 then Result:=1; - W_SOPP:if emit_SOPP then Result:=1; - end; - // - While (CheckBlockEnd) do; - // - if (Result=1) then - begin - Finalize; - end; -end; - -Procedure TsrCFGParser.Finalize; -begin - pCode.FTop.pELabel:=pCode.FetchLabel(FCursor.Adr); - pCode.Size:=FCursor.OFFSET_DW*4; -end; - -function TsrCFGParser.CheckBlockEnd:Boolean; -var - node:TsrCFGBlock; -begin - Result:=False; - if (pBlock=nil) then Exit; - if (pBlock.pParent=nil) then Exit; - - node:=pBlock; - - if (node.bType=btExec) then - begin + repeat //up + Result:=node.pNext; node:=node.pParent; - end; + until (node=nil) or (Result<>nil); +end; - Result:=node.IsEndOf(FCursor.Adr); - - if Result then +function flow_down_next(node:TsrSourceNode):TsrSourceNode; +begin + Result:=node.First; //down + if (Result=nil) then begin - CloseExec(False); - Assert(node.bType<>btExec); - - PopBlock; + //next + Result:=node.pNext; end; end; -function TsrCFGParser.emit_SOP1:Boolean; -begin - Result:=False; - Case FSPI.SOP1.OP of - S_SETPC_B64: - if (pBlock.bType=btSetpc) then - begin - Result:=True; - end; - end; -end; - -function TsrCFGParser.emit_SOPP:Boolean; -begin - Result:=False; - Case FSPI.SOPP.OP of - - S_ENDPGM:; - - S_CBRANCH_SCC0 :emit_S_BRANCH(cScc0); - S_CBRANCH_SCC1 :emit_S_BRANCH(cScc1); - S_CBRANCH_VCCZ :emit_S_BRANCH(cVccz); - S_CBRANCH_VCCNZ :emit_S_BRANCH(cVccnz); - S_CBRANCH_EXECZ :emit_S_BRANCH(cExecz); - S_CBRANCH_EXECNZ:emit_S_BRANCH(cExecnz); - S_BRANCH :emit_S_BRANCH(cTrue); - - else; - end; -end; - -Function TsrCFGParser.NewBlock:TsrCFGBlock; -begin - Inc(order); - Result:=pCode.FEmit.specialize New; - Result.order:=order; -end; - -Procedure TsrCFGParser.PushBlock(New:TsrCFGBlock); -begin - if (New=nil) then Exit; - - Assert(pBlock.bType<>btExec); - - pBlock.FList.Push_tail(New); - New.pParent:=pBlock; - pBlock:=New; -end; - -function TsrCFGParser.PopBlock:Boolean; -begin - Result:=False; - if (pBlock=nil) then Exit; - if (pBlock.pParent=nil) then Exit; - pBlock:=pBlock.pParent; - Result:=True; -end; - -function TsrCFGParser.FindUpperLoop(branch_adr:TSrcAdr;var r_child,r_parent:TsrCFGBlock):Integer; +procedure TsrCFGParser2.EmitLabels; var - child,parent,next:TsrCFGBlock; -begin - Result:=0; - r_child :=nil; - r_parent:=nil; - - child :=pBlock.FList.pTail; - parent:=pBlock; - - repeat - - if parent.IsInside(branch_adr) then - begin - next:=child; - while (child<>nil) do - begin - if (parent.bType=btLoop) then - if (not child.EndFixed) then - if (child.pCond=nil) then //no post conditions - begin - //is exist loop - if (child.beg_adr.get_code_ptr=branch_adr.get_code_ptr) then - begin - //case 3 - r_child :=child; - r_parent:=parent; - Exit(3); - end; - end; - - if (child.end_adr.get_code_ptr<=branch_adr.get_code_ptr) then - begin - //restore - child:=next; - Break; - end; - - // - next:=child; - child:=child.pPrev; - end; - //restore - child:=next; - - if (child<>nil) then - begin - if child.IsInside(branch_adr) then - begin - Exit(0); - end; - - if (child.end_adr.get_code_ptr<=branch_adr.get_code_ptr) then - begin - //no child - child:=nil; - end; - end; - - //case 2 - r_child :=child; - r_parent:=parent; - Exit(2); - end else //IsInside - if (parent.bType=btLoop) then - begin - //is exist loop - if (parent.beg_adr.get_code_ptr=branch_adr.get_code_ptr) then - begin - //case 1 - r_parent:=parent; - Exit(1); - end else - begin - Exit(0); - end; - end; - - if (parent.beg_adr.get_code_ptr<=branch_adr.get_code_ptr) then Break; - - if (parent.pParent=nil) then Break; - child :=parent; - parent:=parent.pParent; - until false; -end; - -function TsrCFGParser.FindLowerLoop(branch_adr:TSrcAdr;var r_child,r_parent:TsrCFGBlock):Integer; -var - child,parent:TsrCFGBlock; -begin - Result:=0; - r_child :=nil; - r_parent:=nil; - - child :=nil; - parent:=pBlock; - - repeat - - if parent.IsInside(branch_adr) or - (parent.end_adr.get_code_ptr=branch_adr.get_code_ptr) then - begin - //case 2 - r_child :=child; - r_parent:=parent; - Exit(2); - end else - if (parent.bType=btLoop) then - begin - //is exist loop - if (parent.end_adr.get_code_ptr=branch_adr.get_code_ptr) then - begin - //case 1 - r_parent:=parent; - Exit(1); - end else - begin - Exit(0); - end; - end; - - if (parent.end_adr.get_code_ptr>branch_adr.get_code_ptr) then Break; - - if (parent.pParent=nil) then Break; - child :=parent; - parent:=parent.pParent; - until false; -end; - -procedure UpdateUp(node:TsrCFGBlock); -var - child:TsrCFGBlock; - updateB,updateE:Boolean; + node:TsrSourceGoto; + inst:TsrSourceInstruction; begin + node:=FGotoList.pHead; + // while (node<>nil) do begin - - case node.bType of - btCond:; - btElse:; - btLoop:; - btMerg:; - else - Break; - end; - - updateB:=False; - updateE:=False; - - //update begin label - child:=node.First; - if (child<>nil) then - begin - if (node.pBLabel=nil) then - begin - updateB:=True; - end else - if (node.pBLabel.Adr.get_code_ptr>child.pBLabel.Adr.get_code_ptr) then - begin - updateB:=True; - end; - // - if updateB then - begin - node.pBLabel:=child.pBLabel; - end; - end; - - //update end label - child:=node.FList.pTail; - if (child<>nil) then - begin - if (node.pELabel=nil) then - begin - updateE:=True; - end else - if (node.pELabel.Adr.get_code_ptrnil); // - node:=node.pParent; - end; -end; - -procedure TsrCFGParser.emit_S_BRANCH(cond:TsrCondition); -var - pPrev,pNext,pBranch:TsrLabel; - c_adr,b_adr:TSrcAdr; - node,child,parent:TsrCFGBlock; - prevLabel:TsrLabelType; -begin - if (FSPI.SOPP.SIMM=0) then - begin - Exit; //skip - end; - - c_adr:=FCursor.Adr; - b_adr:=c_adr; - b_adr.Offdw:=get_branch_offset(FSPI); - - pNext :=pCode.FetchLabel(c_adr); - pBranch:=pCode.FetchLabel(b_adr); - //pPrev:=pCode.FetchLabel(FCursor.prev_adr); - - ExecDivide(b_adr); - - { - //test - begin - pPrev:=pCode.FetchLabel(FCursor.prev_adr); - - AddUnknowGoto(pPrev,pNext,pBranch,cond); - Exit; - end; - } - - prevLabel:=ltUnknow; - - if (SmallInt(FSPI.SOPP.SIMM)<0) then //up - begin - -{ - - [case:1] - while () do<-\ - { | - if (eval) | - { | - continue---/ - } - } - - [case:2] - <------------\ - | - if (eval) | - { | - //do | - } | - | - if (eval) | - { | - continue----/ - } - - [case:3] - while () do<-\ - { | - //do | - } | - | - if (eval) | - { | - //do | - } | - | - if (eval) | - { | - continue----/ - } - -} - - - parent:=nil; - child :=nil; - case FindUpperLoop(b_adr,child,parent) of - 1: - begin - prevLabel:=ltContinue; - end; - 2: - begin - //new loop block - - prevLabel:=ltContinue; - - pNext.RemType(ltUnknow); - - node:=NewBlock; - node.pBLabel:=pBranch; - node.pELabel:=pNext; - node.bType:=btLoop; - - parent.Push_back(node,child); - - //update end label - UpdateUp(node); - - //update block - pBlock:=pCode.FTop.DownBlock(FCursor.prev_adr); - - end; - 3: - begin - //move to loop block - - prevLabel:=ltContinue; - - node:=child; //loop - child:=node.pNext; - - parent.MoveTo(node,child,nil); - - //update end label - UpdateUp(node); - - //update block - pBlock:=pCode.FTop.DownBlock(FCursor.prev_adr); - - end; - else - begin - //Assert(False,'AddUnknowGoto'); - - pPrev:=pCode.FetchLabel(FCursor.prev_adr); - - AddUnknowGoto(pPrev,pNext,pBranch,cond); - Exit; - end; - end; - - end else //down - begin - -{ - [case:0] - if (eval) - { - //do - } - - [case:1] - while () do - { - if (eval) - { - break------\ - } | - }<-----------/ - - [case:2] - if (eval) - { - break-------\ - } | - | - <------------/ - -} - - if (pBlock.end_adr.get_code_ptrelse - node .pIf :=child; //else->if - - end else - begin - //new loop block - - prevLabel:=ltBreak; - - node:=NewBlock; - node.pBLabel:=pNext; - node.pELabel:=pBranch; - node.bType:=btLoop; - node.EndFixed:=True; - - parent.Push_back(node,child); - - //update begin label - UpdateUp(node); - - //update block - pBlock:=pCode.FTop.DownBlock(FCursor.prev_adr); - end; - - end; - else - begin - //Assert(False,'AddUnknowGoto'); - - pPrev:=pCode.FetchLabel(FCursor.prev_adr); - - AddUnknowGoto(pPrev,pNext,pBranch,cond); - Exit; - end; - end; - - end else - begin - //add merge block - node:=NewBlock; - node.pBLabel:=pNext; - node.pELabel:=pBranch; - node.bType:=btMerg; - PushBlock(node); - - //if (eval) {} - - node:=NewBlock; - node.pBLabel:=pNext; - node.pELabel:=pBranch; - node.bType:=btCond; - PushBlock(node); - - //set cond to block - if (cond<>cTrue) then - begin - //The instruction specifies which block to skip, so need to invert the condition! - node.pCond:=pCode.NewCond(InvertCond[cond]); - - //mark used - pPrev:=pCode.FetchLabel(FCursor.prev_adr); - pPrev.AddType(ltGoto); - end; - + inst.pParent.InsertBefore(inst,node.pLabel); end; - - end; //if (SmallInt(FSPI.SOPP.SIMM)<0) then - - if (prevLabel<>ltUnknow) then - begin - - pPrev:=pCode.FetchLabel(FCursor.prev_adr); - pPrev.AddType(prevLabel); - - //add extra block - if (cond<>cTrue) then - begin - //add merge block - node:=NewBlock; - node.pBLabel:=pPrev; //prev_adr - node.pELabel:=pNext; //c_adr - node.bType:=btMerg; - PushBlock(node); - - //if (eval) {} - - node:=NewBlock; - node.pBLabel:=pPrev; - node.pELabel:=pNext; - node.bType:=btCond; - PushBlock(node); - end; - end; - -end; - -procedure TsrCFGParser.GotoPass; -var - node:TsrUnknowGoto; -begin - node:=FUnknowGotoList.pHead; - while (node<>nil) do - begin - //Print(); // - RemoveGoto(node.goto_stmt,node.label_stmt); - // - node:=node.pNext; + node:=node.FGoto.pNext; end; end; -function TsrCFGParser.BlockOf(stmt:TsrLabel):TsrCFGBlock; +function Level(stmt:TsrSourceNode):DWORD; inline; begin - Result:=pCode.FTop.DownBlock(stmt.Adr); + Result:=stmt.get_level; end; -function TsrCFGParser.LevelOf(stmt:TsrLabel):DWORD; -begin - Result:=BlockOf(stmt).get_level; -end; - -function TsrCFGParser.IsDirectlyRelated(goto_stmt,label_stmt:TsrLabel):Boolean; +function IsDirectlyRelated(goto_stmt,label_stmt:TsrSourceNode):Boolean; var - min_level :DWORD; - max_level :DWORD; - l :DWORD; - min_up:TsrCFGBlock; - max_up:TsrCFGBlock; - m :TsrCFGBlock; + goto_level,label_level:DWORD; + min_level,max_level:DWORD; + min,max:TsrSourceNode; begin - min_up:=BlockOf(goto_stmt); - max_up:=BlockOf(label_stmt); + goto_level :=Level(goto_stmt); + label_level:=Level(label_stmt); - min_level:=min_up.get_level; - max_level:=max_up.get_level; - - if (max_level < min_level) then + if (label_level < goto_level) then begin - m :=min_up; - min_up:=max_up; - max_up:=m; - // - l :=min_level; - min_level:=max_level; - max_level:=l; + min_level:=label_level; + max_level:=goto_level; + min:=label_stmt; + max:=goto_stmt; + end else + begin // goto_level < label_level + min_level:=goto_level; + max_level:=label_level; + min:=goto_stmt; + max:=label_stmt; end; - while (max_up<>nil) do + while (max_level > min_level) do begin - if (min_up=max_up) then - begin - Exit(True); - end; - max_up:=max_up.pParent.pReal; + Dec(max_level); + max:=max.pParent.pReal; end; - Result:=False; + Result:=(min.pParent.pReal=max.pParent.pReal); end; -function TsrCFGParser.IsIndirectlyRelated(goto_stmt,label_stmt:TsrLabel):Boolean; +function IsIndirectlyRelated(goto_stmt,label_stmt:TsrSourceNode):Boolean; begin - Result:=(BlockOf(goto_stmt) <> BlockOf(label_stmt)) and - (not IsDirectlyRelated(goto_stmt,label_stmt)); + Result:=(goto_stmt.pParent.pReal <> label_stmt.pParent.pReal) and + (not IsDirectlyRelated(goto_stmt, label_stmt)); end; -function TsrCFGParser.AreSiblings(stmt:TsrCFGBlock;label_stmt:TsrLabel):Boolean; +function AreSiblings(goto_stmt,label_stmt:TsrSourceNode):Boolean; inline; +begin + Result:=(goto_stmt.pParent.pReal=label_stmt.pParent.pReal); +end; + +function SiblingFromNephew(uncle,nephew:TsrSourceNode;up:Boolean):TsrSourceNode; var - pParent1:TsrCFGBlock; - pParent2:TsrCFGBlock; + parent,it,it_up:TsrSourceNode; begin - pParent1:=stmt.pParent.pReal; - pParent2:=BlockOf(label_stmt); - // - Result:=(pParent1=pParent2); -end; + parent:=uncle.pParent.pReal; + it :=nephew; + it_up :=it.pParent.pReal; -function TsrCFGParser.AreSiblings(stmt,label_stmt:TsrLabel):Boolean; -begin - Result:=BlockOf(stmt)=BlockOf(label_stmt); -end; - -function TsrCFGParser.SiblingFromNephew(uncle,nephew:TsrLabel):TsrCFGBlock; -var - parent:TsrCFGBlock; - it_up :TsrCFGBlock; - it :TsrCFGBlock; -begin - parent:=BlockOf(uncle); - it_up :=BlockOf(nephew); - it :=it_up; - - while (it_up<>parent) do + while (it_up <> nil) and (it_up <> parent) do begin it :=it_up; it_up:=it.pParent.pReal; end; + if up then + if (it.pParent<>nil) then + if (it.pParent.bType=btMerg) then + begin + it:=it.pParent; + end; + Result:=it; end; -function TsrCFGParser.AreOrdered(left_sibling:TsrCFGBlock;right_sibling:TsrLabel):Boolean; -begin - if AreSiblings(left_sibling,right_sibling) then - begin - Result:=right_sibling.Adr.get_code_ptr>left_sibling.beg_adr.get_code_ptr; - end else - begin - Result:=False; - end; -end; - -function TsrCFGParser.AreOrdered(left_sibling,right_sibling:TsrLabel):Boolean; -begin - if AreSiblings(left_sibling,right_sibling) then - begin - Result:=right_sibling.Adr.get_code_ptr>left_sibling.Adr.get_code_ptr; - end else - begin - Result:=False; - end; -end; - -function TsrCFGParser.NeedsLift(goto_stmt,label_stmt:TsrLabel):Boolean; +function AreOrdered(left_sibling,right_sibling:TsrSourceNode):Boolean; var - sibling:TsrCFGBlock; + it:TsrSourceNode; begin - sibling:=SiblingFromNephew(goto_stmt,label_stmt); + if AreSiblings(left_sibling,right_sibling) then + begin + it:=right_sibling; + while (it<>nil) do + begin + if (it=left_sibling) then Exit(False); + // + it:=it.pNext; + end; + Result:=True; + end else + begin + Result:=False; + end; +end; + +function NeedsLift(goto_stmt,label_stmt:TsrSourceNode):Boolean; +var + sibling:TsrSourceNode; +begin + sibling:=SiblingFromNephew(goto_stmt,label_stmt,True); Result:=AreOrdered(sibling,goto_stmt); end; -procedure TsrCFGParser.RemoveGoto(goto_stmt:TsrStatement;label_stmt:TsrLabel); -label - _rep; - -var - label_level:DWORD; - goto_level :DWORD; +Function IsUnconditional(cond:TsrStatement):Boolean; inline; begin - { - Writeln('---'); - _print_label(goto_stmt.sLabel.Adr); - _print_label(label_stmt.Adr); - Writeln('---'); - } + Result:=(cond.sType=sCond) and (cond.u.cond=cTrue) +end; - _rep: +Function IsUnreachable(cond:TsrStatement):Boolean; inline; +begin + Result:=(cond.sType=sCond) and (cond.u.cond=cFalse) +end; - // Force goto_stmt and label_stmt to be directly related - if IsIndirectlyRelated(goto_stmt.sLabel,label_stmt) then +procedure TsrCFGParser2.GotoPass; +var + node,next:TsrSourceGoto; +begin + node:=FGotoList.pHead; + // + while (node<>nil) do begin + next:=node.FGoto.pNext; + // + RemoveGoto(node,True); + // + node:=next; + end; + // + node:=FGotoList.pHead; + // + while (node<>nil) do + begin + next:=node.FGoto.pNext; + // + RemoveGoto(node,False); + // + node:=next; + end; + // +end; + +procedure MoveListBefore(List:TsrSourceNodeList;before:TsrSourceNode); +var + node:TsrSourceNode; +begin + while (List.pHead<>nil) do + begin + node:=List.Pop_head; + before.pParent.InsertBefore(before,node); + end; +end; + +procedure TsrCFGParser2.InitMovePass; +var + node,next:TsrSourceNode; +begin + node:=pCode.FTop.First; + + while (node<>nil) do + begin + next:=flow_down_next_up(node); + + if (node.ntype=TsrSourceBlock) then + begin + MoveListBefore(TsrSourceBlock(node).FInit,node); + end; + + node:=next; + end; +end; + +Function NextUsed(node:TsrSourceNode):TsrSourceNode; +begin + Result:=node.pNext; + while (Result<>nil) do + begin + if (Result.ntype=TsrSourceInstruction) then + begin + if not TsrSourceInstruction(Result).used then + begin + Result:=Result.pNext; + Continue; + end; + end; + Break; + end; +end; + +Function NextUsedFlowUp(node:TsrSourceNode):TsrSourceNode; +begin + Result:=flow_next_up(node); + while (Result<>nil) do + begin + if (Result.ntype=TsrSourceInstruction) then + begin + if not TsrSourceInstruction(Result).used then + begin + Result:=flow_next_up(Result); + Continue; + end; + end; + Break; + end; +end; + +Function NextUsedFlowDown(node:TsrSourceNode):TsrSourceNode; +begin + Result:=flow_down_next(node); + while (Result<>nil) do + begin + if (Result.ntype=TsrSourceInstruction) then + begin + if not TsrSourceInstruction(Result).used then + begin + Result:=flow_down_next(Result); + Continue; + end; + end; + Break; + end; +end; + +procedure TsrCFGParser2.RemoveGoto(goto_stmt:TsrSourceGoto;simple_pass:Boolean); +var + label_stmt:TsrSourceLabel; + label_level,goto_level:DWORD; +begin + // Force goto_stmt and label_stmt to be directly related + label_stmt:=goto_stmt.pLabel; + if (IsIndirectlyRelated(goto_stmt, label_stmt)) then + begin + if simple_pass then Exit; // Move goto_stmt out using outward-movement transformation until it becomes // directly related to label_stmt - while (not IsDirectlyRelated(goto_stmt.sLabel, label_stmt)) do + while (not IsDirectlyRelated(goto_stmt, label_stmt)) do begin - goto_stmt:=MoveOutward(goto_stmt,label_stmt); - end; + goto_stmt:=MoveOutward(goto_stmt); + end end; - // Force goto_stmt and label_stmt to be siblings - if IsDirectlyRelated(goto_stmt.sLabel, label_stmt) then + if (IsDirectlyRelated(goto_stmt, label_stmt)) then begin - label_level:=LevelOf(label_stmt); - goto_level :=LevelOf(goto_stmt.sLabel); + label_level:=Level(label_stmt); + goto_level :=Level(goto_stmt); if (goto_level > label_level) then begin + if simple_pass then Exit; // Move goto_stmt out of its level using outward-movement transformations while (goto_level > label_level) do begin - goto_stmt:=MoveOutward(goto_stmt,label_stmt); + goto_stmt:=MoveOutward(goto_stmt); //Dec(goto_level); - goto_level:=LevelOf(goto_stmt.sLabel); + goto_level:=Level(goto_stmt); end; - end else // Level(goto_stmt) < Level(label_stmt) + end else + if (goto_level < label_level) then begin - if (NeedsLift(goto_stmt.sLabel, label_stmt)) then + if simple_pass then Exit; + // + if (NeedsLift(goto_stmt, label_stmt)) then begin // Lift goto_stmt to above stmt containing label_stmt using goto-lifting // transformations - goto_stmt:=Lift(goto_stmt,label_stmt); - //update - label_level:=LevelOf(label_stmt); - goto_level :=LevelOf(goto_stmt.sLabel); + goto_stmt:=Lift(goto_stmt); end; // Move goto_stmt into label_stmt's level using inward-movement transformation while (goto_level < label_level) do begin - goto_stmt:=MoveInward(goto_stmt,label_stmt); - //Inc(goto_level); - goto_level:=LevelOf(goto_stmt.sLabel); + goto_stmt:=MoveInward(goto_stmt); + Inc(goto_level); end; end; end; - - if (not AreSiblings(goto_stmt.sLabel, label_stmt)) then + // + if (not AreSiblings(goto_stmt, label_stmt)) then begin - //Goto is not a sibling with the label - goto _rep; + Assert(false,'Goto is not a sibling with the label'); end; - // goto_stmt and label_stmt are guaranteed to be siblings, eliminate - if (goto_stmt.sNext.Adr.get_code_ptr=label_stmt.Adr.get_code_ptr) then + if (NextUsed(goto_stmt) = label_stmt) then begin // Simply eliminate the goto if the label is next to it + FreeGoto(goto_stmt); end else - if AreOrdered(goto_stmt.sLabel, label_stmt) then + if (AreOrdered(goto_stmt, label_stmt)) then begin // Eliminate goto_stmt with a conditional - EliminateAsConditional(goto_stmt, label_stmt); + EliminateAsConditional(goto_stmt); end else begin // Eliminate goto_stmt with a loop - EliminateAsLoop(goto_stmt, label_stmt); + EliminateAsLoop(goto_stmt); end; - end; -procedure TsrCFGParser.EliminateAsConditional(goto_stmt:TsrStatement;label_stmt:TsrLabel); +procedure InsertAfter(node,new:TsrSourceNode); var - parent :TsrCFGBlock; - cond :TsrStatement; - neg_cond:TsrStatement; - if_stmt :TsrCFGBlock; - if_merg :TsrCFGBlock; - prev :TsrCFGBlock; + parent:TsrSourceBlock; begin - parent:=BlockOf(goto_stmt.sLabel); + parent:=node.pParent; + if (parent.bType=btMerg) then + begin + node:=parent; + parent:=node.pParent; + end; + parent.InsertAfter(node,new); +end; - cond :=goto_stmt.pSrc; - neg_cond:=pCode.NewNot(cond); +procedure InsertBefore(node,new:TsrSourceNode); +var + parent:TsrSourceBlock; +begin + parent:=node.pParent; + if (parent.bType=btMerg) then + begin + node:=parent; + parent:=node.pParent; + end; + parent.InsertBefore(node,new); +end; + +procedure TsrCFGParser2.EliminateAsConditional(goto_stmt:TsrSourceGoto); +var + label_stmt:TsrSourceLabel; + cond :TsrStatement; + neg_cond :TsrStatement; + if_stmt :TsrSourceBlock; + if_merg :TsrSourceBlock; +begin + label_stmt:=goto_stmt.pLabel; + + if_merg:=NewBlock(btMerg); + if_stmt:=NewBlock(btCond); + if_merg.Push_tail(if_stmt); + + if_stmt.splice(goto_stmt.pNext,label_stmt); + + InsertAfter(goto_stmt,if_merg); + + cond:=goto_stmt.pCond; + + neg_cond:=NewNot(cond); + if_merg.FInit.Push_tail(neg_cond); - if_stmt:=NewBlock; - if_stmt.pBLabel:=goto_stmt.sNext; - if_stmt.pELabel:=label_stmt; if_stmt.pCond:=neg_cond; - if_stmt.bType:=btCond; - if_stmt.MoveFromByRange(parent,if_stmt.beg_adr,if_stmt.end_adr); - if_merg:=NewBlock; - if_merg.pBLabel:=if_stmt.pBLabel; - if_merg.pELabel:=if_stmt.pELabel; - if_merg.bType:=btMerg; - if_merg.Push_back(if_stmt); - - if_merg.FBefore.Push_tail(neg_cond); - - prev:=parent.FindPrev(if_merg.beg_adr); - parent.Insert_after(prev,if_merg); - - //update labels - UpdateUp(if_stmt); + // + FreeGoto(goto_stmt); end; -procedure TsrCFGParser.EliminateAsLoop(goto_stmt:TsrStatement;label_stmt:TsrLabel); +procedure TsrCFGParser2.EliminateAsLoop(goto_stmt:TsrSourceGoto); var - parent :TsrCFGBlock; - cond :TsrStatement; - loop_stmt:TsrCFGBlock; - prev :TsrCFGBlock; + label_stmt:TsrSourceLabel; + cond :TsrStatement; + loop_stmt :TsrSourceBlock; begin - parent:=BlockOf(goto_stmt.sLabel); + label_stmt:=goto_stmt.pLabel; - cond:=goto_stmt.pSrc; + loop_stmt:=NewBlock(btLoop); + loop_stmt.splice(label_stmt,goto_stmt); + + InsertBefore(goto_stmt,loop_stmt); + + cond:=goto_stmt.pCond; - loop_stmt:=NewBlock; - loop_stmt.pBLabel:=label_stmt; - loop_stmt.pELabel:=goto_stmt.sLabel; loop_stmt.pCond:=cond; - loop_stmt.bType:=btLoop; - loop_stmt.MoveFromByRange(parent,loop_stmt.beg_adr,loop_stmt.end_adr); - prev:=parent.FindPrev(loop_stmt.beg_adr); - parent.Insert_after(prev,loop_stmt); - - //update labels - UpdateUp(loop_stmt); + // + FreeGoto(goto_stmt); end; -function TsrCFGParser.MoveOutward(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; -var - parent:TsrCFGBlock; +function FindUpLoop(node:TsrSourceBlock):TsrSourceBlock; begin - if (goto_stmt.sNext.Adr.get_code_ptr=label_stmt.Adr.get_code_ptr) then + Result:=nil; + While (node<>nil) do + begin + if (node.bType=btLoop) then Exit(node); + node:=node.pParent; + end; +end; + +function IsBreakLoop(goto_stmt:TsrSourceGoto):Boolean; +var + loop:TsrSourceBlock; + node:TsrSourceNode; +begin + Result:=False; + loop:=FindUpLoop(goto_stmt.pParent); + if (loop<>nil) then + begin + node:=goto_stmt.pLabel; + while (node<>nil) do + begin + if (node=loop) then + begin + //label inside loop + Exit(False); + end; + // + node:=node.pParent; + end; + // + Result:=True; + end; +end; + +{ + if (eval) + { + break-------\ + } | + ... | + <------------/ +} + +function IsBreakElse(goto_stmt:TsrSourceGoto):Boolean; +var + parent:TsrSourceBlock; +begin + Result:=False; + if IsUnconditional(goto_stmt.pCond) then + if (NextUsed(goto_stmt)=nil) then + if (goto_stmt.pParent<>nil) then + if (goto_stmt.pParent.bType=btCond) then + begin + parent:=goto_stmt.pParent; + parent:=parent.pParent; + if (parent<>nil) then + if (parent.bType=btMerg) then + if (NextUsed(parent)<>goto_stmt.pLabel) then + begin + Result:=AreOrdered(parent,goto_stmt.pLabel); + end; + end; +end; + +function IsBreakSwitch(goto_stmt:TsrSourceGoto):Boolean; +var + label_stmt:TsrSourceLabel; + parent:TsrSourceBlock; +begin + Result:=False; + + label_stmt:=goto_stmt.pLabel; + + //if IsUnconditional(goto_stmt.pCond) then + //if (NextUsed(goto_stmt)=nil) then + if (goto_stmt.pParent<>nil) then + if (goto_stmt.pParent.bType=btCond) then + if (label_stmt.links_count>1) then + begin + parent:=goto_stmt.pParent; + parent:=parent.pParent; + + if (NextUsedFlowUp(parent)<>label_stmt) then + while (parent<>nil) do + begin + + if (parent.bType=btLoop) then + begin + Exit(False); + end else + if AreSiblings(parent,label_stmt) then + begin + Exit(True); + end; + + parent:=parent.pParent; + end; + + end; +end; + +function TsrCFGParser2.MoveOutward(goto_stmt:TsrSourceGoto):TsrSourceGoto; +var + parent:TsrSourceBlock; +begin + if (NextUsed(goto_stmt)=goto_stmt.pLabel) then begin Exit(goto_stmt); end; - parent:=BlockOf(goto_stmt.sLabel); + if IsBreakElse(goto_stmt) then + begin + Exit(MoveOutwardElse(goto_stmt)); + end; + + if IsBreakSwitch(goto_stmt) then + begin + Exit(MoveOutwardSwitch(goto_stmt)); + end; + + if IsBreakLoop(goto_stmt) then + begin + Exit(MoveOutwardLoop(goto_stmt)); + end; + + parent:=goto_stmt.pParent.pReal; case parent.bType of - btCond:Result:=MoveOutwardIf (goto_stmt,label_stmt); - btElse:Result:=MoveOutwardIf (goto_stmt,label_stmt); - btLoop:Result:=MoveOutwardLoop(goto_stmt,label_stmt); + btCond:Result:=MoveOutwardIf (goto_stmt); + btElse:Result:=MoveOutwardIf (goto_stmt); + btLoop:Result:=MoveOutwardLoop(goto_stmt); else begin Writeln(stderr,'Invalid outward movement:',parent.bType); @@ -2013,76 +1448,194 @@ end; L1: stmt_n; } +//--> +{ + .... + goto_L1 = false; + if (expr) + { + stmt_1; + .... + goto_L1 = cond; + } + if (goto_L1) goto L1; + .... + L1: + stmt_n; +} -function TsrCFGParser.MoveOutwardIf(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; +function TsrCFGParser2.MoveOutwardIf(goto_stmt:TsrSourceGoto):TsrSourceGoto; var - parent :TsrCFGBlock; - pmerge :TsrCFGBlock; - prev :TsrCFGBlock; - new_var :TsrStatement; - set_var :TsrStatement; - cond :TsrStatement; - neg_cond:TsrStatement; - new_cond:TsrStatement; - new_goto:TsrStatement; - if_stmt :TsrCFGBlock; - if_merg :TsrCFGBlock; + label_stmt:TsrSourceLabel; + parent :TsrSourceBlock; + pmerge :TsrSourceBlock; + new_var :TsrStatement; + set_var :TsrStatement; + cond :TsrStatement; + neg_cond :TsrStatement; + new_goto :TsrSourceGoto; + if_stmt :TsrSourceBlock; + if_merg :TsrSourceBlock; begin - parent:=BlockOf(goto_stmt.sLabel); + label_stmt:=goto_stmt.pLabel; + + parent:=goto_stmt.pParent; pmerge:=parent.pParent; Assert(pmerge<>nil); Assert(pmerge.bType=btMerg); - cond:=goto_stmt.pSrc; + cond:=goto_stmt.pCond; - new_var:=pCode.NewVar; + if (NextUsedFlowUp(pmerge)<>label_stmt) then + begin + new_var:=NewVar; + end else + begin + //simplification + new_var:=nil; + end; - //goto_L1 = false; - set_var:=pCode.NewStore(new_var,pCode.NewCond(cFalse)); - pmerge.FBefore.Push_tail(set_var); + if (new_var<>nil) then + begin + //goto_L1 = false; + set_var:=NewStore(new_var,NewCond(cFalse)); + pmerge.FInit.Push_tail(set_var); + end; - //goto_L1 = cond; - set_var:=pCode.NewStore(new_var,cond); - - if (goto_stmt.sNext.Adr.get_code_ptr=parent.pELabel.Adr.get_code_ptr) then + if (NextUsed(goto_stmt)=nil) then begin //empty body - //goto_L1 = cond; - parent.FEnded.Push_tail(set_var); + if (new_var<>nil) then + begin + //goto_L1 = cond; + set_var:=NewStore(new_var,cond); + parent.Push_tail(set_var); + end; + end else begin - neg_cond:=pCode.NewNot(cond); + if_merg:=NewBlock(btMerg); + if_stmt:=NewBlock(btCond); + if_merg.Push_tail(if_stmt); + + if_stmt.splice(goto_stmt.pNext,nil); + + InsertAfter(goto_stmt,if_merg); + + if (new_var<>nil) then + begin + //goto_L1 = cond; + set_var:=NewStore(new_var,cond); + if_merg.FInit.Push_tail(set_var); + end; + + neg_cond:=NewNot(cond); + if_merg.FInit.Push_tail(neg_cond); - if_stmt:=NewBlock; - if_stmt.pBLabel:=goto_stmt.sNext; - if_stmt.pELabel:=parent.pELabel; if_stmt.pCond:=neg_cond; - if_stmt.bType:=btCond; - if_stmt.MoveFromByRange(parent,if_stmt.beg_adr,if_stmt.end_adr); - if_merg:=NewBlock; - if_merg.pBLabel:=if_stmt.pBLabel; - if_merg.pELabel:=if_stmt.pELabel; - if_merg.bType:=btMerg; - if_merg.Push_back(if_stmt); - - if_merg.FBefore.Push_tail(neg_cond); - - //goto_L1 = cond; - if_merg.FBefore.Push_tail(set_var); - - prev:=parent.FindPrev(if_merg.beg_adr); - parent.Insert_after(prev,if_merg); - - //update labels - UpdateUp(if_stmt); + // end; - new_cond:=pCode.NewLoad(new_var); - pmerge.FAfter.Push_tail(new_cond); + // + FreeGoto(goto_stmt); + // - new_goto:=pCode.NewGoto(parent.pELabel,parent.pELabel,new_cond); + if (new_var=nil) then + begin + if IsUnconditional(Cond) then + begin + new_var:=Cond; + end else + begin + new_var:=NewCond(cTrue); + end; + end; + + new_goto:=NewGoto(new_var,label_stmt); + InsertAfter(pmerge,new_goto); + + Result:=new_goto; +end; + +{ + .... + if (expr) + { + stmt_1; + .... + goto L1; + } + stmt_2; + { + .... + L1: + .... + } + stmt_n; +} +//--> +{ + .... + if (expr) + { + stmt_1; + .... + } else { + stmt_2; + goto L1; + } + + { + .... + L1: + .... + } + stmt_n; +} + +function TsrCFGParser2.MoveOutwardElse(goto_stmt:TsrSourceGoto):TsrSourceGoto; +var + label_stmt:TsrSourceLabel; + pmerge :TsrSourceBlock; + cond :TsrStatement; + new_goto :TsrSourceGoto; + if_stmt :TsrSourceBlock; + if_else :TsrSourceBlock; +begin + label_stmt:=goto_stmt.pLabel; + + if_stmt:=goto_stmt.pParent; + pmerge:=if_stmt.pParent; + Assert(pmerge<>nil); + Assert(pmerge.bType=btMerg); + + cond:=goto_stmt.pCond; + Assert(IsUnconditional(cond)); + + if_else:=NewBlock(btElse); + if_else.pIf :=if_stmt; + if_stmt.pElse:=if_else; + pmerge.InsertAfter(if_stmt,if_else); + + if_else.splice(pmerge.pNext,label_stmt); + + // + FreeGoto(goto_stmt); + // + + goto_stmt:=TsrSourceGoto(if_else.Last); + + if (goto_stmt<>nil) then + if (goto_stmt.ntype=TsrSourceGoto) then + if IsUnconditional(goto_stmt.pCond) then + begin + Exit(goto_stmt); + end; + + new_goto:=NewGoto(cond,label_stmt); + if_else.Push_tail(new_goto); Result:=new_goto; end; @@ -2092,7 +1645,9 @@ end; do { stmt_1; .... - if (cond) goto L1; + if (expr) { + if (cond) goto L1; + } .... stmt_i; } while (expr) @@ -2107,15 +1662,14 @@ end; do { stmt_1; .... - goto_L1 = cond; - if (!cond) - { - stmt_2; - .... - stmt_i; - .... - break; + if (expr) { + if (cond) { + goto_L1 = true; + break; + } } + .... + stmt_i; } while (expr) if (goto_L1) goto L1; .... @@ -2123,80 +1677,162 @@ end; stmt_n; } -function TsrCFGParser.MoveOutwardLoop(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; +function TsrCFGParser2.MoveOutwardLoop(goto_stmt:TsrSourceGoto):TsrSourceGoto; var - parent :TsrCFGBlock; - prev :TsrCFGBlock; - new_var :TsrStatement; - set_var :TsrStatement; - cond :TsrStatement; - neg_cond :TsrStatement; - new_cond :TsrStatement; - new_break:TsrStatement; - new_goto :TsrStatement; - if_stmt :TsrCFGBlock; - if_merg :TsrCFGBlock; + label_stmt :TsrSourceLabel; + loop_parent:TsrSourceBlock; + cond :TsrStatement; + new_var :TsrStatement; + set_var :TsrStatement; + new_goto :TsrSourceGoto; + if_stmt :TsrSourceBlock; + if_merg :TsrSourceBlock; begin - parent:=BlockOf(goto_stmt.sLabel); + label_stmt:=goto_stmt.pLabel; - cond:=goto_stmt.pSrc; + loop_parent:=FindUpLoop(goto_stmt.pParent); - new_var:=pCode.NewVar; + cond:=goto_stmt.pCond; - //goto_L1 = false; - set_var:=pCode.NewStore(new_var,pCode.NewCond(cFalse)); - parent.FBefore.Push_tail(set_var); - - //goto_L1 = cond; - set_var:=pCode.NewStore(new_var,cond); - - if (goto_stmt.sNext.Adr.get_code_ptr=parent.pELabel.Adr.get_code_ptr) then + if (NextUsedFlowUp(loop_parent)<>label_stmt) then begin - //empty body + new_var:=NewVar; - //goto_L1 = cond; - parent.FEnded.Push_tail(set_var); + //goto_L1 = false; + set_var:=NewStore(new_var,NewCond(cFalse)); + loop_parent.FInit.Push_tail(set_var); end else begin - neg_cond:=pCode.NewNot(cond); - - if_stmt:=NewBlock; - if_stmt.pBLabel:=goto_stmt.sNext; - if_stmt.pELabel:=parent.pELabel; - if_stmt.pCond:=neg_cond; - if_stmt.bType:=btCond; - if_stmt.MoveFromByRange(parent,if_stmt.beg_adr,if_stmt.end_adr); - - if_merg:=NewBlock; - if_merg.pBLabel:=if_stmt.pBLabel; - if_merg.pELabel:=if_stmt.pELabel; - if_merg.bType:=btMerg; - if_merg.Push_back(if_stmt); - - if_merg.FBefore.Push_tail(neg_cond); - - //goto_L1 = cond; - if_merg.FBefore.Push_tail(set_var); - - prev:=parent.FindPrev(if_merg.beg_adr); - parent.Insert_after(prev,if_merg); - - //update labels - UpdateUp(if_stmt); + //simplification + new_var:=nil; end; - //break; - new_break:=pCode.NewBreak(parent.pELabel); - parent.FEnded.Push_tail(new_break); + //Unconditional + if IsUnconditional(cond) then + begin + if (new_var<>nil) then + begin + //goto_L1 = true; + set_var:=NewStore(new_var,NewCond(cTrue)); + InsertBefore(goto_stmt,set_var); + end; - new_cond:=pCode.NewLoad(new_var); - parent.FAfter.Push_tail(new_cond); + //break; + InsertBefore(goto_stmt,NewBreak); + end else + begin + //if (cond) { + if_merg:=NewBlock(btMerg); + if_stmt:=NewBlock(btCond); + if_merg.Push_tail(if_stmt); + InsertBefore(goto_stmt,if_merg); - new_goto:=pCode.NewGoto(parent.pELabel,parent.pELabel,new_cond); + if_stmt.pCond:=cond; + + if (new_var<>nil) then + begin + //goto_L1 = true; + set_var:=NewStore(new_var,NewCond(cTrue)); + if_stmt.Push_tail(set_var); + end; + + //break; + if_stmt.Push_tail(NewBreak); + end; + + // + FreeGoto(goto_stmt); + // + + if (new_var=nil) then + begin + if IsUnconditional(Cond) then + begin + new_var:=Cond; + end else + begin + new_var:=NewCond(cTrue); + end; + end; + + new_goto:=NewGoto(new_var,label_stmt); + InsertAfter(loop_parent,new_goto); Result:=new_goto; end; +function SanitizeNoBreaks(node_first,node_last:TsrSourceNode):Boolean; +var + node,next:TsrSourceNode; +begin + Result:=True; + node:=node_first; + + while (node<>nil) and (node<>node_last) do + begin + + if (node.ntype=TsrStatement) then + begin + if (TsrStatement(node).sType=sBreak) then + begin + Exit(False); + end; + end; + + next:=node.First; //down + + if (next<>nil) then + if (TsrSourceBlock(node).bType=btLoop) then + begin + next:=nil; + end; + + if (next=nil) then + begin + repeat //up + next:=node.pNext; + node:=node.pParent; + until (node=nil) or (next<>nil) or (node=node_last); + end; + + node:=next; + end; +end; + +{ + if (expr) { + if (cond) goto L1; + } + ... + L1: + ... +} + +function TsrCFGParser2.MoveOutwardSwitch(goto_stmt:TsrSourceGoto):TsrSourceGoto; +var + label_stmt :TsrSourceLabel; + nested_stmt:TsrSourceNode; + loop_stmt :TsrSourceBlock; +begin + label_stmt :=goto_stmt.pLabel; + + nested_stmt:=SiblingFromNephew(label_stmt,goto_stmt,True); + + if not SanitizeNoBreaks(nested_stmt, label_stmt) then + begin + Assert(false,'SanitizeNoBreaks:MoveOutwardSwitch'); + end; + + loop_stmt:=NewBlock(btLoop); + loop_stmt.pCond:=NewCond(cFalse); + + loop_stmt.splice(nested_stmt, label_stmt); + + InsertBefore(label_stmt,loop_stmt); + + Result:=MoveOutwardLoop(goto_stmt); +end; + { ... if (cond) goto L1; stmt_1; @@ -2238,7 +1874,7 @@ end; ... stmt_i; } - if (!cond && expr) { + if (!goto_L1 && expr) { ... stmt_j; ... @@ -2263,9 +1899,7 @@ end; } do { - goto_L2 = goto_L1; - goto_L1 = false; - if (goto_L2) goto L1; + if (goto_L1) goto L1; stmt_j; ... L1: @@ -2274,75 +1908,92 @@ end; } while (expr) } -function TsrCFGParser.MoveInward(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; +function TsrCFGParser2.MoveInward(goto_stmt:TsrSourceGoto):TsrSourceGoto; var - parent :TsrCFGBlock; - prev :TsrCFGBlock; - nested_stmt:TsrCFGBlock; - nested_real:TsrCFGBlock; - new_var :TsrStatement; - set_var :TsrStatement; + label_stmt :TsrSourceLabel; + nested_stmt:TsrSourceBlock; + nested_real:TsrSourceBlock; + new_copy :TsrStatement; cond :TsrStatement; neg_cond :TsrStatement; new_op :TsrStatement; - new_goto :TsrStatement; - if_stmt :TsrCFGBlock; - if_merg :TsrCFGBlock; + new_goto :TsrSourceGoto; + if_stmt :TsrSourceBlock; + if_merg :TsrSourceBlock; begin - parent:=BlockOf(goto_stmt.sLabel); + label_stmt:=goto_stmt.pLabel; - nested_stmt:=SiblingFromNephew(goto_stmt.sLabel,label_stmt); - nested_real:=nested_stmt.pReal; + nested_stmt:=TsrSourceBlock(SiblingFromNephew(goto_stmt,label_stmt,False)); + Assert(nested_stmt.ntype=TsrSourceBlock); - new_var:=pCode.NewVar; - cond :=goto_stmt.pSrc; + nested_real:=nested_stmt; + if (nested_stmt.pParent<>nil) then + if (nested_stmt.pParent.bType=btMerg) then + begin + nested_real:=nested_stmt.pParent; + end; - //goto_L1 = cond; - set_var:=pCode.NewStore(new_var,cond); + cond:=goto_stmt.pCond; - if (goto_stmt.sNext.Adr.get_code_ptr=parent.pELabel.Adr.get_code_ptr) then + if (NextUsed(goto_stmt)=nested_real) then begin //empty body - nested_real.FBefore.Push_tail(set_var); + //goto_L1 = cond; + if (cond.sType<>sCond) then + begin + new_copy:=cond; + end else + begin + new_copy:=NewCopy(cond); + nested_real.FInit.Push_tail(new_copy); + end; + end else begin - neg_cond:=pCode.NewNot(cond); + if_merg:=NewBlock(btMerg); + if_stmt:=NewBlock(btCond); + if_merg.Push_tail(if_stmt); + + if_stmt.splice(goto_stmt.pNext,nested_real); + + InsertAfter(goto_stmt,if_merg); + + //goto_L1 = cond; + if (cond.sType<>sCond) then + begin + new_copy:=cond; + end else + begin + new_copy:=NewCopy(cond); + if_merg.FInit.Push_tail(new_copy); + end; + + neg_cond:=NewNot(cond); + if_merg.FInit.Push_tail(neg_cond); - if_stmt:=NewBlock; - if_stmt.pBLabel:=goto_stmt.sNext; - if_stmt.pELabel:=nested_stmt.pBLabel; if_stmt.pCond:=neg_cond; - if_stmt.bType:=btCond; - if_stmt.MoveFromByRange(parent,if_stmt.beg_adr,if_stmt.end_adr); - if_merg:=NewBlock; - if_merg.pBLabel:=if_stmt.pBLabel; - if_merg.pELabel:=if_stmt.pELabel; - if_merg.bType:=btMerg; - if_merg.Push_back(if_stmt); - - if_merg.FBefore.Push_tail(set_var); - if_merg.FBefore.Push_tail(neg_cond); - - prev:=parent.FindPrev(if_merg.beg_adr); - parent.Insert_after(prev,if_merg); - - //update labels - UpdateUp(if_stmt); + // end; - case nested_stmt.bType of + case TsrSourceBlock(nested_stmt).bType of btCond: begin - //load before - cond:=pCode.NewLoad(new_var); - //(goto_L1 || expr) Assert(nested_stmt.pCond<>nil); - new_op:=pCode.NewOr(nested_stmt.pCond,cond); - // - nested_real.FBefore.Push_tail(cond); - nested_real.FBefore.Push_tail(new_op); + //load before + + if IsUnreachable(nested_stmt.pCond) then + begin + new_op:=new_copy; + end else + begin + //(goto_L1 || expr) + new_op:=NewOr(new_copy,nested_stmt.pCond); + // + nested_real.FInit.Push_tail(new_op); + end; + // Update nested if condition nested_stmt.pCond:=new_op; end; @@ -2350,28 +2001,29 @@ begin begin if_stmt:=nested_stmt.pIf; Assert(if_stmt<>nil); - //load before - cond:=pCode.NewLoad(new_var); - //!cond - neg_cond:=pCode.NewNot(cond); - //(!cond && expr) Assert(nested_stmt.pCond<>nil); - new_op:=pCode.NewAnd(nested_stmt.pCond,cond); - // - nested_real.FBefore.Push_tail(cond); - nested_real.FBefore.Push_tail(neg_cond); - nested_real.FBefore.Push_tail(new_op); + //load before + + if IsUnreachable(nested_stmt.pCond) then + begin + new_op:=nested_stmt.pCond; + end else + begin + //!goto_L1 + neg_cond:=NewNot(new_copy); + nested_real.FInit.Push_tail(neg_cond); + //(!goto_L1 && expr) + new_op:=NewAnd(neg_cond,nested_stmt.pCond); + // + nested_real.FInit.Push_tail(new_op); + end; + // Update nested if condition nested_stmt.pCond:=new_op; end; btLoop: begin - //goto_L2 = goto_L1; - cond:=pCode.NewLoad(new_var); - nested_stmt.FStart.Push_tail(cond); - //goto_L1 = false; - set_var:=pCode.NewStore(new_var,pCode.NewCond(cFalse)); - nested_stmt.FStart.Push_tail(set_var); + // end; else begin @@ -2380,7 +2032,12 @@ begin end; end; - new_goto:=pCode.NewGoto(nested_stmt.pBLabel,nested_stmt.pBLabel,cond); + // + FreeGoto(goto_stmt); + // + + new_goto:=NewGoto(new_copy,label_stmt); + nested_stmt.Push_head(new_goto); Result:=new_goto; end; @@ -2413,55 +2070,534 @@ end; stmt_n; } -function TsrCFGParser.Lift(goto_stmt:TsrStatement;label_stmt:TsrLabel):TsrStatement; +function TsrCFGParser2.Lift(goto_stmt:TsrSourceGoto):TsrSourceGoto; var - parent :TsrCFGBlock; - prev :TsrCFGBlock; - nested_stmt:TsrCFGBlock; - new_var :TsrStatement; + label_stmt :TsrSourceLabel; + nested_stmt:TsrSourceNode; + loop_stmt :TsrSourceBlock; cond :TsrStatement; - new_goto :TsrStatement; + new_var :TsrStatement; set_var :TsrStatement; - loop_stmt :TsrCFGBlock; + new_goto :TsrSourceGoto; begin - parent:=BlockOf(goto_stmt.sLabel); + label_stmt:=goto_stmt.pLabel; - nested_stmt:=SiblingFromNephew(goto_stmt.sLabel,label_stmt); + nested_stmt:=SiblingFromNephew(goto_stmt,label_stmt,True); - new_var:=pCode.NewVar; - cond :=goto_stmt.pSrc; + if not SanitizeNoBreaks(nested_stmt, goto_stmt) then + begin + Assert(false,'SanitizeNoBreaks:Lift'); + end; + + loop_stmt:=NewBlock(btLoop); + + loop_stmt.splice(nested_stmt, goto_stmt); + + InsertBefore(goto_stmt,loop_stmt); + + new_var:=NewVar; + cond :=goto_stmt.pCond; - loop_stmt:=NewBlock; - loop_stmt.pBLabel:=nested_stmt.pBLabel; - loop_stmt.pELabel:=goto_stmt.sLabel; loop_stmt.pCond:=cond; - loop_stmt.bType:=btLoop; - loop_stmt.MoveFromByRange(parent,loop_stmt.beg_adr,loop_stmt.end_adr); - //TODO: SanitizeNoBreaks(loop_stmt); - - prev:=parent.FindPrev(loop_stmt.beg_adr); - parent.Insert_after(prev,loop_stmt); - - //update labels - UpdateUp(loop_stmt); - - cond :=pCode.NewLoad(new_var); - loop_stmt.FStart.Push_tail(cond); - - new_goto:=pCode.NewGoto(label_stmt,label_stmt,cond); // goto_L1 = cond; - cond :=goto_stmt.pSrc; - set_var:=pCode.NewStore(new_var,cond); - loop_stmt.FEnded.Push_tail(set_var); + set_var:=NewStore(new_var,cond); + loop_stmt.Push_tail(set_var); //goto_L1 = false; - set_var:=pCode.NewStore(new_var,pCode.NewCond(cFalse)); - loop_stmt.FBefore.Push_tail(set_var); + set_var:=NewStore(new_var,NewCond(cFalse)); + loop_stmt.FInit.Push_tail(set_var); + + // + FreeGoto(goto_stmt); + // + + new_goto:=NewGoto(new_var,label_stmt); + loop_stmt.Push_head(new_goto); Result:=new_goto; end; +/// + +type + TsrExecFlow=( + efNone, + efFalse, + efTrue + ); + +function is_cmp_x(i:Integer):Boolean; inline; +begin + case i of + V_CMPX_F_F32 ..V_CMPX_T_F32, + V_CMPX_F_F64 ..V_CMPX_T_F64, + V_CMPSX_F_F32..V_CMPSX_T_F32, + V_CMPSX_F_F64..V_CMPSX_T_F64, + V_CMPX_F_I32 ..V_CMPX_T_I32, + V_CMPX_F_I64 ..V_CMPX_T_I64, + V_CMPX_F_U32 ..V_CMPX_T_U32, + V_CMPX_F_U64 ..V_CMPX_T_U64, + + V_CMPX_CLASS_F32, + V_CMPX_CLASS_F64: + Result:=True; + + else + Result:=False; + end; +end; + +function GetExecFlow(var FSPI:TSPI):TsrExecFlow; +begin + Case FSPI.CMD.EN of + W_VOP1 : + Case FSPI.VOP1.OP of + V_NOP :Result:=efNone; + V_READFIRSTLANE_B32:Result:=efFalse; + else + Result:=efTrue; + end; + //-> The result is given in a scalar register, so it needs to be processed separately + W_VOPC :Result:=efFalse; + W_VOP3 : + Case FSPI.VOP3a.OP of + //-> The result is given in a scalar register, so it needs to be processed separately + 0..255 :Result:=efFalse; //VOP3c + 384+V_NOP :Result:=efNone; + 256+V_READLANE_B32 :Result:=efFalse; + 256+V_WRITELANE_B32 :Result:=efFalse; + 384+V_READFIRSTLANE_B32:Result:=efFalse; + else + Result:=efTrue; + end; + W_DS : + Case FSPI.DS.OP of + DS_NOP:Result:=efNone; + else + Result:=efTrue; + end; + W_MUBUF :Result:=efTrue; + W_MTBUF :Result:=efTrue; + W_EXP :Result:=efFalse; //-> processed separately + W_MIMG :Result:=efTrue; + W_VOP2 : + Case FSPI.VOP2.OP of + V_READLANE_B32 :Result:=efFalse; + V_WRITELANE_B32:Result:=efFalse; + else + Result:=efTrue; + end; + W_SOPP : + Case FSPI.SOPP.OP of + S_NOP :Result:=efNone; + S_WAITCNT:Result:=efNone; + else + Result:=efFalse; + end; + else + Result:=efFalse; + end; +end; + +function GetExecFlow(node:TsrSourceNode):TsrExecFlow; +begin + if (node.ntype=TsrSourceInstruction) then + begin + Result:=GetExecFlow(TsrSourceInstruction(node).FSPI); + end else + if (node.ntype=TsrSourceNode) then + begin + Result:=efNone; + end else + if (node.ntype=TsrSourceLabel) then + begin + Result:=efNone; + end else + begin + Result:=efFalse; + end; +end; + +procedure TsrCFGParser2.ExecPass; +var + node :TsrSourceNode; + next :TsrSourceNode; + parent :TsrSourceNode; + exec :TsrSourceBlock; + if_stmt:TsrSourceBlock; + if_merg:TsrSourceBlock; +begin + node:=pCode.FTop.First; + exec:=nil; + + while (node<>nil) do + begin + parent:=node.pParent; + next:=flow_down_next_up(node); + + case GetExecFlow(node) of + efNone: + begin + if (exec<>nil) then + begin + exec.splice(node,node.pNext); + end; + end; + efFalse: + begin + exec:=nil; + end; + efTrue: + begin + if (exec=nil) then + begin + if_merg:=NewBlock(btMerg); + if_stmt:=NewBlock(btCond); + if_stmt.pCond:=NewCond(cTidnz); + if_merg.Push_tail(if_stmt); + InsertBefore(node,if_merg); + exec:=if_stmt; + end; + exec.splice(node,node.pNext); + end; + end; + + if (next<>nil) then + if (parent<>next.pParent) then + begin + exec:=nil; + end; + + node:=next; + end; + +end; + +/// + +function Vertical(node:TsrSourceNode):RawByteString; +var + i:Integer; + tmp:TsrSourceBlock; +begin + i:=node.get_level; + // + Result:=''; + SetLength(Result,i); + + tmp:=node.pParent; + While (tmp<>nil) do + begin + if isReal(tmp.bType) then + begin + if (tmp.bType=btLoop) then + begin + Result[i]:='!'; + end else + begin + Result[i]:='|'; + end; + Dec(i); + end; + tmp:=tmp.pParent; + end; + + // + if (i<>0) and (node.ntype=TsrSourceBlock) then + begin + Result[i]:='+'; + end; +end; + +function get_str_prefix(count:Byte;node:TsrSourceNode):RawByteString; +begin + if (node.ntype=TsrSourceInstruction) then + begin + Result:=' '+HexStr(TsrSourceInstruction(node).b_adr.Offset,count)+Vertical(node); + end else + if (node.ntype=TsrSourceLabel) then + begin + Result:=' '+Space(count)+Space(node.get_level); + end else + begin + Result:=' '+Space(count)+Vertical(node); + end; +end; + +function get_str_label(count:Byte;node:TsrSourceLabel):RawByteString; +begin + Result:='_label_'+HexStr(node.b_adr.Offset,count); +end; + +const + CondStr:array[TsrCondition] of RawByteString=( + 'None', + 'False', + 'True', + 'Scc0', + 'Scc1', + 'Vccz', + 'Vccnz', + 'Execz', + 'Execnz', + 'Tidz', + 'Tidnz' + ); + +function GetCondStr(node:TsrStatement):RawByteString; +begin + Result:=''; + while (node<>nil) do + begin + case node.sType of + sCond :begin Result:=Result+CondStr[node.u.cond]; Break; end; + sCopy :begin Result:=Result+'C'+IntToStr(node.u.id); Break; end; + sVar :begin Result:=Result+'U'+IntToStr(node.u.id); Break; end; + //sStore:; + //sBreak:; + sNot :begin Result:='!'+Result; node:=node.pSrc; end; + sOr :begin Result:=Result+'('+GetCondStr(node.pSrc)+' || '+GetCondStr(node.pDst)+')'; Break; end; + sAnd :begin Result:=Result+'('+GetCondStr(node.pSrc)+' && '+GetCondStr(node.pDst)+')'; Break; end; + else Break; + end; + end; +end; + +function GetStatmentStr(node:TsrStatement):RawByteString; +begin + Result:=''; + case node.sType of + //sCond :' + sCopy :Result:=GetCondStr(node.pDst)+' = '+GetCondStr(node.pSrc)+';'; + //sVar :' + sStore:Result:=GetCondStr(node.pDst)+' = '+GetCondStr(node.pSrc)+';'; + sBreak:Result:='break;'; + //sNot :; + //sOr :; + //sAnd :; + else; + end; +end; + +procedure PrintStatmentList(const prefix:RawByteString;List:TsrSourceNodeList); +var + node:TsrStatement; + s:RawByteString; +begin + node:=TsrStatement(List.pHead); + while (node<>nil) do + begin + case node.sType of + sCond:; //skip + sNot :; //skip + sOr :; //skip + sAnd :; //skip + else + begin + s:=GetStatmentStr(node); + if (s<>'') then + begin + Writeln(prefix+s); + end; + end; + end; + // + node:=TsrStatement(node.pNext); + end; +end; + +function get_str_goto(count:Byte;node:TsrSourceGoto):RawByteString; +begin + Result:='if ('+GetCondStr(node.pCond)+') goto '+get_str_label(count,node.pLabel)+'; //#'+IntToStr(node.order); +end; + +function get_down_str(node:TsrSourceBlock):RawByteString; +begin + Result:=''; + case node.bType of + btCond:Result:='if ('+GetCondStr(node.pCond)+') { //#'+IntToStr(node.order); + btLoop:Result:='do { //#'+IntToStr(node.order); + else; + end; +end; + +function get_up_str(node:TsrSourceBlock):RawByteString; +begin + Result:=''; + case node.bType of + btCond:begin + if (node.pElse=nil) then + begin + Result:='}; //if #'+IntToStr(node.order);; + end else + begin + Result:='} else { //#'+IntToStr(node.order); + end; + end; + btElse:Result:='}; //else #'+IntToStr(node.order); + btLoop:begin + Result:='} while ('+GetCondStr(node.pCond)+'); //#'+IntToStr(node.order); + end; + else; + end; +end; + +procedure TsrCFGParser2.Print; +var + count:Byte; + prefix,s:RawByteString; + node,next:TsrSourceNode; + +begin + count:=BsrQWord(pCode.Size); + if (count=$FF) then count:=0; + count:=(count+4) div 4; + + node:=pCode.FTop.First; + + while (node<>nil) do + begin + + prefix:=get_str_prefix(count,node); + + if (node.ntype=TsrSourceInstruction) then + begin + Writeln(prefix+get_str_spi(TsrSourceInstruction(node).FSPI)); + end else + if (node.ntype=TsrSourceLabel) then + begin + Writeln(prefix+get_str_label(count,TsrSourceLabel(node))+': //#'+IntToStr(node.order)); + end else + if (node.ntype=TsrSourceGoto) then + begin + Writeln(prefix+get_str_goto(count,TsrSourceGoto(node))); + end else + if (node.ntype=TsrSourceBlock) then + begin + // + PrintStatmentList(prefix,TsrSourceBlock(node).FInit); + //down + s:=get_down_str(TsrSourceBlock(node)); + if (s<>'') then + begin + Writeln(prefix+s); + end; + //up + if (node.First=nil) then + begin + s:=get_up_str(TsrSourceBlock(node)); + if (s<>'') then + begin + Writeln(prefix+s); + end; + end; + // + end else + if (node.ntype=TsrStatement) then + begin + s:=GetStatmentStr(TsrStatement(node)); + if (s<>'') then + begin + Writeln(prefix+s); + end; + end else + begin + //Writeln(prefix+node.ntype.ClassName); + end; + + next:=node.First; //down + if (next=nil) then + begin + repeat //up + next:=node.pNext; + node:=node.pParent; + // + if (node<>nil) and (next=nil) then + begin + s:=get_up_str(TsrSourceBlock(node)); + if (s<>'') then + begin + prefix:=get_str_prefix(count,node); + Writeln(prefix+s); + end; + end else + begin + Break; + end; + // + until false; + end; + + node:=next; + end; + +end; + +/// + +function parse_code_cfg2(var pCode:TsrCodeRegion;bType:TsrBlockType;Body,Dmem:Pointer;FEmit:TCustomEmit):Integer; +var + parser:TsrCFGParser2; +begin + pCode:=FEmit.specialize New; + // + parser:=Default(TsrCFGParser2); + parser.FEmit:=FEmit; + parser.pCode:=pCode; + // + pCode.FEmit:=FEmit; + pCode.Body :=Body; + pCode.Dmem :=Dmem; + pCode.FTop :=parser.NewBlock(bType); + + Result:=parser.Parse; + if (Result>1) then Exit; + + parser.EmitLabels; + parser.GotoPass; + parser.InitMovePass; + parser.ExecPass; + + if PsrConfig(pCode.FEmit.GetConfig)^.PrintCfg then + begin + parser.Print; + end; + + Result:=0; +end; + +// + +function TsrCodeRegion.FindByPtr(base:Pointer):TsrSourceNode; +var + node:TsrSourceNode; +begin + Result:=nil; + node:=FTop.First; + + while (node<>nil) do + begin + + if node.InheritsFrom(TsrSourceAdr) then + with TsrSourceAdr(node) do + begin + if (b_adr.get_code_ptr=base) then + begin + Exit(node); + end else + if (e_adr.get_code_ptr=base) then + begin + Exit(node); + end; + end; + + node:=flow_down_next_up(node); + end; + +end; + +/// end. diff --git a/spirv/srCacheOp.pas b/spirv/srCacheOp.pas index f76ba0e4..8a505b8f 100644 --- a/spirv/srCacheOp.pas +++ b/spirv/srCacheOp.pas @@ -7,7 +7,7 @@ interface uses ginodes, srNode, - srCFGLabel, + srCFGParser, srType, srReg, srOp; @@ -51,7 +51,7 @@ function _up_to_real(t:TsrOpBlock):TsrOpBlock; begin repeat if not t.IsType(ntOpBlock) then Break; - if IsReal(t.Block.bType) then Break; + if IsReal(t.bType) then Break; t:=t.Parent; until false; Result:=t; diff --git a/spirv/srConfig.pas b/spirv/srConfig.pas index 53173752..449ef89e 100644 --- a/spirv/srConfig.pas +++ b/spirv/srConfig.pas @@ -9,19 +9,20 @@ type PsrConfig=^TsrConfig; TsrConfig=packed object - PrintAsm:Boolean; - PrintCfg:Boolean; - UseVertexInput:Boolean; //True - UseTexelBuffer:Boolean; - UseOutput16:Boolean; + PrintAsm :Boolean; + PrintCfg :Boolean; + UseVertexInput :Boolean; //True + UseTexelBuffer :Boolean; + UseOutput16 :Boolean; UseOnlyUserdataPushConst:Boolean; + UseExtendedEXECMask :Boolean; // DescriptorSet:DWORD; //0 // - SpvVersion:PtrUint; // $10100 - maxUniformBufferRange:PtrUint; // $FFFF - PushConstantsOffset:PtrUint; // 0 - maxPushConstantsSize:PtrUint; // 128 + SpvVersion :PtrUint; // $10100 + maxUniformBufferRange :PtrUint; // $FFFF + PushConstantsOffset :PtrUint; // 0 + maxPushConstantsSize :PtrUint; // 128 minStorageBufferOffsetAlignment:PtrUint; // $10 minUniformBufferOffsetAlignment:PtrUint; // $100 // diff --git a/spirv/srConst.pas b/spirv/srConst.pas index 36752457..77bfb932 100644 --- a/spirv/srConst.pas +++ b/spirv/srConst.pas @@ -6,6 +6,7 @@ interface uses sysutils, + math, spirv, ginodes, srNode, @@ -818,6 +819,7 @@ end; Function TryTruncInt64(c:Single;var i:int64):Boolean; begin + if IsNan(c) or IsInfinite(c) then Exit(False); Result:=(c>=Low(int64)) and (c<=High(int64)); if Result then begin diff --git a/spirv/srFlow.pas b/spirv/srFlow.pas index 04f43878..71c4b410 100644 --- a/spirv/srFlow.pas +++ b/spirv/srFlow.pas @@ -9,7 +9,6 @@ uses ps4_pssl, spirv, srNode, - srCFGLabel, srCFGParser, srCFGCursor, srPrivate, @@ -31,29 +30,27 @@ type // Procedure InitFlow; procedure mark_end_of(mark:TsrVolMark); - Procedure PushBlockOp(pLine:TspirvOp;pChild:TsrOpBlock;pLBlock:TsrCFGBlock=nil); + Procedure PushBlockOp(pLine:TspirvOp;pChild:TsrOpBlock;iCursor:TsrCursor); function PopBlockOp:Boolean; function ConvertCond(cond:TsrCondition;pLine:TspirvOp):TConvertResult; function ConvertStatment(node:TsrStatement;pLine:TspirvOp):TConvertResult; - procedure emit_break(b_adr:TSrcAdr;pCurr:TsrOpBlock); + function LoadStatment(C:TConvertResult):TConvertResult; + procedure emit_break(pCurr:TsrOpBlock); procedure EmitStatment(node:TsrStatement); - procedure EmitStatmentList(List:TsrStatementList); - function NewMerge(pLBlock:TsrCFGBlock):TsrOpBlock; - function NewIf (pOpMerge:TsrOpBlock;pLBlock:TsrCFGBlock;src:TsrRegNode):TsrOpBlock; - function NewElse (pOpMerge:TsrOpBlock;pLBlock:TsrCFGBlock):TsrOpBlock; - function NewLoop (pLBlock:TsrCFGBlock):TsrOpBlock; - function CheckBlockBeg:Boolean; - function CheckBlockEnd:Boolean; + function NewMerge(iCursor:TsrCursor):TsrOpBlock; + function NewIf (pOpMerge:TsrOpBlock;iCursor:TsrCursor;src:TsrRegNode):TsrOpBlock; + function NewElse (pOpMerge:TsrOpBlock;iCursor:TsrCursor):TsrOpBlock; + function NewLoop (iCursor:TsrCursor):TsrOpBlock; + function BlockBeg:Boolean; + function BlockEnd:Boolean; // function get_code_ptr:Pointer; procedure set_code_ptr(base:Pointer;bType:TsrBlockType); function fetch_cursor_ptr(base:Pointer;bType:TsrBlockType):TsrCursor; - function IsFinalize:Boolean; - function FindLabel(Adr:TSrcAdr):TsrLabel; + //function IsFinalize:Boolean; // procedure Finalize; // - function NextParse:Byte; function ParseStage(base:Pointer):Integer; end; @@ -64,8 +61,8 @@ begin CodeHeap.Init(Self); // InitBlock:=AllocBlockOp; - InitBlock.SetInfo(btOther,Cursor.Adr,Cursor.Adr); - PushBlockOp(line,InitBlock); + InitBlock.SetInfo(btOther); + PushBlockOp(line,InitBlock,Default(TsrCursor)); Main.PopBlock; end; @@ -86,25 +83,27 @@ begin node.FVolMark:=mark; //exit if real block - if IsReal(node.Block.bType) then Exit; + if IsReal(node.bType) then Exit; node:=node.Parent; end; end; -Procedure TEmitFlow.PushBlockOp(pLine:TspirvOp;pChild:TsrOpBlock;pLBlock:TsrCFGBlock=nil); +Procedure TEmitFlow.PushBlockOp(pLine:TspirvOp;pChild:TsrOpBlock;iCursor:TsrCursor); begin - pChild.FCursor:=Cursor; //prev - pChild.FLBlock:=pLBlock; + pChild.FCursor:=iCursor; //prev + //pChild.FLBlock:=pLBlock; InsSpirvOp(pLine,pChild); Main.PushBlock(pChild); + { if (pLBlock<>nil) then begin Cursor.pBlock:=pLBlock; //push end; + } end; function TEmitFlow.PopBlockOp:Boolean; @@ -113,7 +112,7 @@ var pOpChild:TsrOpBlock; pBegOp,pEndOp,pMrgOp:TspirvOp; - procedure pop_merge; + procedure pop_merge(pOpBlock:TsrOpBlock); begin Assert(pMrgOp<>nil); @@ -125,17 +124,17 @@ var AddSpirvOp(line,pMrgOp); //end end; - procedure pop_merge_after; + procedure pop_merge_after(pOpBlock:TsrOpBlock); begin // end; - procedure pop_cond; + procedure pop_cond(pOpBlock:TsrOpBlock); begin // end; - procedure pop_cond_after; + procedure pop_cond_after(pOpBlock:TsrOpBlock); begin if (pOpBlock.pElse<>nil) then //have else begin @@ -162,12 +161,12 @@ var end; end; - procedure pop_else; + procedure pop_else(pOpBlock:TsrOpBlock); begin // end; - procedure pop_else_after; + procedure pop_else_after(pOpBlock:TsrOpBlock); var pIf:TsrOpBlock; begin @@ -194,10 +193,10 @@ var end; end; - procedure pop_loop; + procedure pop_loop(pOpBlock:TsrOpBlock); var pLine:TspirvOp; - pLBlock:TsrCFGBlock; + parent:TsrSourceBlock; src:TsrRegNode; begin //add OpLoopMerge continue @@ -206,92 +205,75 @@ var Assert(pEndOp<>nil); Assert(pMrgOp<>nil); - pLBlock:=pOpBlock.FLBlock; - Assert(pLBlock<>nil); + parent:=pOpBlock.FCursor.AsBlock; + Assert(parent<>nil); pLine:=line; //before close //if pOpBlock.Cond.FUseCont then //use continue - if (pLBlock.pCond<>nil) then - begin - //have post conditions - if not is_term_op(line) then - begin - OpBranch(line,pMrgOp); //LoopMerge - end; - end else - begin - //not post conditions - if not is_term_op(line) then - begin - OpBranch(line,pEndOp); //break - end; - end; - - AddSpirvOp(line,pMrgOp); //OpLoopMerge end - - pOpChild:=AllocBlockOp; - pOpChild.SetInfo(btOther,Cursor.Adr,Cursor.Adr); - PushBlockOp(line,pOpChild); - - if (pLBlock.pCond<>nil) then - begin - //have post conditions - src:=ConvertStatment(pLBlock.pCond,pLine).pNode; - Assert(src<>nil); - // - OpBranchCond(line,pBegOp,pEndOp,src); //True|False - end else - begin - //not post conditions - OpBranch(line,pBegOp); //continue - end; - - Main.PopBlock; - - AddSpirvOp(line,pEndOp); //end - - { - end else //dont used continue + if (parent.pCond<>nil) then begin - - { + //have post conditions if not is_term_op(line) then begin - AddSpirvOp(line,NewLabelOp(True)); //devide + OpBranch(line,pMrgOp); //LoopMerge end; - } + end else + begin + //not post conditions + if not is_term_op(line) then + begin + OpBranch(line,pEndOp); //break + end; + end; - AddSpirvOp(line,pMrgOp); //OpLoopMerge end + AddSpirvOp(line,pMrgOp); //OpLoopMerge end - pOpChild:=AllocBlockOp; - pOpChild.SetInfo(btOther,Cursor.Adr,Cursor.Adr); - PushBlockOp(line,pOpChild); - OpBranch(line,pEndOp); //break - Main.PopBlock; + pOpChild:=AllocBlockOp; + pOpChild.SetInfo(btOther); + PushBlockOp(line,pOpChild,Default(TsrCursor)); - AddSpirvOp(line,pEndOp); //end - } + if (parent.pCond<>nil) then + begin + //have post conditions + src:=LoadStatment(ConvertStatment(parent.pCond,pLine)).pNode; + Assert(src<>nil); + // + OpBranchCond(line,pBegOp,pEndOp,src); //True|False + end else + begin + //not post conditions + OpBranch(line,pBegOp); //continue + end; + Main.PopBlock; + + AddSpirvOp(line,pEndOp); //end end; - procedure pop_loop_after; - var - pLBlock:TsrCFGBlock; + Function IsUnreachable(cond:TsrStatement):Boolean; inline; + begin + Result:=(cond.sType=sCond) and (cond.u.cond=cFalse) + end; + + procedure pop_loop_after(pOpBlock:TsrOpBlock); + var + parent:TsrSourceBlock; begin if (pOpBlock.FVolMark<>vmNone) then begin - //restore original if inside endpgm/break/continue - PrivateList.build_volatile_reset(pOpBlock.Regs.orig); + //set next volatile state + PrivateList.build_volatile_reset(pOpBlock.Regs.next); end else begin //calc break volatile state PrivateList.build_volatile_break(pOpBlock.vctx,pOpBlock.Regs.orig,pOpBlock.Regs.prev,pOpBlock.Regs.next); - pLBlock:=pOpBlock.FLBlock; - if (pLBlock.pCond<>nil) then + parent:=pOpBlock.FCursor.AsBlock; + if (parent.pCond<>nil) then + if not IsUnreachable(parent.pCond) then begin //have post conditions PrivateList.build_volatile_conti(pOpBlock.vctx,pOpBlock.Regs.orig,pOpBlock.Regs.prev,pOpBlock.Regs.next); @@ -302,7 +284,7 @@ var end; end; - procedure pop_other; + procedure pop_other(pOpBlock:TsrOpBlock); begin //pMrgOp??? if (pEndOp<>nil) then @@ -322,91 +304,80 @@ begin pOpBlock:=Main.pBlock; if (pOpBlock=nil) then Exit; - if (pOpBlock.FLBlock<>nil) then - begin - EmitStatmentList(pOpBlock.FLBlock.FEnded); - end; - pBegOp:=pOpBlock.Labels.pBegOp; pEndOp:=pOpBlock.Labels.pEndOp; pMrgOp:=pOpBlock.Labels.pMrgOp; - Case pOpBlock.Block.bType of + Case pOpBlock.bType of btMerg: begin - pop_merge; + pop_merge(pOpBlock); end; btCond: begin - pop_cond; + pop_cond(pOpBlock); end; btElse: begin - pop_else; + pop_else(pOpBlock); end; btLoop: begin - pop_loop; + pop_loop(pOpBlock); end; else - pop_other; + pop_other(pOpBlock); end; //restore - Case pOpBlock.Block.bType of + Case pOpBlock.bType of btInline: begin - Assert(pOpBlock.FCursor.pBlock<>nil); + Assert(pOpBlock.FCursor.pCode<>nil); + Assert(pOpBlock.FCursor.pNode<>nil); Cursor:=pOpBlock.FCursor; end; btOther: begin - if (pOpBlock.FLBlock<>nil) then + if (pOpBlock.FCursor.pCode<>nil) then + if (pOpBlock.FCursor.pNode<>nil) then begin - Cursor.PopBlock; + Cursor:=pOpBlock.FCursor; end; end; else begin - Assert(pOpBlock.FCursor.pBlock<>nil); - //Cursor.pCode:=pOpBlock.FCursor.pCode; + Assert(pOpBlock.FCursor.pCode<>nil); + Assert(pOpBlock.FCursor.pNode<>nil); Cursor.PopBlock; end; end; Result:=Main.PopBlock; - Case pOpBlock.Block.bType of + Case pOpBlock.bType of btMerg: begin - pop_merge_after; + pop_merge_after(pOpBlock); end; btCond: begin - pop_cond_after; - //PrivateList.build_volatile_test; + pop_cond_after(pOpBlock); end; btElse: begin - pop_else_after; + pop_else_after(pOpBlock); end; btLoop: begin - pop_loop_after; - //PrivateList.build_volatile_test; + pop_loop_after(pOpBlock); end; else begin - //PrivateList.build_volatile_test; end; end; - if (pOpBlock.FLBlock<>nil) then - begin - EmitStatmentList(pOpBlock.FLBlock.FAfter); - end; - end; function Base64(b:Byte):Char; @@ -420,17 +391,20 @@ begin end; end; + function TEmitFlow.ConvertCond(cond:TsrCondition;pLine:TspirvOp):TConvertResult; begin case cond of cFalse :Result.pNode:=NewImm_b(False,pLine); cTrue :Result.pNode:=NewImm_b(True ,pLine); - cScc0 :Result.pNode:=fetch_scc; - cScc1 :Result.pNode:=fetch_scc; - cVccz :Result.pNode:=fetch_vccz ; //It means that lane_id=0 - cVccnz :Result.pNode:=fetch_vccz ; //It means that lane_id=0 - cExecz :Result.pNode:=fetch_execz; //It means that lane_id=0 - cExecnz:Result.pNode:=fetch_execz; //It means that lane_id=0 + cScc0 :Result.pNode:=fetch_scc; //It means that (scc == 0) + cScc1 :Result.pNode:=fetch_scc; //It means that (scc == 1) + cVccz :Result.pNode:=fetch_vccnz (@pLine); //It means that (vcc0 == 0) && (vcc1 == 0) + cVccnz :Result.pNode:=fetch_vccnz (@pLine); //It means that (vcc0 != 0) || (vcc1 != 0) + cExecz :Result.pNode:=fetch_execnz (@pLine); //It means that (exec0 == 0) && (exec1 == 0) + cExecnz:Result.pNode:=fetch_execnz (@pLine); //It means that (exec0 != 0) || (exec1 != 0) + cTidz :Result.pNode:=fetch_execnz_tid(@pLine); //It means that (exec[thread_id:] == 0) + cTidnz :Result.pNode:=fetch_execnz_tid(@pLine); //It means that (exec[thread_id:] != 0) else Assert(false,'ConvertCond'); end; @@ -438,13 +412,14 @@ begin case cond of cScc0, cVccz, - cExecz: + cExecz, + cTidz: begin //invert if TsrRegNode(Result.pNode).is_const then begin //early optimization - Result.pNode:=NewImm_b(TsrRegNode(Result.pNode).AsConst.AsBool,pLine); + Result.pNode:=NewImm_b(not TsrRegNode(Result.pNode).AsConst.AsBool,pLine); end else begin Result.pNode:=OpLogicalNotTo(Result.pNode,@pLine); @@ -458,6 +433,8 @@ begin end; function TEmitFlow.ConvertStatment(node:TsrStatement;pLine:TspirvOp):TConvertResult; +var + V:TsrVolatile; begin Result.pNode:=nil; Result.pLine:=pLine; @@ -466,19 +443,24 @@ begin sCond :begin Result:=ConvertCond(node.u.cond,pLine); end; + sCopy :begin + Result.pNode:=TsrNode(node.pCache); + Assert(Result.pNode<>nil); + end; sVar :begin if (node.pCache<>nil) then begin Result.pNode:=TsrNode(node.pCache); end else begin - Result.pNode:=PrivateList.NewVolatile(@RegsStory.FUnattach); + V:=PrivateList.NewVolatile(@RegsStory.FUnattach); + V.ForceBool:=True; + // + Result.pNode:=V; node.pCache:=Result.pNode; end; - end; - sLoad :begin - Result.pNode:=TsrNode(node.pCache); - Assert(Result.pNode<>nil); + //load + end; sNot :begin Result.pNode:=TsrNode(node.pCache); @@ -493,14 +475,37 @@ begin Assert(Result.pNode<>nil); end; else - Assert(false); + Assert(false,'ConvertStatment'); end; end; -procedure TEmitFlow.emit_break(b_adr:TSrcAdr;pCurr:TsrOpBlock); +function TEmitFlow.LoadStatment(C:TConvertResult):TConvertResult; +var + V:TsrVolatile; + R:TsrRegNode; +begin + Result:=C; + + if C.pNode.IsType(ntVolatile) then + begin + V:=C.pNode.specialize AsType; + Assert(V<>nil); + + R:=NewReg(dtBool); + R.pWriter:=V; + R.CustomLine:=C.pLine; + + Result.pNode:=R; + end; + +end; + +procedure TEmitFlow.emit_break(pCurr:TsrOpBlock); var pOpLabel:TspirvOp; + parent:TsrSourceBlock; + pLoop:TsrOpBlock; bnew:Boolean; @@ -510,25 +515,32 @@ begin pOpLabel:=nil; - if (pLoop.Block.e_adr.get_code_ptr=b_adr.get_code_ptr) then //is break? + { + parent:=pLoop.FCursor.AsBlock; + Assert(parent<>nil); + + if (parent.Last=Cursor.pNode) then //is break? begin pOpLabel:=pLoop.Labels.pEndOp; end else begin Assert(false,'break'); end; + } + pOpLabel:=pLoop.Labels.pEndOp; Assert(pOpLabel<>nil); + Assert(pLoop.FCursor.pNode<>nil); + parent:=pLoop.FCursor.AsBlock; + Assert(parent<>nil); + bnew:=true; - if pCurr.IsEndOf(Cursor.Adr) then //is last + //if pCurr.IsEndOf(Cursor.Adr) then //is last begin - Case pCurr.Block.bType of - btSetpc:; - else - begin - bnew:=false; - end; + if IsReal(pCurr.bType) then + begin + bnew:=false; end; end; @@ -554,6 +566,15 @@ Var begin case node.sType of sCond:; //skip + sCopy: + begin + C:=ConvertStatment(node.pSrc,line); + C:=LoadStatment(C); + R:=C.pNode.specialize AsType; + Assert(R<>nil); + + node.pCache:=R; + end; sStore: begin C:=ConvertStatment(node.pDst,line); @@ -561,32 +582,23 @@ begin Assert(V<>nil); C:=ConvertStatment(node.pSrc,C.pLine); - R:=C.pNode.specialize AsType; - Assert(R<>nil); + C:=LoadStatment(C); + D:=C.pNode.specialize AsType; + Assert(D<>nil); - V.AddStore(R); - end; - sLoad: - begin - C:=ConvertStatment(node.pSrc,line); - V:=C.pNode.specialize AsType; - Assert(V<>nil); + //Writeln('sStore to:',node.pDst.u.id,' from ',node.pSrc.u.id); - R:=NewReg(dtBool); - R.pWriter:=V; - R.CustomLine:=C.pLine; - - node.pCache:=R; + V.AddStore(D); end; sBreak: begin - Assert(node.sLabel<>nil); - - emit_break(node.sLabel.Adr,Main.pBlock); + emit_break(Main.pBlock); end; sNot: begin - R:=ConvertStatment(node.pSrc,line).pNode.specialize AsType; + C:=ConvertStatment(node.pSrc,line); + C:=LoadStatment(C); + R:=C.pNode.specialize AsType; Assert(R<>nil); R:=OpLogicalNotTo(R); @@ -595,10 +607,14 @@ begin end; sOr: begin - R:=ConvertStatment(node.pSrc,line).pNode.specialize AsType; + C:=ConvertStatment(node.pSrc,line); + C:=LoadStatment(C); + R:=C.pNode.specialize AsType; Assert(R<>nil); - D:=ConvertStatment(node.pDst,line).pNode.specialize AsType; + C:=ConvertStatment(node.pDst,line); + C:=LoadStatment(C); + D:=C.pNode.specialize AsType; Assert(D<>nil); R:=OpOrTo(R,D); @@ -607,10 +623,14 @@ begin end; sAnd: begin - R:=ConvertStatment(node.pSrc,line).pNode.specialize AsType; + C:=ConvertStatment(node.pSrc,line); + C:=LoadStatment(C); + R:=C.pNode.specialize AsType; Assert(R<>nil); - D:=ConvertStatment(node.pDst,line).pNode.specialize AsType; + C:=ConvertStatment(node.pDst,line); + C:=LoadStatment(C); + D:=C.pNode.specialize AsType; Assert(D<>nil); R:=OpAndTo(R,D); @@ -618,76 +638,53 @@ begin node.pCache:=R; end; else - Assert(false); + Assert(false,'EmitStatment'); end; end; -procedure TEmitFlow.EmitStatmentList(List:TsrStatementList); +function TEmitFlow.NewMerge(iCursor:TsrCursor):TsrOpBlock; var - node:TsrStatement; -begin - node:=List.pHead; - while (node<>nil) do - begin - EmitStatment(node); - // - node:=node.pNext; - end; -end; - -function TEmitFlow.NewMerge(pLBlock:TsrCFGBlock):TsrOpBlock; -var - Info:TsrBlockInfo; pMrgOp:TspirvOp; pLine:TspirvOp; pNop :TspirvOp; begin - Info:=Default(TsrBlockInfo); - Info.bType:=btMerg; - - if (pLBlock<>nil) then - begin - Info.b_adr:=pLBlock.pBLabel.Adr; - Info.e_adr:=pLBlock.pELabel.Adr; - end else - begin - Info.b_adr:=Cursor.prev_adr; - Info.e_adr:=Cursor.Adr; - end; - pMrgOp:=NewLabelOp(False); //merge - pMrgOp.Adr:=Info.e_adr; //save push point pLine:=line; + pNop:=nil; if pLine.IsType(ntOp) then if (pLine.OpId=Op.OpNop) then begin pNop:=pLine; - end else + pNop.mark([soNotUsed,soPost]); + end; + + if (pNop=nil) then begin pNop:=AddSpirvOp(pLine,Op.OpNop); - pNop.mark_not_used; + pNop.mark([soNotUsed,soPost]); // pLine:=pNop; end; Result:=AllocBlockOp; - Result.SetInfo(Info); + Result.SetInfo(btMerg); Result.SetLabels(nil,nil,pMrgOp); + //Result.Cond.FExcMerg:=pLBlock.ExcMerg; //save nop before Result.vctx.Befor:=pNop; //add nop aka PostLink pNop:=AddSpirvOp(pLine,Op.OpNop); - pNop.mark_not_used; + pNop.mark([soNotUsed,soPost]); Result.vctx.After:=pNop; //add by push point - PushBlockOp(pLine,Result,pLBlock); + PushBlockOp(pLine,Result,iCursor); //Deferred instruction //OpCondMerge(line,pMrgOp); @@ -704,14 +701,14 @@ begin Result:=pConst.AsBool; end; -function TEmitFlow.NewIf(pOpMerge:TsrOpBlock;pLBlock:TsrCFGBlock;src:TsrRegNode):TsrOpBlock; +function TEmitFlow.NewIf(pOpMerge:TsrOpBlock;iCursor:TsrCursor;src:TsrRegNode):TsrOpBlock; var orig:TsrRegsSnapshot; - pLElse:TsrCFGBlock; + pLBlock:TsrSourceBlock; + pLElse:TsrSourceBlock; pBegOp,pEndOp,pMrgOp,pAfter,pBefor:TspirvOp; pOpElse:TsrOpBlock; pOpBody:TsrOpBlock; - Info:TsrBlockInfo; function _IsNestedTrue(src:TsrRegNode):Boolean; var @@ -728,30 +725,25 @@ begin pAfter:=pOpMerge.vctx.After; pBefor:=pOpMerge.vctx.Befor; - src:=nil; + pLBlock:=iCursor.AsBlock; if (pLBlock<>nil) then if (pLBlock.pElse=nil) then //no else if (pLBlock.pCond<>nil) then //have cond begin - src:=ConvertStatment(pLBlock.pCond,pBefor).pNode; + src:=LoadStatment(ConvertStatment(pLBlock.pCond,pBefor)).pNode; // if _IsConstTrue(src) or _IsNestedTrue(src) then begin //early optimization - pOpMerge.Block.bType:=btOther; + pOpMerge.bType:=btOther; //down body group - Info:=Default(TsrBlockInfo); - Info.bType:=btOther; - Info.b_adr:=pLBlock.pBLabel.Adr; - Info.e_adr:=pLBlock.pELabel.Adr; - pOpBody:=AllocBlockOp; - pOpBody.SetInfo(Info); - PushBlockOp(line,pOpBody,pLBlock); + pOpBody.SetInfo(btOther); + PushBlockOp(line,pOpBody,Default(TsrCursor)); Exit(pOpBody); end; @@ -770,19 +762,6 @@ begin orig:=RegsStory.get_snapshot; - Info:=Default(TsrBlockInfo); - Info.bType:=btCond; - - if (pLBlock<>nil) then - begin - Info.b_adr:=pLBlock.pBLabel.Adr; - Info.e_adr:=pLBlock.pELabel.Adr; - end else - begin - Info.b_adr:=Cursor.prev_adr; - Info.e_adr:=Cursor.Adr; - end; - pBegOp:=NewLabelOp(False); //begin if (pLElse<>nil) then //have else @@ -793,17 +772,14 @@ begin pEndOp:=pMrgOp; //endif end; - pBegOp.Adr:=Info.b_adr; - pEndOp.Adr:=Info.e_adr; - Result:=NewBlockOp(orig); Result.SetLabels(pBegOp,pEndOp,pMrgOp); - Result.SetInfo(Info); + Result.SetInfo(btCond); Result.vctx.Befor:=pBefor; Result.vctx.After:=pAfter; //move nop link - PushBlockOp(line,Result,pLBlock); + PushBlockOp(line,Result,iCursor); pOpMerge.pBody:=Result; //Merge->if @@ -813,7 +789,7 @@ begin begin if (src=nil) then begin - src:=ConvertStatment(pLBlock.pCond,pBefor).pNode; + src:=LoadStatment(ConvertStatment(pLBlock.pCond,pBefor)).pNode; end; Assert(src<>nil); // @@ -847,14 +823,11 @@ begin if (pLElse<>nil) then //have else begin - Info.bType:=btElse; - Info.b_adr:=pLElse.pBLabel.Adr; - Info.e_adr:=pLElse.pELabel.Adr; //create else block pOpElse:=AllocBlockOp; pOpElse.SetLabels(pEndOp,pMrgOp,pMrgOp); - pOpElse.SetInfo(Info); + pOpElse.SetInfo(btElse); pOpElse.vctx.After:=pAfter; //move nop link //save snap links @@ -871,35 +844,22 @@ begin pOpMerge.pIf:=Result; //down body group - Info.bType:=btOther; - - if (pLBlock<>nil) then - begin - Info.b_adr:=pLBlock.pBLabel.Adr; - Info.e_adr:=pLBlock.pELabel.Adr; - end else - begin - Info.b_adr:=Cursor.prev_adr; - Info.e_adr:=Cursor.Adr; - end; - pOpBody:=AllocBlockOp; - pOpBody.SetInfo(Info); + pOpBody.SetInfo(btOther); Result.pBody:=pOpBody; //save body link - PushBlockOp(line,pOpBody); + PushBlockOp(line,pOpBody,Default(TsrCursor)); end; -function TEmitFlow.NewElse(pOpMerge:TsrOpBlock;pLBlock:TsrCFGBlock):TsrOpBlock; +function TEmitFlow.NewElse(pOpMerge:TsrOpBlock;iCursor:TsrCursor):TsrOpBlock; var pBegOp,pMrgOp:TspirvOp; pOpBody:TsrOpBlock; - Info:TsrBlockInfo; begin Result:=pOpMerge.pElse; Assert(Result<>nil); //down else block - PushBlockOp(line,Result,pLBlock); + PushBlockOp(line,Result,iCursor); pBegOp:=Result.Labels.pBegOp; pMrgOp:=Result.Labels.pMrgOp; @@ -911,24 +871,19 @@ begin AddSpirvOp(line,pBegOp); //start else //down body group - Info.bType:=btOther; - Info.b_adr:=pLBlock.pBLabel.Adr; - Info.e_adr:=pLBlock.pELabel.Adr; - pOpBody:=AllocBlockOp; - pOpBody.SetInfo(Info); + pOpBody.SetInfo(btOther); Result.pBody:=pOpBody; //save body link - PushBlockOp(line,pOpBody); + PushBlockOp(line,pOpBody,Default(TsrCursor)); end; -function TEmitFlow.NewLoop(pLBlock:TsrCFGBlock):TsrOpBlock; +function TEmitFlow.NewLoop(iCursor:TsrCursor):TsrOpBlock; var orig:TsrRegsSnapshot; pLine:TspirvOp; pBegOp,pEndOp,pMrgOp,pRepOp:TspirvOp; pNop:TspirvOp; pOpBody:TsrOpBlock; - Info:TsrBlockInfo; begin orig:=RegsStory.get_snapshot; PrivateList.make_copy_all; @@ -936,14 +891,18 @@ begin //get before pLine:=line; + pNop:=nil; if pLine.IsType(ntOp) then if (pLine.OpId=Op.OpNop) then begin pNop:=pLine; - end else + pNop.mark([soNotUsed,soPost]); + end; + + if (pNop=nil) then begin pNop:=AddSpirvOp(pLine,Op.OpNop); - pNop.mark_not_used; + pNop.mark([soNotUsed,soPost]); // pLine:=pNop; end; @@ -951,24 +910,14 @@ begin Assert(pLine.IsType(ntOp) ,'WTF'); Assert(pLine.OpId=Op.OpNop,'WTF'); - Info:=Default(TsrBlockInfo); - Info.b_adr:=pLBlock.pBLabel.Adr; - Info.e_adr:=pLBlock.pELabel.Adr; - Info.bType:=btLoop; - pBegOp:=NewLabelOp(False); //continue pEndOp:=NewLabelOp(False); //end pMrgOp:=NewLabelOp(False); //cond pRepOp:=NewLabelOp(False); //start - pBegOp.Adr:=Info.b_adr; - pEndOp.Adr:=Info.e_adr; - pMrgOp.Adr:=Info.e_adr; - pRepOp.Adr:=Info.b_adr; - Result:=NewBlockOp(RegsStory.get_snapshot,orig); Result.SetLabels(pBegOp,pEndOp,pMrgOp); - Result.SetInfo(Info); + Result.SetInfo(btLoop); //save nop before Result.vctx.Befor:=pNop; @@ -978,11 +927,11 @@ begin //add nop aka PostLink pNop:=AddSpirvOp(pLine,Op.OpNop); - pNop.mark_not_used; + pNop.mark([soNotUsed,soPost]); // Result.vctx.After:=pNop; - PushBlockOp(pLine,Result,pLBlock); + PushBlockOp(pLine,Result,iCursor); OpBranch (line,pBegOp); AddSpirvOp(line,pBegOp); //continue loop @@ -992,92 +941,77 @@ begin AddSpirvOp (line,pRepOp); //down group - Info.bType:=btOther; pOpBody:=AllocBlockOp; - pOpBody.SetInfo(Info); + pOpBody.SetInfo(btOther); Result.pBody:=pOpBody; //save body link - PushBlockOp(line,pOpBody); + PushBlockOp(line,pOpBody,Default(TsrCursor)); end; -function TEmitFlow.CheckBlockBeg:Boolean; +function TEmitFlow.BlockBeg:Boolean; var - pLBlock:TsrCFGBlock; + parent:TsrSourceBlock; pOpMerge:TsrOpBlock; - adr:TSrcAdr; begin Result:=False; //is marked of end - if IsFinalize then Exit; + //if IsFinalize then Exit; - adr:=Cursor.Adr; + parent:=Cursor.AsBlock; - if (FindLabel(adr)=nil) then Exit; + Case parent.bType of + btMerg: + begin + pOpMerge:=NewMerge(Cursor); - pLBlock:=Cursor.pBlock.FindBlock(adr); + Result:=True; + end; + btCond: + begin + pOpMerge:=line.Parent; + Assert(pOpMerge<>nil); + Assert(pOpMerge.bType=btMerg); - if (pLBlock<>nil) then - begin - EmitStatmentList(pLBlock.FBefore); + NewIf(pOpMerge,Cursor,nil); - Case pLBlock.bType of - btMerg: - begin - pOpMerge:=NewMerge(pLBlock); + Result:=True; + end; + btElse: + begin + pOpMerge:=line.Parent; + Assert(pOpMerge<>nil); + Assert(pOpMerge.bType=btMerg); - Result:=True; - end; - btCond: - begin - pOpMerge:=line.Parent; - Assert(pOpMerge<>nil); - Assert(pOpMerge.Block.bType=btMerg); + NewElse(pOpMerge,Cursor); - NewIf(pOpMerge,pLBlock,nil); + Result:=True; + end; + btLoop: + begin + NewLoop(Cursor); - Result:=True; - end; - btElse: - begin - pOpMerge:=line.Parent; - Assert(pOpMerge<>nil); - Assert(pOpMerge.Block.bType=btMerg); - - NewElse(pOpMerge,pLBlock); - - Result:=True; - end; - btLoop: - begin - NewLoop(pLBlock); - - Result:=True; - end; - btInline: //skip - begin - adr:=pLBlock.pELabel.Adr; - Cursor.Adr:=adr; - end; - else - begin - Assert(false); - end; - end; - - EmitStatmentList(pLBlock.FStart); + Result:=True; + end; + btInline: //skip + begin + // + end; + else + begin + Assert(false); + end; end; end; -function TEmitFlow.CheckBlockEnd:Boolean; +function TEmitFlow.BlockEnd:Boolean; begin Result:=False; if (Main=nil) then Exit; if (Main.pBlock=nil) then Exit; if (Main.pBlock.Parent<>nil) then - if Main.pBlock.IsEndOf(Cursor.Adr) then begin Result:=PopBlockOp; end; @@ -1087,12 +1021,12 @@ end; function TEmitFlow.get_code_ptr:Pointer; begin - Result:=Cursor.Adr.get_code_ptr; + Result:=Cursor.e_adr.get_code_ptr; end; procedure TEmitFlow.set_code_ptr(base:Pointer;bType:TsrBlockType); begin - if (Cursor.Adr.get_code_ptr=base) then Exit; + if (Cursor.b_adr.get_code_ptr=base) then Exit; Cursor:=CodeHeap.FetchByPtr(base,bType); end; @@ -1101,6 +1035,7 @@ begin Result:=CodeHeap.FetchByPtr(base,bType); end; +{ function TEmitFlow.IsFinalize:Boolean; begin Result:=False; @@ -1111,13 +1046,7 @@ begin Result:=True; end; end; - -function TEmitFlow.FindLabel(Adr:TSrcAdr):TsrLabel; -begin - Result:=nil; - if (Cursor.pCode=nil) then Exit; - Result:=Cursor.pCode.FindLabel(Adr); -end; +} procedure TEmitFlow.Finalize; begin @@ -1134,68 +1063,108 @@ end; // -function TEmitFlow.NextParse:Byte; -var - FLevel:DWORD; -begin - if (Cursor.pCode=nil) then Exit(2); - if (Cursor.pBlock=nil) then Exit(3); - if (Main=nil) then Exit(4); - if (Main.pBlock=nil) then Exit(5); - - if Config.PrintAsm then - begin - Write(HexStr(Cursor.OFFSET_DW*4,4)); - - //Write('(',GetGlobalIndex(line),')'); - - FLevel:=0; - if (Main<>nil) then - if (Main.pBlock<>nil) then - begin - FLevel:=Main.pBlock.Level; - end; - Write(Space(FLevel+1)); - end; - - Result:=Cursor.Next(FSPI); - if (Result>1) then Exit; - - if Config.PrintAsm then - begin - print_spi(FSPI); - end; - - emit_spi; - - While (CheckBlockBeg) do; - While (CheckBlockEnd) do; - While (CheckBlockBeg) do; - - Result:=0; - if IsFinalize then - begin - Finalize; - Result:=1; - end; - -end; - function TEmitFlow.ParseStage(base:Pointer):Integer; +label + _skip, + _up; +var + next:TsrSourceNode; + FLevel:DWORD; begin Result:=0; set_code_ptr(base,btMain); - Main.pTop.SetCFGBlock(Cursor.pBlock); - While (CheckBlockBeg) do; - repeat - Result:=NextParse; - Case Result of - 0:; - 1:Break; - else - Break; + + while (Cursor.pNode<>nil) do + begin + + if Cursor.fnext then + begin + //skip intruction + Cursor.fnext:=False; + goto _skip; end; - until false; + + //down + while (Cursor.pNode.ntype=TsrSourceBlock) do + begin + BlockBeg; + next:=Cursor.pNode.First; + if (next=nil) then + begin + //up + goto _up; + end; + Cursor.pNode:=next; + Cursor.UpdateAdr; + end; + + if (Cursor.pNode.ntype=TsrSourceNode) then + begin + //skip + end else + if (Cursor.pNode.ntype=TsrSourceLabel) then + begin + //skip + end else + if (Cursor.pNode.ntype=TsrSourceInstruction) then + begin + // + FSPI:=TsrSourceInstruction(Cursor.pNode).FSPI; + // + if Config.PrintAsm then + begin + + FLevel:=0; + if (Main<>nil) then + if (Main.pBlock<>nil) then + begin + FLevel:=Main.pBlock.Level; + end; + + Writeln(HexStr(Cursor.b_adr.Offset,4),Space(FLevel+1),get_str_spi(FSPI)); + end; + // + next:=Cursor.pNode; + + emit_spi; + + if (Cursor.pNode<>next) then + begin + //node is change + Continue; + end; + // + end else + if (Cursor.pNode.ntype=TsrStatement) then + begin + // + EmitStatment(TsrStatement(Cursor.pNode)); + // + end else + begin + Assert(false,'Unhandled node:'+Cursor.pNode.ntype.ClassName); + end; + + _skip: + + next:=Cursor.pNode.pNext; + while (next=nil) and + (Cursor.pNode.pParent<>nil) and + (Cursor.pNode.pParent<>Cursor.pCode.FTop) do + begin + _up: + //up + BlockEnd; //"Cursor.pNode:=Cursor.pNode.pParent" in "PopBlockOp" + // + next:=Cursor.pNode.pNext; + end; + // + Cursor.pNode:=next; + Cursor.UpdateAdr; + + end; //while + + Finalize; end; end. diff --git a/spirv/srInput.pas b/spirv/srInput.pas index 14252d8e..5dc9f1a4 100644 --- a/spirv/srInput.pas +++ b/spirv/srInput.pas @@ -205,7 +205,7 @@ var l:TSpirvOp; begin l:=node.pReg.pWriter.specialize AsType; - l.mark_not_used; + l.mark([soNotUsed]); c:=PsrConstList(FEmit.GetConstList)^.Fetch(node.pReg.dtype,0); node.pReg.pWriter:=c; diff --git a/spirv/srInterface.pas b/spirv/srInterface.pas index 8653035c..589b595d 100644 --- a/spirv/srInterface.pas +++ b/spirv/srInterface.pas @@ -85,6 +85,8 @@ type FSGPRS :WORD; FGeometryInfo :TGeometryInfo; // + FThread_id :TsrRegNode; + // Config:TsrConfig; // FSPI:TSPI; @@ -208,10 +210,6 @@ type function get_exec0:PsrRegSlot; function get_exec1:PsrRegSlot; function get_scc :PsrRegSlot; - // - function fetch_vccz :TsrRegNode; - function fetch_execz:TsrRegNode; - function fetch_scc :TsrRegNode; end; implementation @@ -503,7 +501,7 @@ function TEmitInterface.NewSpirvOp(OpId:DWORD):TSpirvOp; begin Result:=specialize New; Result.Init(OpId); - Result.adr:=Cursor.Adr; + //Result.adr:=Cursor.Adr; end; function TEmitInterface.NewLabelOp(sdep:Boolean):TSpirvOp; @@ -558,7 +556,7 @@ begin node:=AddSpirvOp(node,Op.OpNop); node.AddParam(dst); - node.mark_not_used; + node.mark([soNotUsed,soPost]); Exit(node); end; @@ -803,26 +801,6 @@ end; // - -function TEmitInterface.fetch_vccz:TsrRegNode; -begin - //It means that lane_id=0 - Result:=MakeRead(get_vcc0,dtBool); //implict cast (int != 0) -end; - -function TEmitInterface.fetch_execz:TsrRegNode; -begin - //It means that lane_id=0 - Result:=MakeRead(get_exec0,dtBool); //implict cast (int != 0) -end; - -function TEmitInterface.fetch_scc:TsrRegNode; -begin - Result:=MakeRead(get_scc,dtBool); -end; - -// - end. diff --git a/spirv/srLayout.pas b/spirv/srLayout.pas index 96d22001..a6fe45df 100644 --- a/spirv/srLayout.pas +++ b/spirv/srLayout.pas @@ -926,7 +926,7 @@ var Writer:TseWriter; pHeap :PsrCodeHeap; desc :TsrDescriptor; - block :TsrCodeBlock; + pCode :TsrCodeRegion; imm :TsrDataImm; PV :PVSharpResource4; PS :PTSharpResource4; @@ -1020,11 +1020,11 @@ begin rtFunPtr2: begin //func - block:=pHeap^.FindByPtr(Writer.node.GetData); - Assert(block<>nil); + pCode:=pHeap^.FindByPtr(Writer.node.GetData); + Assert(pCode<>nil); // - Writer.HexOpt('LEN',block.Size); - Writer.ImmOpt('IMM',block.DMem,block.Size); + Writer.HexOpt('LEN',pCode.Size); + Writer.ImmOpt('IMM',pCode.DMem,pCode.Size); end; else; end; @@ -1215,7 +1215,7 @@ begin if (dst<>nil) then begin old:=dst.dtype; - if (old<>dtUnknow) and (not CompareType(rtype,old)) then + if (old<>dtUnknow) and (rtype<>old) then begin //OpLoad -> new -> dst dst:=pBitcastList^.FetchDstr(rtype,dst); diff --git a/spirv/srNode.pas b/spirv/srNode.pas index 20f8cc2a..7e21b015 100644 --- a/spirv/srNode.pas +++ b/spirv/srNode.pas @@ -15,6 +15,7 @@ type pLeft,pRight:TDependenceNode; // key:TsrNode; + // fread_count :DWORD; fwrite_count:DWORD; // diff --git a/spirv/srOp.pas b/spirv/srOp.pas index 1ca2c916..6d116789 100644 --- a/spirv/srOp.pas +++ b/spirv/srOp.pas @@ -10,7 +10,6 @@ uses srOpInternal, ginodes, srNode, - srCFGLabel, srCFGParser, srCFGCursor, srLiteral, @@ -58,7 +57,7 @@ type TsrOpList=specialize TNodeListClass; - TsoFlags=(soClear,soNotUsed,soForce); + TsoFlags=(soClear,soNotUsed,soForce,soPost); TsoSetFlags=Set of TsoFlags; TspirvOp=class(TsrOpCustom) @@ -71,7 +70,7 @@ type Procedure SetDst(r:TsrNode); Procedure UnClear; public - Adr :TSrcAdr; + //Adr :TSrcAdr; OpId:DWORD; // Procedure _zero_read; override; @@ -95,8 +94,9 @@ type procedure AddString(const name:RawByteString); function is_cleared:Boolean; function is_force:Boolean; + function is_post:Boolean; function Clear:Boolean; - procedure mark_not_used(Force:Boolean=False); + procedure mark(f:TsoSetFlags); function can_clear:Boolean; end; @@ -104,11 +104,6 @@ type TsrVolMark=(vmNone,vmEndpg,vmBreak,vmConti,vmMixed); - TsrBlockInfo=packed record - b_adr,e_adr:TSrcAdr; - bType:TsrBlockType; - end; - TsrOpBlockCustom=class(TsrOpCustom) private FList :TsrOpList; @@ -138,7 +133,7 @@ type TsrOpBlock=packed class(TsrOpBlockCustom) public - Block:TsrBlockInfo; + bType:TsrBlockType; Labels:record pBegOp:TspirvOp; @@ -153,7 +148,6 @@ type vctx :TsrVolatileContext; - FLBlock:TsrCFGBlock; FCursor:TsrCursor; Regs:record @@ -166,6 +160,7 @@ type pReg :TsrRegNode; FNormalOrder:Boolean; FUseCont :Boolean; + FExcMerg :Boolean; end; FVolMark:TsrVolMark; @@ -173,12 +168,9 @@ type dummy:TspirvOp; procedure Init; - procedure SetCFGBlock(pLBlock:TsrCFGBlock); - procedure SetInfo(const b:TsrBlockInfo); - procedure SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr); + procedure SetInfo(_bType:TsrBlockType); procedure SetLabels(pBegOp,pEndOp,pMrgOp:TspirvOp); procedure SetCond(pReg:TsrRegNode;FNormalOrder:Boolean); - function IsEndOf(Adr:TSrcAdr):Boolean; function FindUpLoop:TsrOpBlock; function FindUpCond:TsrOpBlock; function FindUpCondByReg(pReg:TsrRegNode;rDown:Boolean;var Invert:Boolean):TsrOpBlock; @@ -568,12 +560,18 @@ begin Result:=(soForce in flags); end; +function TspirvOp.is_post:Boolean; +begin + Result:=(soPost in flags); +end; + function TspirvOp.Clear:Boolean; var node:POpParamNode; b:Byte; begin Result:=False; + if not can_clear then Exit; if (read_count<>0) then @@ -650,13 +648,9 @@ begin flags:=flags-[soClear]; end; -procedure TspirvOp.mark_not_used(Force:Boolean=False); +procedure TspirvOp.mark(f:TsoSetFlags); begin - flags:=flags+[soNotUsed]; - if Force then - begin - flags:=flags+[soForce]; - end; + flags:=flags+f; end; function TspirvOp.can_clear:Boolean; @@ -680,28 +674,9 @@ begin vctx.block:=Self; end; -procedure TsrOpBlock.SetCFGBlock(pLBlock:TsrCFGBlock); +procedure TsrOpBlock.SetInfo(_bType:TsrBlockType); begin - dummy.Adr :=pLBlock.pBLabel.Adr; - Block.b_adr:=pLBlock.pBLabel.Adr; - Block.e_adr:=pLBlock.pELabel.Adr; - Block.bType:=pLBlock.bType; -end; - -procedure TsrOpBlock.SetInfo(const b:TsrBlockInfo); -begin - dummy.Adr :=b.b_adr; - Block.b_adr:=b.b_adr; - Block.e_adr:=b.e_adr; - Block.bType:=b.bType; -end; - -procedure TsrOpBlock.SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr); -begin - dummy.Adr :=b_adr; - Block.b_adr:=b_adr; - Block.e_adr:=e_adr; - Block.bType:=bType; + bType:=_bType; end; procedure TsrOpBlock.SetLabels(pBegOp,pEndOp,pMrgOp:TspirvOp); @@ -717,11 +692,6 @@ begin Cond.FNormalOrder:=FNormalOrder; end; -function TsrOpBlock.IsEndOf(Adr:TSrcAdr):Boolean; -begin - Result:=(Block.e_adr.get_code_ptr<=Adr.get_code_ptr); -end; - function TsrOpBlock.FindUpLoop:TsrOpBlock; var node:TsrOpBlock; @@ -730,7 +700,7 @@ begin node:=Self; While (node<>nil) do begin - if (node.Block.bType=btLoop) then Exit(node); + if (node.bType=btLoop) then Exit(node); node:=node.pParent; end; end; @@ -743,7 +713,7 @@ begin node:=Self; While (node<>nil) do begin - if (node.Block.bType=btCond) then Exit(node); + if (node.bType=btCond) then Exit(node); node:=node.pParent; end; end; @@ -763,7 +733,7 @@ begin node:=Self; While (node<>nil) do begin - if (node.Block.bType=btCond) then + if (node.bType=btCond) then begin // pCond:=node.Cond.pReg; @@ -777,7 +747,7 @@ begin Exit(node); end; end else - if (node.Block.bType=btElse) then + if (node.bType=btElse) then begin Assert(node.pIf<>nil); node:=node.pIf; diff --git a/spirv/srOpUtils.pas b/spirv/srOpUtils.pas index d8374a7c..1db338ff 100644 --- a/spirv/srOpUtils.pas +++ b/spirv/srOpUtils.pas @@ -11,7 +11,7 @@ uses srReg, srLayout, srVariable, - srCFGLabel; + srCFGParser; function InsSpirvOp(pLine,pNew:TSpirvOp):TSpirvOp; Function get_inverse_left_cmp_op(OpId:DWORD):DWORD; @@ -79,7 +79,7 @@ function flow_prev_up(pLine:TSpirvOp):TSpirvOp; Result:=nil; if (p<>nil) then if p.IsType(ntOpBlock) then - if not IsReal(TsrOpBlock(p).Block.bType) then + if not IsReal(TsrOpBlock(p).bType) then begin Result:=p.Last; end; @@ -114,7 +114,7 @@ begin tmp:=flow_down_prev_up(tmp); Assert(tmp<>nil); end; - pNew.Adr:=tmp.Adr; + //pNew.Adr:=tmp.Adr; end; pLine.InsertAfter(pNew); @@ -529,31 +529,101 @@ begin end; end; -function GetChainRegNode(node:TsrRegNode):TsrChain; +type + a_volatile_node=array of TsrRegNode; + +procedure add_node(var A:a_volatile_node;node:TsrRegNode); +var + i:Integer; +begin + //check exist + if Length(A)<>0 then + For i:=0 to High(A) do + begin + if (A[i]=node) then Exit; + end; + // + Insert([node],A,High(A)); +end; + +procedure add_volatile(var A:a_volatile_node;V:TsrVolatile); +var + node:TStoreNode; +begin + node:=V.FList.pHead; + while (node<>nil) do + begin + add_node(A,RegDown(node.src)); + // + node:=node.pNext; + end; +end; + +function next_volatile(var A:a_volatile_node;var i:Integer):TsrRegNode; +begin + if (inil) do + begin node:=RegDown(node); if node.pWriter.IsType(TsrVolatile) then begin V:=node.pWriter.specialize AsType; - node:=V.FList.pTail.src; - end else - begin - Break; + add_volatile(A,V); + node:=next_volatile(A,i); end; - until false; - pOp:=node.pWriter.specialize AsType; - if (pOp=nil) then Exit; + pOp:=node.pWriter.specialize AsType; + if (pOp<>nil) then + if (pOp.OpId=Op.OpLoad) then + begin + C:=pOp.ParamNode(0).Value.specialize AsType; - if (pOp.OpId<>Op.OpLoad) then Exit; - Result:=pOp.ParamNode(0).Value.specialize AsType; + if (C<>nil) then + begin + Insert([C],Result,High(Result)); + end; + end; + + node:=next_volatile(A,i); + end; +end; + +function GetChainRegNode(node:TsrRegNode):TsrChain; +Var + A:AsrChain; +begin + A:=GetChainRegNode2(node); + if (Length(A)=0) then Exit(nil); + if (Length(A)>1) then + begin + Assert(false,'Multiple reachable chains are not supported!'); + end; + Result:=A[0]; end; function GetSourceRegNode(node:TsrRegNode):TsrNode; diff --git a/spirv/srPrivate.pas b/spirv/srPrivate.pas index 8c865fa7..dd7d2c5b 100644 --- a/spirv/srPrivate.pas +++ b/spirv/srPrivate.pas @@ -18,7 +18,7 @@ uses srVariable, srConst, srBitcast, - srCFGLabel; + srCFGParser; type TsrPrivate=class; @@ -27,7 +27,7 @@ type pPrev,pNext:TStoreNode; // src :TsrRegNode; - line:TspirvOp; + //line:TspirvOp; // end; TStoreNodeList=specialize TNodeListClass; @@ -40,11 +40,13 @@ type 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; @@ -176,11 +178,29 @@ begin 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; @@ -198,7 +218,7 @@ begin Assert(pLine<>nil); node:=Emit.specialize New; //cache in free list? node.src :=src; - node.line:=pLine; + //node.line:=pLine; if FZeroRead then begin src.mark_read(Self); @@ -209,8 +229,8 @@ end; Procedure TsrVolatile.PushStore(node:TStoreNode); begin if (node=nil) then Exit; - Assert(node.src.pLine<>nil); - Assert(node.line<>nil); + //Assert(node.src.pLine<>nil); + //Assert(node.line<>nil); if FZeroRead then begin node.src.mark_read(Self); @@ -343,7 +363,7 @@ begin if (dst<>nil) then begin old:=dst.dtype; - if (old<>dtUnknow) and (not CompareType(rtype,old)) then + if (old<>dtUnknow) and (rtype<>old) then begin //OpLoad -> new -> dst dst:=pBitcastList^.FetchDstr(rtype,dst); @@ -406,6 +426,8 @@ begin end; end; + +{ procedure _update_store_line(pLine:TspirvOp); var pReg:TsrRegNode; @@ -422,13 +444,22 @@ begin pCur.InsertAfter(pLine); end; end; +} Procedure TsrPrivate.SortLines; var dnode,dnext:TDependenceNode; - pLine:array[0..1] of TspirvOp; + //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; @@ -437,13 +468,14 @@ begin dnext:=dnode.pNext; if (dnext=nil) then Break; - pLine[0]:=dnode.pNode; - pLine[1]:=dnext.pNode; + //pLine[0]:=dnode.pNode; + //pLine[1]:=dnext.pNode; - _update_store_line(pLine[0]); - _update_store_line(pLine[1]); + //_update_store_line(pLine[0]); + //_update_store_line(pLine[1]); - if (MaxLine(pLine[0],pLine[1])=pLine[0]) then //dnode>dnext + //if (MaxLine(pLine[0],pLine[1])=pLine[0]) then //dnode>dnext + if (dnode.fread_count>dnext.fread_count) then begin //swap nswp:=False; @@ -466,7 +498,7 @@ begin if (node=prev) then Exit(True); // if node.IsType(ntOpBlock) then - if IsReal(TsrOpBlock(node).Block.bType) then + if IsReal(TsrOpBlock(node).bType) then begin Exit(False); end; @@ -501,7 +533,7 @@ begin begin //Remove dprev FLineList.Remove(dprev); - pLine[1].mark_not_used; + pLine[1].mark([soNotUsed]); Continue; end else if (pLine[0].OpId=Op.OpStore) and (pLine[1].OpId=Op.OpLoad) then @@ -516,7 +548,7 @@ begin begin //Remove dnode FLineList.Remove(dnode); - pLine[0].mark_not_used; + pLine[0].mark([soNotUsed]); dnode:=dprev; if (dnode.pNext<>nil) then @@ -745,7 +777,7 @@ begin pLine:=ctx.after; //replace next - _next:=pSlot^.New(rtype,pLine); + _next:=pSlot^._New(rtype,pLine); //<-The slot value will not be updated _next.pWriter:=pVolatile; ctx.AddVolatile(pVolatile,_next); @@ -827,7 +859,7 @@ begin pLine:=ctx.after; //replace next - _next:=pSlot^.New(rtype,pLine); + _next:=pSlot^._New(rtype,pLine); //<-The slot value will not be updated _next.pWriter:=pVolatile; ctx.AddVolatile(pVolatile,_next); @@ -916,6 +948,24 @@ begin 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 @@ -933,6 +983,7 @@ begin rtype:=LazyType2(rtype,prv.dtype); end; end; + } // if (cur<>nil) then begin @@ -949,7 +1000,7 @@ begin if (prev=nil) then begin //The input register is not defined, should it be initialized to make_copy_slot? - prev:=pSlot^.New(rtype,pLine); + prev:=pSlot^._New(rtype,pLine); //<-The slot value will not be updated end; //set backedge dependence @@ -1075,6 +1126,56 @@ begin 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; @@ -1084,6 +1185,7 @@ var pLine:TspirvOp; //pTmp:TspirvOp; //vtmp:TsrVolatile; + dtype:TsrDataType; begin Result:=src; if (src=nil) then Exit; @@ -1098,18 +1200,42 @@ begin pVolatile:=src.pWriter.specialize AsType; - pPrivate:=pVolatile.FPrivate; + 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); - pVolatile.FPrivate:=pPrivate; + + 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(src.dtype); - pVolatile.PrepType(pPrivate.GetRegType); + pPrivate .PrepType(dtype); + + pVolatile.PrepType(dtype); if (pPrivate.GetRegType=dtUnknow) then begin @@ -1126,7 +1252,8 @@ begin begin //pLine:=TsrRegNode(node.pNode).pLine; - pLine:=node.line; + //pLine:=node.line; + pLine:=node.src.pLine; Assert(pLine<>nil); up_merge_line(pLine); @@ -1156,7 +1283,7 @@ begin //ntVolatile -> src -> next //Opload -> new - Result:=src.pSlot^.New(src.dtype,dst); + Result:=src.pSlot^._New(src.dtype,dst); //<-The slot value will not be updated pPrivate.FetchLoad(dst,Result); //before reg end; diff --git a/spirv/srReg.pas b/spirv/srReg.pas index e85803d0..849179ff 100644 --- a/spirv/srReg.pas +++ b/spirv/srReg.pas @@ -124,6 +124,7 @@ type FBits :TsrBitKey; procedure set_current(c:TsrRegNode); public + FPrivate:TsrNode; property Emit :TCustomEmit read FEmit; property current :TsrRegNode read FCurrent write set_current; property Name :TString7 read FName; @@ -137,6 +138,7 @@ type function isBoolOnly:Boolean; function isScalar:Boolean; function iUnattach:Boolean; + function _New(rtype:TsrDataType;pLine:TsrRegNode):TsrRegNode; function New(rtype:TsrDataType;pLine:TsrRegNode=nil):TsrRegNode; end; @@ -1046,7 +1048,7 @@ begin Result:=(FBits.Category=cUnattach); end; -function TsrRegSlot.New(rtype:TsrDataType;pLine:TsrRegNode=nil):TsrRegNode; +function TsrRegSlot._New(rtype:TsrDataType;pLine:TsrRegNode):TsrRegNode; var node:TsrRegNode; begin @@ -1059,8 +1061,13 @@ begin node.dtype:=rtype; node.CustomLine:=pLine; Result:=node; +end; + +function TsrRegSlot.New(rtype:TsrDataType;pLine:TsrRegNode=nil):TsrRegNode; +begin + Result:=_New(rtype,pLine); //update - current:=node; + current:=Result; end; // diff --git a/vulkan/vRectGS.pas b/vulkan/vRectGS.pas index 0c78be18..6f2ff8b3 100644 --- a/vulkan/vRectGS.pas +++ b/vulkan/vRectGS.pas @@ -166,16 +166,17 @@ begin yxEqual:=SprvEmit.OpAndTo(CoordEqualY[i], CoordEqualX[(i + 2) mod 3]); // EdgeVertex[i]:=SprvEmit.OpOrTo(xyEqual,yxEqual); - // - barycentric[i]:=SprvEmit.OpSelectTo(pOneId,pMinusOne,EdgeVertex[i]); + //cond,src_true,src_false + barycentric[i]:=SprvEmit.OpSelectTo(EdgeVertex[i],pMinusOne,pOneId); end; //calc last pos Positions[3]:=interpolate(SprvEmit,dtVec4f,@barycentric,@Positions); //select first index - pIndex:=SprvEmit.OpSelectTo(UintId[0], UintId[1], EdgeVertex[1]); - pIndex:=SprvEmit.OpSelectTo(pIndex , UintId[2], EdgeVertex[2]); + //cond,src_true,src_false + pIndex:=SprvEmit.OpSelectTo(EdgeVertex[1], UintId[1], UintId[0]); + pIndex:=SprvEmit.OpSelectTo(EdgeVertex[2], UintId[2], pIndex ); //Send vertex by index For i:=0 to 2 do