Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3216,12 +3216,16 @@ INSTR.LINALGMATRIXDIMKVECKMISMATCH %0 vector size '%1' must b
INSTR.LINALGMATRIXDIMVECTORMISMATCH %0 vector size '%1' must match input matrix M dimension '%2'
INSTR.LINALGMATRIXLAYOUTREQSTRIDE %0 with layout '%1' requires stride 0.
INSTR.LINALGMATRIXLOADTHREADREQUIRESBAB Loading matrix with Thread scope requires ByteAddressBuffer.
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.
INSTR.LINALGMATRIXSCOPEMISMATCH2 %0 matrix scope '%1' does not match expected scope %2 or %3.
INSTR.LINALGMATRIXSCOPEMUSTMATCH3 Matrix scope must be the same for all matrices. %0 '%1', %2 '%3', %4 '%5'.
INSTR.LINALGMATRIXSCOPEMUSTMATCH4 Matrix scope must be the same for all matrices. %0 '%1', %2 '%3', %4 '%5', %6 '%7'.
INSTR.LINALGMATRIXSCOPEREQLAYOUT2 %0 matrix with scope '%1' requires layout %2 or %3 for %4.
INSTR.LINALGMATRIXUNSIGNEDFLOATTYPENOTALLOWED Float-like type '%0' must be signed
INSTR.LINALGMATRIXUSEMISMATCH %0 matrix use '%1' does not match expected use %2.
Expand Down
186 changes: 186 additions & 0 deletions lib/DxilValidation/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1451,12 +1451,198 @@ static void ValidateLinAlgMatrixMultiply(CallInst *CI,
ValidationContext &ValCtx) {
ValidateLinAlgOpReturnMatrix(CI, ValCtx);
ValidateLinAlgOpParameters(CI, ValCtx);
DxilInst_LinAlgMatrixMultiply Op(CI);
std::optional<LinAlgTargetType> RetMat =
GetCheckedLATT(CI->getType(), ValCtx);
if (!RetMat)
return;
std::optional<LinAlgTargetType> AMat =
GetCheckedLATT(Op.get_matrixA()->getType(), ValCtx);
Comment thread
joaosaffran marked this conversation as resolved.
if (!AMat)
return;
std::optional<LinAlgTargetType> BMat =
GetCheckedLATT(Op.get_matrixB()->getType(), ValCtx);
if (!BMat)
return;

// A is an A matrix
if (AMat->Use != DXIL::MatrixUse::A)
ValCtx.EmitInstrFormatError(CI,
ValidationRule::InstrLinAlgMatrixUseMismatch,
{"A", MatrixUseToString(AMat->Use), "A"});

// B is a B matrix
if (BMat->Use != DXIL::MatrixUse::B)
ValCtx.EmitInstrFormatError(CI,
ValidationRule::InstrLinAlgMatrixUseMismatch,
{"B", MatrixUseToString(BMat->Use), "B"});

// Ret is an Accumulator matrix
if (RetMat->Use != DXIL::MatrixUse::Accumulator)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixUseMismatch,
{"Return", MatrixUseToString(RetMat->Use), "Accumulator"});

// A scope must be Wave or ThreadGroup
if (AMat->Scope != DXIL::MatrixScope::Wave &&
AMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"A", MatrixScopeToString(AMat->Scope), "Wave", "ThreadGroup"});

// B scope must be Wave or ThreadGroup
if (BMat->Scope != DXIL::MatrixScope::Wave &&
BMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"B", MatrixScopeToString(BMat->Scope), "Wave", "ThreadGroup"});

// Ret scope must be Wave or ThreadGroup
if (RetMat->Scope != DXIL::MatrixScope::Wave &&
RetMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"Return", MatrixScopeToString(RetMat->Scope), "Wave", "ThreadGroup"});

// A, B, Ret scope must all be the same
if (AMat->Scope != BMat->Scope || BMat->Scope != RetMat->Scope)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMustMatch3,
{"A", MatrixScopeToString(AMat->Scope), "B",
MatrixScopeToString(BMat->Scope), "Return",
MatrixScopeToString(RetMat->Scope)});

unsigned M = AMat->M;
unsigned AK = AMat->N;
unsigned BK = BMat->M;
unsigned N = BMat->N;

// K dim must match between A and B
if (AK != BK)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixMatrixKDimMustMatch,
{std::to_string(M) + "x" + std::to_string(AK),
std::to_string(BK) + "x" + std::to_string(N), std::to_string(AK),
std::to_string(BK)});

// Return dim must match A.M x B.N
if (RetMat->M != M || RetMat->N != N)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixMatrixResDimMustMatch,
{"Return", std::to_string(RetMat->M) + "x" + std::to_string(RetMat->N),
std::to_string(M) + "x" + std::to_string(N)});
}

static void ValidateLinAlgMatrixMultiplyAccumulate(CallInst *CI,
ValidationContext &ValCtx) {
ValidateLinAlgOpReturnMatrix(CI, ValCtx);
ValidateLinAlgOpParameters(CI, ValCtx);
DxilInst_LinAlgMatrixMultiplyAccumulate Op(CI);
std::optional<LinAlgTargetType> RetMat =
GetCheckedLATT(CI->getType(), ValCtx);
if (!RetMat)
return;
std::optional<LinAlgTargetType> AMat =
GetCheckedLATT(Op.get_matrixA()->getType(), ValCtx);
if (!AMat)
return;
std::optional<LinAlgTargetType> BMat =
GetCheckedLATT(Op.get_matrixB()->getType(), ValCtx);
if (!BMat)
return;
std::optional<LinAlgTargetType> CMat =
GetCheckedLATT(Op.get_matrixC()->getType(), ValCtx);
if (!CMat)
return;

// A is an A matrix
if (AMat->Use != DXIL::MatrixUse::A)
ValCtx.EmitInstrFormatError(CI,
ValidationRule::InstrLinAlgMatrixUseMismatch,
{"A", MatrixUseToString(AMat->Use), "A"});

// B is a B matrix
if (BMat->Use != DXIL::MatrixUse::B)
ValCtx.EmitInstrFormatError(CI,
ValidationRule::InstrLinAlgMatrixUseMismatch,
{"B", MatrixUseToString(BMat->Use), "B"});

// C is an Accumulator matrix
if (CMat->Use != DXIL::MatrixUse::Accumulator)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixUseMismatch,
{"C", MatrixUseToString(CMat->Use), "Accumulator"});

// Ret is an Accumulator matrix
if (RetMat->Use != DXIL::MatrixUse::Accumulator)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixUseMismatch,
{"Return", MatrixUseToString(RetMat->Use), "Accumulator"});

// A scope must be Wave or ThreadGroup
if (AMat->Scope != DXIL::MatrixScope::Wave &&
AMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"A", MatrixScopeToString(AMat->Scope), "Wave", "ThreadGroup"});

// B scope must be Wave or ThreadGroup
if (BMat->Scope != DXIL::MatrixScope::Wave &&
BMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"B", MatrixScopeToString(BMat->Scope), "Wave", "ThreadGroup"});

// C scope must be Wave or ThreadGroup
if (CMat->Scope != DXIL::MatrixScope::Wave &&
CMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"C", MatrixScopeToString(CMat->Scope), "Wave", "ThreadGroup"});

// Ret scope must be Wave or ThreadGroup
if (RetMat->Scope != DXIL::MatrixScope::Wave &&
RetMat->Scope != DXIL::MatrixScope::ThreadGroup)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMismatch2,
{"Return", MatrixScopeToString(RetMat->Scope), "Wave", "ThreadGroup"});

// A, B, C, Ret scope must all be the same
if (AMat->Scope != BMat->Scope || BMat->Scope != CMat->Scope ||
CMat->Scope != RetMat->Scope)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixScopeMustMatch4,
{"A", MatrixScopeToString(AMat->Scope), "B",
MatrixScopeToString(BMat->Scope), "C",
MatrixScopeToString(CMat->Scope), "Return",
MatrixScopeToString(RetMat->Scope)});

unsigned M = AMat->M;
unsigned AK = AMat->N;
unsigned BK = BMat->M;
unsigned N = BMat->N;

// K dim must match between A and B
if (AK != BK)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixMatrixKDimMustMatch,
{std::to_string(M) + "x" + std::to_string(AK),
std::to_string(BK) + "x" + std::to_string(N), std::to_string(AK),
std::to_string(BK)});

// C dim must match A.M x B.N
if (CMat->M != M || CMat->N != N)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixMatrixResDimMustMatch,
{"C", std::to_string(CMat->M) + "x" + std::to_string(CMat->N),
std::to_string(M) + "x" + std::to_string(N)});

// Return dim must match A.M x B.N
if (RetMat->M != M || RetMat->N != N)
ValCtx.EmitInstrFormatError(
CI, ValidationRule::InstrLinAlgMatrixMatrixResDimMustMatch,
{"Return", std::to_string(RetMat->M) + "x" + std::to_string(RetMat->N),
std::to_string(M) + "x" + std::to_string(N)});
}

static void ValidateLinAlgMatrixOuterProduct(CallInst *CI,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@
void main() {
// CHECK-LABEL: define void @main()

// CHECK: call %dx.types.LinAlgMatrixC4M5N4U1S2 @dx.op.linAlgMatrixMultiply.mC4M5N4U1S2.mC4M5N4U1S2.mC4M5N4U1S2(i32 -2147483625,
// CHECK-SAME: %dx.types.LinAlgMatrixC4M5N4U1S2 %{{.*}}, %dx.types.LinAlgMatrixC4M5N4U1S2 %{{.*}}) ; LinAlgMatrixMultiply(matrixA,matrixB)
// Matrix<I32, 8, 4, A, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 8, 4, 0, 2)]] matA;
// Matrix<I32, 4, 8, B, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 4, 8, 1, 2)]] matB;
// Matrix<I32, 8, 8, Acc, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 8, 8, 2, 2)]] matC;

// CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC4M5N4U1S2*, %dx.types.LinAlgMatrixC4M5N4U1S2,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M5N4U1S2)"(i32 412, %dx.types.LinAlgMatrixC4M5N4U1S2* %mat2,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M5N4U1S2 %{{[0-9]+}}, %dx.types.LinAlgMatrixC4M5N4U1S2 %{{[0-9]+}})
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 5, 4, 1, 2)]] mat1;
__builtin_LinAlg_FillMatrix(mat1, 1);
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 5, 4, 1, 2)]] mat2;
__builtin_LinAlg_MatrixMatrixMultiply(mat2, mat1, mat1);
__builtin_LinAlg_FillMatrix(matA, 1);
__builtin_LinAlg_FillMatrix(matB, 2);

// CHECK: call %dx.types.LinAlgMatrixC4M8N8U2S2 @dx.op.linAlgMatrixMultiply.mC4M8N8U2S2.mC4M8N4U0S2.mC4M4N8U1S2(i32 -2147483625,
// CHECK-SAME: %dx.types.LinAlgMatrixC4M8N4U0S2 %{{.*}}, %dx.types.LinAlgMatrixC4M4N8U1S2 %{{.*}}) ; LinAlgMatrixMultiply(matrixA,matrixB)

// CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC4M8N8U2S2*, %dx.types.LinAlgMatrixC4M8N4U0S2,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M4N8U1S2)"(i32 412, %dx.types.LinAlgMatrixC4M8N8U2S2* %matC,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M8N4U0S2 %{{[0-9]+}}, %dx.types.LinAlgMatrixC4M4N8U1S2 %{{[0-9]+}})

__builtin_LinAlg_MatrixMatrixMultiply(matC, matA, matB);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,28 @@ void main() {
// CHECK: ; LinAlgFillMatrix(value)
// CHECK: ; LinAlgFillMatrix(value)

// CHECK: call %dx.types.LinAlgMatrixC4M5N3U1S2
// CHECK-SAME: @dx.op.linAlgMatrixMultiplyAccumulate.mC4M5N3U1S2.mC4M5N4U1S2.mC4M4N3U1S2.mC4M5N3U1S2
// CHECK-SAME: (i32 -2147483637, %dx.types.LinAlgMatrixC4M5N4U1S2 %{{[0-9]+}}, %dx.types.LinAlgMatrixC4M4N3U1S2 %{{[0-9]+}},
// CHECK-SAME: %dx.types.LinAlgMatrixC4M5N3U1S2 %{{[0-9]+}}) ; LinAlgMatrixMultiplyAccumulate(matrixA,matrixB,matrixC)
// Matrix<I32, 8, 4, A, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 8, 4, 0, 2)]] matA;
// Matrix<I32, 4, 8, B, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 4, 8, 1, 2)]] matB;
// Matrix<I32, 8, 8, Acc, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 8, 8, 2, 2)]] matC;
// Matrix<I32, 8, 8, Acc, ThreadGroup>
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 8, 8, 2, 2)]] matR;

// CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC4M5N3U1S2*, %dx.types.LinAlgMatrixC4M5N4U1S2,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M4N3U1S2, %dx.types.LinAlgMatrixC4M5N3U1S2)"(i32 413,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M5N3U1S2* %{{.*}}, %dx.types.LinAlgMatrixC4M5N4U1S2 %{{[0-9]+}},
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M4N3U1S2 %{{[0-9]+}}, %dx.types.LinAlgMatrixC4M5N3U1S2 %{{[0-9]+}})
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 5, 4, 1, 2)]] mat1;
__builtin_LinAlg_FillMatrix(mat1, 1);
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 4, 3, 1, 2)]] mat2;
__builtin_LinAlg_FillMatrix(mat2, 2);
__builtin_LinAlgMatrix [[__LinAlgMatrix_Attributes(4, 5, 3, 1, 2)]] mat3;
__builtin_LinAlg_FillMatrix(mat3, 3);
__builtin_LinAlg_MatrixMatrixMultiplyAccumulate(mat3, mat1, mat2, mat3);
__builtin_LinAlg_FillMatrix(matA, 1);
__builtin_LinAlg_FillMatrix(matB, 2);
__builtin_LinAlg_FillMatrix(matC, 3);

// CHECK: call %dx.types.LinAlgMatrixC4M8N8U2S2
// CHECK-SAME: @dx.op.linAlgMatrixMultiplyAccumulate.mC4M8N8U2S2.mC4M8N4U0S2.mC4M4N8U1S2.mC4M8N8U2S2
// CHECK-SAME: (i32 -2147483637, %dx.types.LinAlgMatrixC4M8N4U0S2 %{{[0-9]+}}, %dx.types.LinAlgMatrixC4M4N8U1S2 %{{[0-9]+}},
// CHECK-SAME: %dx.types.LinAlgMatrixC4M8N8U2S2 %{{[0-9]+}}) ; LinAlgMatrixMultiplyAccumulate(matrixA,matrixB,matrixC)

// CHECK2: call void @"dx.hl.op..void (i32, %dx.types.LinAlgMatrixC4M8N8U2S2*, %dx.types.LinAlgMatrixC4M8N4U0S2,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M4N8U1S2, %dx.types.LinAlgMatrixC4M8N8U2S2)"(i32 413,
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M8N8U2S2* %{{.*}}, %dx.types.LinAlgMatrixC4M8N4U0S2 %{{[0-9]+}},
// CHECK2-SAME: %dx.types.LinAlgMatrixC4M4N8U1S2 %{{[0-9]+}}, %dx.types.LinAlgMatrixC4M8N8U2S2 %{{[0-9]+}})

__builtin_LinAlg_MatrixMatrixMultiplyAccumulate(matR, matA, matB, matC);
}
Loading
Loading