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