diff --git a/docs/DXIL.rst b/docs/DXIL.rst index ba0de6e739..74acdd51fa 100644 --- a/docs/DXIL.rst +++ b/docs/DXIL.rst @@ -3219,7 +3219,6 @@ INSTR.LINALGMATRIXLOADTHREADREQUIRESBAB Loading matrix with Thread INSTR.LINALGMATRIXMATRIXKDIMMUSTMATCH K dim of A matrix '%0' must match K dim of B matrix '%1'. %2 != %3. INSTR.LINALGMATRIXMATRIXRESDIMMUSTMATCH %0 matrix dimension '%1' must match A.MxB.N '%2'. INSTR.LINALGMATRIXNOTEXACTMATCH %0 matrix '%1' must exactly match %2 matrix '%3'. -INSTR.LINALGMATRIXOUTPUTBIASVECMISMATCH Output vector element type '%0' must match bias vector element type '%1' INSTR.LINALGMATRIXREQUIRESLAYOUT2 %0 requires layout %1 or %2. INSTR.LINALGMATRIXREQUIRESRWBAB %0 requires RWByteAddressBuffer. INSTR.LINALGMATRIXSCOPEMISMATCH %0 matrix scope '%1' does not match expected scope %2. @@ -3230,6 +3229,7 @@ INSTR.LINALGMATRIXSCOPEREQLAYOUT2 %0 matrix with scope '%1' INSTR.LINALGMATRIXUNSIGNEDFLOATTYPENOTALLOWED Float-like type '%0' must be signed INSTR.LINALGMATRIXUSEMISMATCH %0 matrix use '%1' does not match expected use %2. INSTR.LINALGMATRIXUSEMISMATCH2 %0 matrix use '%1' does not match expected use %2 or %3. +INSTR.LINALGMATRIXVECELEMENTTYPEMISMATCH %0 vector element type '%1' must match %2 vector element type '%3' INSTR.LINALGMETADATAMISSING %0 matrix must have well-formed metadata. INSTR.MAYREORDERTHREADUNDEFCOHERENCEHINTPARAM Use of undef coherence hint or num coherence hint bits in MaybeReorderThread. INSTR.MINPRECISIONNOTPRECISE Instructions marked precise may not refer to minprecision values. diff --git a/lib/DxilValidation/DxilValidation.cpp b/lib/DxilValidation/DxilValidation.cpp index ee047af974..3ae2446132 100644 --- a/lib/DxilValidation/DxilValidation.cpp +++ b/lib/DxilValidation/DxilValidation.cpp @@ -1311,8 +1311,8 @@ static void ValidateLinAlgMatVecMulAdd(CallInst *CI, // Bias element type must match output element type if (BiasVecTy->getElementType() != OutputVecTy->getElementType()) ValCtx.EmitInstrFormatError( - CI, ValidationRule::InstrLinAlgMatrixOutputBiasVecMismatch, - {TypeToString(OutputVecTy->getElementType()), + CI, ValidationRule::InstrLinAlgMatrixVecElementTypeMismatch, + {"Output", TypeToString(OutputVecTy->getElementType()), "bias", TypeToString(BiasVecTy->getElementType())}); } @@ -1660,6 +1660,46 @@ static void ValidateLinAlgMatrixOuterProduct(CallInst *CI, ValidationContext &ValCtx) { ValidateLinAlgOpReturnMatrix(CI, ValCtx); ValidateLinAlgOpParameters(CI, ValCtx); + DxilInst_LinAlgMatrixOuterProduct Op(CI); + VectorType *AVecTy = cast(Op.get_vectorA()->getType()); + VectorType *BVecTy = cast(Op.get_vectorB()->getType()); + std::optional RetMat = + GetCheckedLATT(CI->getType(), ValCtx); + if (!RetMat) + return; + + // Matrix must be thread scope + if (RetMat->Scope != DXIL::MatrixScope::Thread) + ValCtx.EmitInstrFormatError( + CI, ValidationRule::InstrLinAlgMatrixScopeMismatch, + {"Return", MatrixScopeToString(RetMat->Scope), "Thread"}); + + // Matrix must be accumulator use + if (RetMat->Use != DXIL::MatrixUse::Accumulator) + ValCtx.EmitInstrFormatError( + CI, ValidationRule::InstrLinAlgMatrixUseMismatch, + {"Return", MatrixUseToString(RetMat->Use), "Accumulator"}); + + // M dim must be length of vecA + unsigned M = AVecTy->getNumElements(); + + // N dim must be length of vecB + unsigned N = BVecTy->getNumElements(); + + // Matrix must be M*N dim + if (RetMat->M != M || RetMat->N != N) + ValCtx.EmitInstrFormatError( + CI, ValidationRule::InstrLinAlgMatrix2PartsMustMatch, + {"Return", "dimension", + std::to_string(RetMat->M) + "x" + std::to_string(RetMat->N), "derived", + "dimension", std::to_string(M) + "x" + std::to_string(N)}); + + // element type of vecA and vecB must be the same + if (AVecTy->getElementType() != BVecTy->getElementType()) + ValCtx.EmitInstrFormatError( + CI, ValidationRule::InstrLinAlgMatrixVecElementTypeMismatch, + {"A", TypeToString(AVecTy->getElementType()), "B", + TypeToString(BVecTy->getElementType())}); } static void ValidateLinAlgMatrixLoadFromDescriptor(CallInst *CI, diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixouterproduct/nominal.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixouterproduct/nominal.hlsl index 8b478f2980..fa4a8530f7 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixouterproduct/nominal.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixouterproduct/nominal.hlsl @@ -9,33 +9,36 @@ void main() { float4 lhs1 = {1,2,3,4}; float4 rhs1 = {4,3,2,1}; - // CHECK: call %dx.types.LinAlgMatrixC2M2N2U2S2 @dx.op.linAlgMatrixOuterProduct.mC2M2N2U2S2.v4f32.v4f32 + // CHECK: call %dx.types.LinAlgMatrixC9M4N4U2S0 @dx.op.linAlgMatrixOuterProduct.mC9M4N4U2S0.v4f32.v4f32 // CHECK-SAME: (i32 -2147483619, <4 x float> {{.*}}, <4 x float> {{.*}}) ; LinAlgMatrixOuterProduct(vectorA,vectorB) - // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC2M2N2U2S2*, <4 x float>, <4 x float>)" - // CHECK2: (i32 417, %dx.types.LinAlgMatrixC2M2N2U2S2* {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}}) - __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(2, 2, 2, 2, 2)]] mat1; + // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC9M4N4U2S0*, <4 x float>, <4 x float>)" + // CHECK2: (i32 417, %dx.types.LinAlgMatrixC9M4N4U2S0* {{.*}}, <4 x float> {{.*}}, <4 x float> {{.*}}) + // Matrix + __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(9, 4, 4, 2, 0)]] mat1; __builtin_LinAlg_MatrixOuterProduct(mat1, lhs1, rhs1); double4 lhs2 = {1,2,3,4}; double4 rhs2 = {4,3,2,1}; - // CHECK: call %dx.types.LinAlgMatrixC2M2N2U2S2 @dx.op.linAlgMatrixOuterProduct.mC2M2N2U2S2.v4f64.v4f64 + // CHECK: call %dx.types.LinAlgMatrixC10M4N4U2S0 @dx.op.linAlgMatrixOuterProduct.mC10M4N4U2S0.v4f64.v4f64 // CHECK-SAME: (i32 -2147483619, <4 x double> {{.*}}, <4 x double> {{.*}}) ; LinAlgMatrixOuterProduct(vectorA,vectorB) - // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC2M2N2U2S2*, <4 x double>, <4 x double>)" - // CHECK2: (i32 417, %dx.types.LinAlgMatrixC2M2N2U2S2* {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}) - __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(2, 2, 2, 2, 2)]] mat2; + // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC10M4N4U2S0*, <4 x double>, <4 x double>)" + // CHECK2: (i32 417, %dx.types.LinAlgMatrixC10M4N4U2S0* {{.*}}, <4 x double> {{.*}}, <4 x double> {{.*}}) + // Matrix + __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(10, 4, 4, 2, 0)]] mat2; __builtin_LinAlg_MatrixOuterProduct(mat2, lhs2, rhs2); vector lhs3 = {1,2,3,4}; vector rhs3 = {4,3,2,1}; - // CHECK: call %dx.types.LinAlgMatrixC2M2N2U2S2 @dx.op.linAlgMatrixOuterProduct.mC2M2N2U2S2.v4i64.v4i64 + // CHECK: call %dx.types.LinAlgMatrixC6M4N4U2S0 @dx.op.linAlgMatrixOuterProduct.mC6M4N4U2S0.v4i64.v4i64 // CHECK-SAME: (i32 -2147483619, <4 x i64> {{.*}}, <4 x i64> {{.*}}) ; LinAlgMatrixOuterProduct(vectorA,vectorB) - // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC2M2N2U2S2*, <4 x i64>, <4 x i64>)" - // CHECK2: (i32 417, %dx.types.LinAlgMatrixC2M2N2U2S2* {{.*}}, <4 x i64> {{.*}}, <4 x i64> {{.*}}) - __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(2, 2, 2, 2, 2)]] mat3; + // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC6M4N4U2S0*, <4 x i64>, <4 x i64>)" + // CHECK2: (i32 417, %dx.types.LinAlgMatrixC6M4N4U2S0* {{.*}}, <4 x i64> {{.*}}, <4 x i64> {{.*}}) + // Matrix + __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(6, 4, 4, 2, 0)]] mat3; __builtin_LinAlg_MatrixOuterProduct(mat3, lhs3, rhs3); } diff --git a/tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-outerproduct.ll b/tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-outerproduct.ll new file mode 100644 index 0000000000..a0b304eb6e --- /dev/null +++ b/tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-outerproduct.ll @@ -0,0 +1,92 @@ +; REQUIRES: dxil-1-10 +; RUN: not %dxv %s 2>&1 | FileCheck %s +target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.LinAlgMatrixC8M8N8U2S0 = type { i8* } +%dx.types.LinAlgMatrixC21M8N8U2S0 = type { i8* } +%dx.types.LinAlgMatrixC8M8N16U2S0 = type { i8* } +%dx.types.LinAlgMatrixC8M8N8U2S1 = type { i8* } +%dx.types.LinAlgMatrixC8M8N8U1S0 = type { i8* } +%dx.types.LinAlgMatrixC8M16N16U2S0 = type { i8* } + +define void @main() { + ; okay + %1 = call %dx.types.LinAlgMatrixC8M8N8U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S0.v8f16.v8f16(i32 -2147483619, <8 x half> , <8 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; okay + %2 = call %dx.types.LinAlgMatrixC21M8N8U2S0 @dx.op.linAlgMatrixOuterProduct.mC21M8N8U2S0.v8f16.v8f16(i32 -2147483619, <8 x half> , <8 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; okay + %3 = call %dx.types.LinAlgMatrixC8M8N16U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N16U2S0.v8f16.v16f16(i32 -2147483619, <8 x half> , <16 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; CHECK: Function: main: error: Return matrix scope 'Wave' does not match expected scope Thread. + ; CHECK-NEXT: note: at {{.*}} @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S1.v8f16.v8f16 + %4 = call %dx.types.LinAlgMatrixC8M8N8U2S1 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S1.v8f16.v8f16(i32 -2147483619, <8 x half> , <8 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; CHECK-NEXT: Function: main: error: Return matrix use 'B' does not match expected use Accumulator. + ; CHECK-NEXT: note: at {{.*}} @dx.op.linAlgMatrixOuterProduct.mC8M8N8U1S0.v8f16.v8f16 + %5 = call %dx.types.LinAlgMatrixC8M8N8U1S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U1S0.v8f16.v8f16(i32 -2147483619, <8 x half> , <8 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; CHECK-NEXT: Function: main: error: Return matrix dimension '16x16' must match derived matrix dimension '8x8'. + ; CHECK-NEXT: note: at {{.*}} @dx.op.linAlgMatrixOuterProduct.mC8M16N16U2S0.v8f16.v8f16 + %6 = call %dx.types.LinAlgMatrixC8M16N16U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M16N16U2S0.v8f16.v8f16(i32 -2147483619, <8 x half> , <8 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; CHECK-NEXT: Function: main: error: Return matrix dimension '8x16' must match derived matrix dimension '8x8'. + ; CHECK-NEXT: note: at {{.*}} @dx.op.linAlgMatrixOuterProduct.mC8M8N16U2S0.v8f16.v8f16 + %7 = call %dx.types.LinAlgMatrixC8M8N16U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N16U2S0.v8f16.v8f16(i32 -2147483619, <8 x half> , <8 x half> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; CHECK-NEXT: Function: main: error: A vector element type 'half' must match B vector element type 'i32' + ; CHECK-NEXT: note: at {{.*}} @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S0.v8f16.v8i32 + %8 = call %dx.types.LinAlgMatrixC8M8N8U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S0.v8f16.v8i32(i32 -2147483619, <8 x half> , <8 x i32> ) ; LinAlgMatrixOuterProduct(vectorA,vectorB) + + ; CHECK-NEXT: Validation failed. + ret void +} + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M8N8U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S0.v8f16.v8f16(i32, <8 x half>, <8 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC21M8N8U2S0 @dx.op.linAlgMatrixOuterProduct.mC21M8N8U2S0.v8f16.v8f16(i32, <8 x half>, <8 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M8N16U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N16U2S0.v8f16.v16f16(i32, <8 x half>, <16 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M8N8U2S1 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S1.v8f16.v8f16(i32, <8 x half>, <8 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M8N8U1S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U1S0.v8f16.v8f16(i32, <8 x half>, <8 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M16N16U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M16N16U2S0.v8f16.v8f16(i32, <8 x half>, <8 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M8N16U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N16U2S0.v8f16.v8f16(i32, <8 x half>, <8 x half>) #0 + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC8M8N8U2S0 @dx.op.linAlgMatrixOuterProduct.mC8M8N8U2S0.v8f16.v8i32(i32, <8 x half>, <8 x i32>) #0 + +attributes #0 = { nounwind } + +!dx.targetTypes = !{!0, !1, !2, !3, !4, !5} +!llvm.ident = !{!6} +!dx.version = !{!7} +!dx.valver = !{!7} +!dx.shaderModel = !{!8} +!dx.entryPoints = !{!9} + +!0 = !{%dx.types.LinAlgMatrixC8M8N8U2S0 undef, i32 8, i32 8, i32 8, i32 2, i32 0} +!1 = !{%dx.types.LinAlgMatrixC8M8N8U2S1 undef, i32 8, i32 8, i32 8, i32 2, i32 1} +!2 = !{%dx.types.LinAlgMatrixC8M8N8U1S0 undef, i32 8, i32 8, i32 8, i32 1, i32 0} +!3 = !{%dx.types.LinAlgMatrixC8M16N16U2S0 undef, i32 8, i32 16, i32 16, i32 2, i32 0} +!4 = !{%dx.types.LinAlgMatrixC21M8N8U2S0 undef, i32 21, i32 8, i32 8, i32 2, i32 0} +!5 = !{%dx.types.LinAlgMatrixC8M8N16U2S0 undef, i32 8, i32 8, i32 16, i32 2, i32 0} +!6 = !{!"dxc(private) 1.9.0.5463 (linalg-vali-convert, c401f722f)"} +!7 = !{i32 1, i32 10} +!8 = !{!"cs", i32 6, i32 10} +!9 = !{void ()* @main, !"main", null, null, !10} +!10 = !{i32 0, i64 8388608, i32 4, !11} +!11 = !{i32 1, i32 1, i32 1} + diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index 2597402dea..14a78ceaf8 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -8690,8 +8690,8 @@ def build_valrules(self): "%0 vector size '%1' must be %2 for input matrix with K '%3' and Type '%4'", ) self.add_valrule( - "Instr.LinAlgMatrixOutputBiasVecMismatch", - "Output vector element type '%0' must match bias vector element type '%1'", + "Instr.LinAlgMatrixVecElementTypeMismatch", + "%0 vector element type '%1' must match %2 vector element type '%3'", ) self.add_valrule( "Instr.LinAlgMatrixUnsignedFloatTypeNotAllowed",