From b8b639b7dc5766cdc0cd715dcaee7d19ca40acb5 Mon Sep 17 00:00:00 2001 From: Ashley Coleman Date: Tue, 7 Jul 2026 18:05:49 -0600 Subject: [PATCH] [SM6.10] LinAlg Validation: Restrict Matrix to Allowed Component Types --- docs/DXIL.rst | 1 + lib/DxilValidation/DxilValidation.cpp | 23 ++++++++ lib/DxilValidation/DxilValidationUtils.cpp | 53 ++++++++++++++++++ lib/DxilValidation/DxilValidationUtils.h | 2 + .../matrixloadfromdescriptor/nominal.hlsl | 8 +-- .../matrixvectormultiplyadd/nominal.hlsl | 10 ++-- .../linalgmatrix-illegal-component-type.ll | 56 +++++++++++++++++++ utils/hct/hctdb.py | 4 ++ 8 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-illegal-component-type.ll diff --git a/docs/DXIL.rst b/docs/DXIL.rst index ff8e4ec3d4..097c6c2e9f 100644 --- a/docs/DXIL.rst +++ b/docs/DXIL.rst @@ -3209,6 +3209,7 @@ INSTR.ILLEGALDXILOPCODE DXILOpCode must be valid o INSTR.ILLEGALDXILOPFUNCTION '%0' is not a DXILOpFuncition for DXILOpcode '%1'. INSTR.IMMBIASFORSAMPLEB bias amount for sample_b must be in the range [%0,%1], but %2 was specified as an immediate. INSTR.INBOUNDSACCESS Access to out-of-bounds memory is disallowed. +INSTR.LINALGILLEGALCOMPONENTTYPE Matrix Component Type '%0' not allowed in LinAlg Matrix. INSTR.LINALGILLEGALKDIM Matrix K Dimension out of bounds. K=%0 must be >= %1 and <= %2. 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 fa593c3fab..89cfef14a5 100644 --- a/lib/DxilValidation/DxilValidation.cpp +++ b/lib/DxilValidation/DxilValidation.cpp @@ -1024,6 +1024,29 @@ static void ValidateLinAlgOpReturnMatrix(CallInst *CI, CI, ValidationRule::InstrLinAlgIllegalKDim, {std::to_string(K), std::to_string(MinK), std::to_string(MaxK)}); } + + // Validate the ComponentType is allowed + switch (LATT.Type) { + case DXIL::ComponentType::I8: + case DXIL::ComponentType::I16: + case DXIL::ComponentType::I32: + case DXIL::ComponentType::I64: + case DXIL::ComponentType::U8: + case DXIL::ComponentType::U16: + case DXIL::ComponentType::U32: + case DXIL::ComponentType::U64: + case DXIL::ComponentType::F8_E4M3FN: + case DXIL::ComponentType::F8_E5M2: + case DXIL::ComponentType::F16: + case DXIL::ComponentType::F32: + case DXIL::ComponentType::F64: + break; + default: + ValCtx.EmitInstrFormatError(CI, + ValidationRule::InstrLinAlgIllegalComponentType, + {ComponentTypeToString(LATT.Type)}); + break; + } } // Validate the type-defined mask compared to the store value mask which diff --git a/lib/DxilValidation/DxilValidationUtils.cpp b/lib/DxilValidation/DxilValidationUtils.cpp index 06ad9092f7..e8d7c6c0ab 100644 --- a/lib/DxilValidation/DxilValidationUtils.cpp +++ b/lib/DxilValidation/DxilValidationUtils.cpp @@ -616,4 +616,57 @@ void ValidationContext::EmitFnAttributeError(Function *F, StringRef Kind, {F->getName(), Kind, Value}); } +llvm::StringRef ComponentTypeToString(DXIL::ComponentType CT) { + switch (CT) { + case DXIL::ComponentType::Invalid: + return "Invalid"; + case DXIL::ComponentType::I1: + return "I1"; + case DXIL::ComponentType::I16: + return "I16"; + case DXIL::ComponentType::U16: + return "U16"; + case DXIL::ComponentType::I32: + return "I32"; + case DXIL::ComponentType::U32: + return "U32"; + case DXIL::ComponentType::I64: + return "I64"; + case DXIL::ComponentType::U64: + return "U64"; + case DXIL::ComponentType::F16: + return "F16"; + case DXIL::ComponentType::F32: + return "F32"; + case DXIL::ComponentType::F64: + return "F64"; + case DXIL::ComponentType::SNormF16: + return "SNormF16"; + case DXIL::ComponentType::UNormF16: + return "UNormF16"; + case DXIL::ComponentType::SNormF32: + return "SNormF32"; + case DXIL::ComponentType::UNormF32: + return "UNormF32"; + case DXIL::ComponentType::SNormF64: + return "SNormF64"; + case DXIL::ComponentType::UNormF64: + return "UNormF64"; + case DXIL::ComponentType::PackedS8x32: + return "PackedS8x32"; + case DXIL::ComponentType::PackedU8x32: + return "PackedU8x32"; + case DXIL::ComponentType::I8: + return "I8"; + case DXIL::ComponentType::U8: + return "U8"; + case DXIL::ComponentType::F8_E4M3FN: + return "F8_E4M3FN"; + case DXIL::ComponentType::F8_E5M2: + return "F8_E5M2"; + default: + return "Unknown ComponentType"; + } +} + } // namespace hlsl diff --git a/lib/DxilValidation/DxilValidationUtils.h b/lib/DxilValidation/DxilValidationUtils.h index a16b7a66da..5446a336c3 100644 --- a/lib/DxilValidation/DxilValidationUtils.h +++ b/lib/DxilValidation/DxilValidationUtils.h @@ -155,4 +155,6 @@ struct ValidationContext { }; uint32_t ValidateDxilModule(llvm::Module *pModule, llvm::Module *pDebugModule); + +llvm::StringRef ComponentTypeToString(DXIL::ComponentType CT); } // namespace hlsl diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixloadfromdescriptor/nominal.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixloadfromdescriptor/nominal.hlsl index ed14e3d324..b584fdeb81 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixloadfromdescriptor/nominal.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixloadfromdescriptor/nominal.hlsl @@ -8,12 +8,12 @@ ByteAddressBuffer inbuf; void main() { // CHECK-LABEL: define void @main() - // CHECK: %{{.*}} = call %dx.types.LinAlgMatrixC1M4N4U0S0 @dx.op.linAlgMatrixLoadFromDescriptor.mC1M4N4U0S0 + // CHECK: %{{.*}} = call %dx.types.LinAlgMatrixC2M4N4U0S0 @dx.op.linAlgMatrixLoadFromDescriptor.mC2M4N4U0S0 // CHECK-SAME: (i32 -2147483634, %dx.types.Handle %{{.*}}, i32 0, i32 0, i32 0, i32 4) // CHECK-SAME: ; LinAlgMatrixLoadFromDescriptor(handle,offset,stride,layout,align) - // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC1M4N4U0S0*, %dx.types.Handle, i32, i32, i32, i32) - // CHECK2-SAME: "(i32 406, %dx.types.LinAlgMatrixC1M4N4U0S0* %mat, %dx.types.Handle {{.*}}, i32 0, i32 0, i32 0, i32 4) - __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(1, 4, 4, 0, 0)]] mat; + // CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC2M4N4U0S0*, %dx.types.Handle, i32, i32, i32, i32) + // CHECK2-SAME: "(i32 406, %dx.types.LinAlgMatrixC2M4N4U0S0* %mat, %dx.types.Handle {{.*}}, i32 0, i32 0, i32 0, i32 4) + __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(2, 4, 4, 0, 0)]] mat; __builtin_LinAlg_MatrixLoadFromDescriptor(mat, inbuf, 0, 0, 0, 4); } diff --git a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl index b0d298bb49..016c4ae7e5 100644 --- a/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl +++ b/tools/clang/test/CodeGenDXIL/hlsl/linalg/builtins/matrixvectormultiplyadd/nominal.hlsl @@ -53,18 +53,18 @@ void main() { __builtin_LinAlg_MatrixVectorMultiplyAdd(result3, mat3, true, vec3, 1, result3, 0); - __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(17, 8, 8, 0, 0)]] mat4; + __builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 8, 8, 0, 0)]] mat4; __builtin_LinAlg_FillMatrix(mat4, 4); vector vec4 = 0; vector result4 = 0; - // CHECK: call <8 x i32> @dx.op.linAlgMatVecMulAdd.v8i32.mC17M8N8U0S0.v8i32.v8i32(i32 -2147483622, - // CHECK-SAME: %dx.types.LinAlgMatrixC17M8N8U0S0 %{{.*}}, i1 true, <8 x i32> zeroinitializer, + // CHECK: call <8 x i32> @dx.op.linAlgMatVecMulAdd.v8i32.mC4M8N8U0S0.v8i32.v8i32(i32 -2147483622, + // CHECK-SAME: %dx.types.LinAlgMatrixC4M8N8U0S0 %{{.*}}, i1 true, <8 x i32> zeroinitializer, // CHECK-SAME: i32 1, <8 x i32> zeroinitializer, i32 0) // CHECK-SAME: ; LinAlgMatVecMulAdd(matrix,isOutputSigned,inputVector,inputInterpretation,biasVector,biasInterpretation) - // CHECK2: call void @"dx.hl.op..void (i32, <8 x i32>*, %dx.types.LinAlgMatrixC17M8N8U0S0, i1, <8 x i32>, - // CHECK2-SAME: i32, <8 x i32>, i32)"(i32 419, <8 x i32>* %result4, %dx.types.LinAlgMatrixC17M8N8U0S0 %{{[0-9]+}}, + // CHECK2: call void @"dx.hl.op..void (i32, <8 x i32>*, %dx.types.LinAlgMatrixC4M8N8U0S0, i1, <8 x i32>, + // CHECK2-SAME: i32, <8 x i32>, i32)"(i32 419, <8 x i32>* %result4, %dx.types.LinAlgMatrixC4M8N8U0S0 %{{[0-9]+}}, // CHECK2-SAME: i1 true, <8 x i32> %{{[0-9]+}}, i32 1, <8 x i32> %{{[0-9]+}}, i32 0) __builtin_LinAlg_MatrixVectorMultiplyAdd(result4, mat4, true, vec4, 1, result4, 0); diff --git a/tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-illegal-component-type.ll b/tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-illegal-component-type.ll new file mode 100644 index 0000000000..89e1510d9d --- /dev/null +++ b/tools/clang/test/LitDXILValidation/LinAlgMatrix/linalgmatrix-illegal-component-type.ll @@ -0,0 +1,56 @@ +; REQUIRES: dxil-1-10 +; RUN: not %dxv %s 2>&1 | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.ResBind = type { i32, i32, i32, i8 } +%dx.types.LinAlgMatrixC0M128N128U0S0 = type { i8* } +%dx.types.ResourceProperties = type { i32, i32 } +%struct.RWByteAddressBuffer = type { i32 } + +define void @main() { + %1 = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, %dx.types.ResBind { i32 0, i32 0, i32 0, i8 1 }, i32 0, i1 false) ; CreateHandleFromBinding(bind,index,nonUniformIndex) + %handle = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle %1, %dx.types.ResourceProperties { i32 4107, i32 0 }) ; AnnotateHandle(res,props) resource: RWByteAddressBuffer + + ; CHECK: Function: main: error: Matrix Component Type 'Invalid' not allowed in LinAlg Matrix. + ; CHECK-NEXT: note: at '%mC0M128N128U0S0 + ; Matrix + %mC0M128N128U0S0 = call %dx.types.LinAlgMatrixC0M128N128U0S0 @dx.op.linAlgMatrixLoadFromDescriptor.mC0M128N128U0S0(i32 -2147483634, %dx.types.Handle %handle, i32 0, i32 0, i32 0, i32 0) + + ; CHECK-NEXT: Validation failed. + + ret void +} + +; Function Attrs: nounwind +declare %dx.types.LinAlgMatrixC0M128N128U0S0 @dx.op.linAlgMatrixLoadFromDescriptor.mC0M128N128U0S0(i32, %dx.types.Handle, i32, i32, i32, i32) #0 + +; Function Attrs: nounwind readnone +declare %dx.types.Handle @dx.op.annotateHandle(i32, %dx.types.Handle, %dx.types.ResourceProperties) #1 + +; Function Attrs: nounwind readnone +declare %dx.types.Handle @dx.op.createHandleFromBinding(i32, %dx.types.ResBind, i32, i1) #1 + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } + +!dx.targetTypes = !{!26} +!llvm.ident = !{!17} +!dx.version = !{!18} +!dx.valver = !{!18} +!dx.shaderModel = !{!19} +!dx.resources = !{!20} +!dx.entryPoints = !{!23} + +!17 = !{!"dxc(private) 1.9.0.15241 (main, 1f63535ae)"} +!18 = !{i32 1, i32 10} +!19 = !{!"cs", i32 6, i32 10} +!20 = !{null, !21, null, null} +!21 = !{!22} +!22 = !{i32 0, %struct.RWByteAddressBuffer* undef, !"", i32 0, i32 0, i32 1, i32 11, i1 false, i1 false, i1 false, null} +!23 = !{void ()* @main, !"main", null, !20, !24} +!24 = !{i32 0, i64 8589934608, i32 4, !25} +!25 = !{i32 4, i32 4, i32 4} +!26 = !{%dx.types.LinAlgMatrixC0M128N128U0S0 undef, i32 0, i32 128, i32 128, i32 0, i32 0} diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py index d12886c777..ba05825a69 100644 --- a/utils/hct/hctdb.py +++ b/utils/hct/hctdb.py @@ -8640,6 +8640,10 @@ def build_valrules(self): "Instr.LinAlgIllegalKDim", "Matrix K Dimension out of bounds. K=%0 must be >= %1 and <= %2.", ) + self.add_valrule( + "Instr.LinAlgIllegalComponentType", + "Matrix Component Type '%0' not allowed in LinAlg Matrix.", + ) # Some legacy rules: # - space is only supported for shader targets 5.1 and higher