aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2024-11-22 12:13:21 -0800
committerGitHub <noreply@github.com>2024-11-22 12:13:21 -0800
commita05a1d6eefe6bfb46d2e5ee6191a10cfefd64484 (patch)
tree92d7957f288d1d0bd4fd19f6892e5f9b116b453e /llvm/lib/IR/Verifier.cpp
parent7d544c64e3b6ea014c59e230dcf65ac4f9d60f2b (diff)
downloadllvm-a05a1d6eefe6bfb46d2e5ee6191a10cfefd64484.zip
llvm-a05a1d6eefe6bfb46d2e5ee6191a10cfefd64484.tar.gz
llvm-a05a1d6eefe6bfb46d2e5ee6191a10cfefd64484.tar.bz2
AMDGPU: Add basic verification for mfma scale intrinsics (#117048)
Verify the format is valid and the type is one of the expected i32 vectors. Verify the used vector types at least cover the requirements of the corresponding format operand.
Diffstat (limited to 'llvm/lib/IR/Verifier.cpp')
-rw-r--r--llvm/lib/IR/Verifier.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 6783463..55de486 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -6390,6 +6390,55 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
"llvm.amdgcn.s.prefetch.data only supports global or constant memory");
break;
}
+ case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:
+ case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {
+ Value *Src0 = Call.getArgOperand(0);
+ Value *Src1 = Call.getArgOperand(1);
+
+ uint64_t CBSZ = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue();
+ uint64_t BLGP = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue();
+ Check(CBSZ <= 4, "invalid value for cbsz format", Call,
+ Call.getArgOperand(3));
+ Check(BLGP <= 4, "invalid value for blgp format", Call,
+ Call.getArgOperand(4));
+
+ // AMDGPU::MFMAScaleFormats values
+ auto getFormatNumRegs = [](unsigned FormatVal) {
+ switch (FormatVal) {
+ case 0:
+ case 1:
+ return 8u;
+ case 2:
+ case 3:
+ return 6u;
+ case 4:
+ return 4u;
+ default:
+ llvm_unreachable("invalid format value");
+ }
+ };
+
+ auto isValidSrcASrcBVector = [](FixedVectorType *Ty) {
+ if (!Ty || !Ty->getElementType()->isIntegerTy(32))
+ return false;
+ unsigned NumElts = Ty->getNumElements();
+ return NumElts == 4 || NumElts == 6 || NumElts == 8;
+ };
+
+ auto *Src0Ty = dyn_cast<FixedVectorType>(Src0->getType());
+ auto *Src1Ty = dyn_cast<FixedVectorType>(Src1->getType());
+ Check(isValidSrcASrcBVector(Src0Ty),
+ "operand 0 must be 4, 6 or 8 element i32 vector", &Call, Src0);
+ Check(isValidSrcASrcBVector(Src1Ty),
+ "operand 1 must be 4, 6 or 8 element i32 vector", &Call, Src1);
+
+ // Permit excess registers for the format.
+ Check(Src0Ty->getNumElements() >= getFormatNumRegs(CBSZ),
+ "invalid vector type for format", &Call, Src0, Call.getArgOperand(3));
+ Check(Src1Ty->getNumElements() >= getFormatNumRegs(BLGP),
+ "invalid vector type for format", &Call, Src1, Call.getArgOperand(5));
+ break;
+ }
case Intrinsic::nvvm_setmaxnreg_inc_sync_aligned_u32:
case Intrinsic::nvvm_setmaxnreg_dec_sync_aligned_u32: {
Value *V = Call.getArgOperand(0);