diff --git a/spirv/emit_post_op.pas b/spirv/emit_post_op.pas index 23ff11aa..7cb6c7df 100644 --- a/spirv/emit_post_op.pas +++ b/spirv/emit_post_op.pas @@ -47,6 +47,7 @@ type function OnBitwiseOr1(node:PSpirvOp):Integer; function OnLogicalOr1(node:PSpirvOp):Integer; function OnNot1(node:PSpirvOp):Integer; + function OnLogicalNot1(node:PSpirvOp):Integer; function OnBranchConditional1(node:PSpirvOp):Integer; // function OpBitCount1(node:PSpirvOp):Integer; @@ -103,6 +104,7 @@ begin Op.OpLogicalOr :Result:=OnLogicalOr1(node); Op.OpNot :Result:=OnNot1(node); + Op.OpLogicalNot :Result:=OnLogicalNot1(node); Op.OpBranchConditional:Result:=OnBranchConditional1(node); @@ -751,6 +753,54 @@ begin Result:=Result+PrepTypeParam(node^.ParamNode(0),dst^.dtype); end; +function TEmitPostOp.OnLogicalNot1(node:PSpirvOp):Integer; +var + dtype:TsrDataType; + dst:PsrRegNode; + src:PsrRegNode; + + dst2:PsrRegNode; + srp:array[0..1] of PsrRegNode; + pop:PSpirvOp; + cmp:DWORD; + + procedure _SetReg(src:PsrRegNode); + begin + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; + Inc(Result); + end; + +begin + Result:=0; + dst:=node^.pDst^.AsType(ntReg); + src:=RegDown(node^.ParamNode(0)^.AsReg); + + if (dst=nil) or (src=nil) then Exit; + + if (src^.read_count>1) then Exit; + + pop:=src^.pWriter^.AsType(ntOp); + + if (pop=nil) then Exit; + + cmp:=pop^.OpId; + cmp:=get_inverse_not_cmp_op(cmp); + + if (cmp=0) then Exit; + + srp[0]:=pop^.ParamNode(0)^.AsReg; + srp[1]:=pop^.ParamNode(1)^.AsReg; + + if (srp[0]=nil) or (srp[1]=nil) then Exit; + + dst2:=NewReg(dtBool); + _Op2(pop,cmp,dst2,srp[0],srp[1]); + + _SetReg(dst2); +end; + function TEmitPostOp.OnBranchConditional1(node:PSpirvOp):Integer; var src,prv:PsrRegNode; diff --git a/spirv/srOpUtils.pas b/spirv/srOpUtils.pas index 251363fe..043d4b54 100644 --- a/spirv/srOpUtils.pas +++ b/spirv/srOpUtils.pas @@ -34,7 +34,8 @@ const OpCUBEMA =DWORD(-15); function InsSpirvOp(pLine,pNew:PspirvOp):PspirvOp; -Function get_inverse_cmp_op(OpId:DWORD):DWORD; +Function get_inverse_left_cmp_op(OpId:DWORD):DWORD; +Function get_inverse_not_cmp_op(OpId:DWORD):DWORD; Function is_term_op(OpId:DWORD):Boolean; Function is_merge_op(OpId:DWORD):Boolean; Function is_term_op(pLine:PspirvOp):Boolean; @@ -295,7 +296,7 @@ begin end; end; -Function get_inverse_cmp_op(OpId:DWORD):DWORD; +Function get_inverse_left_cmp_op(OpId:DWORD):DWORD; begin Result:=0; Case OpId of @@ -314,19 +315,54 @@ begin Op.OpFUnordNotEqual :Result:=Op.OpFUnordNotEqual ; Op.OpFUnordGreaterThanEqual:Result:=Op.OpFUnordLessThanEqual ; - Op.OpSLessThan :Result:=Op.OpSGreaterThan ; Op.OpIEqual :Result:=Op.OpIEqual ; + Op.OpINotEqual :Result:=Op.OpINotEqual ; + + Op.OpSLessThan :Result:=Op.OpSGreaterThan ; Op.OpSLessThanEqual :Result:=Op.OpSGreaterThanEqual ; Op.OpSGreaterThan :Result:=Op.OpSLessThan ; - Op.OpINotEqual :Result:=Op.OpINotEqual ; Op.OpSGreaterThanEqual :Result:=Op.OpSLessThanEqual ; Op.OpULessThan :Result:=Op.OpUGreaterThan ; Op.OpULessThanEqual :Result:=Op.OpUGreaterThanEqual ; Op.OpUGreaterThan :Result:=Op.OpULessThan ; Op.OpUGreaterThanEqual :Result:=Op.OpULessThanEqual ; - else - Assert(false); + else; + end; +end; + +Function get_inverse_not_cmp_op(OpId:DWORD):DWORD; +begin + Result:=0; + Case OpId of + Op.OpFOrdLessThan :Result:=Op.OpFUnordGreaterThanEqual; + Op.OpFOrdEqual :Result:=Op.OpFUnordNotEqual; + Op.OpFOrdLessThanEqual :Result:=Op.OpFUnordGreaterThan; + Op.OpFOrdGreaterThan :Result:=Op.OpFUnordLessThanEqual; + Op.OpFOrdNotEqual :Result:=Op.OpFUnordEqual; + Op.OpFOrdGreaterThanEqual :Result:=Op.OpFUnordLessThan; + Op.OpOrdered :Result:=Op.OpUnordered; + Op.OpUnordered :Result:=Op.OpOrdered; + Op.OpFUnordLessThan :Result:=Op.OpFOrdGreaterThanEqual; + Op.OpFUnordEqual :Result:=Op.OpFOrdNotEqual; + Op.OpFUnordLessThanEqual :Result:=Op.OpFOrdGreaterThan; + Op.OpFUnordGreaterThan :Result:=Op.OpFOrdLessThanEqual; + Op.OpFUnordNotEqual :Result:=Op.OpFOrdEqual; + Op.OpFUnordGreaterThanEqual:Result:=Op.OpFOrdLessThan; + + Op.OpIEqual :Result:=Op.OpINotEqual; + Op.OpINotEqual :Result:=Op.OpIEqual; + + Op.OpSLessThan :Result:=Op.OpSGreaterThanEqual; + Op.OpSLessThanEqual :Result:=Op.OpSGreaterThan; + Op.OpSGreaterThan :Result:=Op.OpSLessThanEqual; + Op.OpSGreaterThanEqual :Result:=Op.OpSLessThan; + + Op.OpULessThan :Result:=Op.OpUGreaterThanEqual; + Op.OpULessThanEqual :Result:=Op.OpUGreaterThan; + Op.OpUGreaterThan :Result:=Op.OpULessThanEqual; + Op.OpUGreaterThanEqual :Result:=Op.OpULessThan; + else; end; end;