-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TargetVerifier][AMDGPU] Add TargetVerifier. #123609
Draft
jofrn
wants to merge
1
commit into
llvm:main
Choose a base branch
from
jofrn:tgt-verifier
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
+631
−7
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You can test this locally with the following command:git-clang-format --diff 1c5b12257d19681d72a52e39eb2247dc6ab6af3b 053aac8113194cda51fbbafe98e38c6c54521134 --extensions h,cpp -- llvm/include/llvm/Target/TargetVerifier.h llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp llvm/include/llvm/IR/Module.h llvm/lib/Analysis/Lint.cpp llvm/lib/IR/Verifier.cpp View the diff from clang-format here.diff --git a/llvm/include/llvm/Target/TargetVerifier.h b/llvm/include/llvm/Target/TargetVerifier.h
index e00c6a7b26..400282d0a7 100644
--- a/llvm/include/llvm/Target/TargetVerifier.h
+++ b/llvm/include/llvm/Target/TargetVerifier.h
@@ -1,4 +1,5 @@
-//===-- llvm/Target/TargetVerifier.h - LLVM IR Target Verifier ---*- C++ -*-===//
+//===-- llvm/Target/TargetVerifier.h - LLVM IR Target Verifier ---*- C++
+//-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -20,8 +21,8 @@
#ifndef LLVM_TARGET_VERIFIER_H
#define LLVM_TARGET_VERIFIER_H
-#include "llvm/IR/PassManager.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/TargetParser/Triple.h"
namespace llvm {
@@ -59,10 +60,11 @@ protected:
/// This calls the Message-only version so that the above is easier to set
/// a breakpoint on.
template <typename T1, typename... Ts>
- void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) {
+ void CheckFailed(const Twine &Message, const T1 &V1, const Ts &...Vs) {
CheckFailed(Message);
WriteValues({V1, Vs...});
}
+
public:
Module *Mod;
Triple TT;
diff --git a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h
index e6ff57629b..207ff2d07d 100644
--- a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h
+++ b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h
@@ -1,8 +1,9 @@
-//===-- llvm/Target/TargetVerify/AMDGPUTargetVerifier.h - AMDGPU ---*- C++ -*-===//
+//===-- llvm/Target/TargetVerify/AMDGPUTargetVerifier.h - AMDGPU ---*- C++
+//-*-===//
////
-//// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-//// See https://llvm.org/LICENSE.txt for license information.
-//// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+///Exceptions. / See https://llvm.org/LICENSE.txt for license information. /
+///SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
////
////===----------------------------------------------------------------------===//
////
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 1a42131b8e..9c314b80c7 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -750,9 +750,10 @@ PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) {
if (!L.MessagesStr.str().empty()) {
F.getParent()->IsValid = false;
if (LintAbortOnError)
- report_fatal_error(Twine("Linter found errors, aborting. (enabled by --") +
- LintAbortOnErrorArgName + ")",
- false);
+ report_fatal_error(
+ Twine("Linter found errors, aborting. (enabled by --") +
+ LintAbortOnErrorArgName + ")",
+ false);
}
return PreservedAnalyses::all();
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
index 4e12145d0b..ee6fbe771c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
@@ -1,21 +1,22 @@
#include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h"
-#include "llvm/Analysis/UniformityAnalysis.h"
#include "llvm/Analysis/PostDominators.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Analysis/UniformityAnalysis.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-static cl::opt<bool>
-MarkUniform("mark-uniform", cl::desc("Mark instructions as uniform"), cl::init(false));
+static cl::opt<bool> MarkUniform("mark-uniform",
+ cl::desc("Mark instructions as uniform"),
+ cl::init(false));
// Check - We know that cond should be true, if not print an error message.
#define Check(C, ...) \
@@ -28,55 +29,55 @@ MarkUniform("mark-uniform", cl::desc("Mark instructions as uniform"), cl::init(f
static bool isMFMA(unsigned IID) {
switch (IID) {
- case Intrinsic::amdgcn_mfma_f32_4x4x1f32:
- case Intrinsic::amdgcn_mfma_f32_4x4x4f16:
- case Intrinsic::amdgcn_mfma_i32_4x4x4i8:
- case Intrinsic::amdgcn_mfma_f32_4x4x2bf16:
-
- case Intrinsic::amdgcn_mfma_f32_16x16x1f32:
- case Intrinsic::amdgcn_mfma_f32_16x16x4f32:
- case Intrinsic::amdgcn_mfma_f32_16x16x4f16:
- case Intrinsic::amdgcn_mfma_f32_16x16x16f16:
- case Intrinsic::amdgcn_mfma_i32_16x16x4i8:
- case Intrinsic::amdgcn_mfma_i32_16x16x16i8:
- case Intrinsic::amdgcn_mfma_f32_16x16x2bf16:
- case Intrinsic::amdgcn_mfma_f32_16x16x8bf16:
-
- case Intrinsic::amdgcn_mfma_f32_32x32x1f32:
- case Intrinsic::amdgcn_mfma_f32_32x32x2f32:
- case Intrinsic::amdgcn_mfma_f32_32x32x4f16:
- case Intrinsic::amdgcn_mfma_f32_32x32x8f16:
- case Intrinsic::amdgcn_mfma_i32_32x32x4i8:
- case Intrinsic::amdgcn_mfma_i32_32x32x8i8:
- case Intrinsic::amdgcn_mfma_f32_32x32x2bf16:
- case Intrinsic::amdgcn_mfma_f32_32x32x4bf16:
-
- case Intrinsic::amdgcn_mfma_f32_4x4x4bf16_1k:
- case Intrinsic::amdgcn_mfma_f32_16x16x4bf16_1k:
- case Intrinsic::amdgcn_mfma_f32_16x16x16bf16_1k:
- case Intrinsic::amdgcn_mfma_f32_32x32x4bf16_1k:
- case Intrinsic::amdgcn_mfma_f32_32x32x8bf16_1k:
-
- case Intrinsic::amdgcn_mfma_f64_16x16x4f64:
- case Intrinsic::amdgcn_mfma_f64_4x4x4f64:
-
- case Intrinsic::amdgcn_mfma_i32_16x16x32_i8:
- case Intrinsic::amdgcn_mfma_i32_32x32x16_i8:
- case Intrinsic::amdgcn_mfma_f32_16x16x8_xf32:
- case Intrinsic::amdgcn_mfma_f32_32x32x4_xf32:
-
- case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_bf8:
- case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_fp8:
- case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_bf8:
- case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_fp8:
-
- case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_bf8:
- case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_fp8:
- case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_bf8:
- case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_fp8:
- return true;
- default:
- return false;
+ case Intrinsic::amdgcn_mfma_f32_4x4x1f32:
+ case Intrinsic::amdgcn_mfma_f32_4x4x4f16:
+ case Intrinsic::amdgcn_mfma_i32_4x4x4i8:
+ case Intrinsic::amdgcn_mfma_f32_4x4x2bf16:
+
+ case Intrinsic::amdgcn_mfma_f32_16x16x1f32:
+ case Intrinsic::amdgcn_mfma_f32_16x16x4f32:
+ case Intrinsic::amdgcn_mfma_f32_16x16x4f16:
+ case Intrinsic::amdgcn_mfma_f32_16x16x16f16:
+ case Intrinsic::amdgcn_mfma_i32_16x16x4i8:
+ case Intrinsic::amdgcn_mfma_i32_16x16x16i8:
+ case Intrinsic::amdgcn_mfma_f32_16x16x2bf16:
+ case Intrinsic::amdgcn_mfma_f32_16x16x8bf16:
+
+ case Intrinsic::amdgcn_mfma_f32_32x32x1f32:
+ case Intrinsic::amdgcn_mfma_f32_32x32x2f32:
+ case Intrinsic::amdgcn_mfma_f32_32x32x4f16:
+ case Intrinsic::amdgcn_mfma_f32_32x32x8f16:
+ case Intrinsic::amdgcn_mfma_i32_32x32x4i8:
+ case Intrinsic::amdgcn_mfma_i32_32x32x8i8:
+ case Intrinsic::amdgcn_mfma_f32_32x32x2bf16:
+ case Intrinsic::amdgcn_mfma_f32_32x32x4bf16:
+
+ case Intrinsic::amdgcn_mfma_f32_4x4x4bf16_1k:
+ case Intrinsic::amdgcn_mfma_f32_16x16x4bf16_1k:
+ case Intrinsic::amdgcn_mfma_f32_16x16x16bf16_1k:
+ case Intrinsic::amdgcn_mfma_f32_32x32x4bf16_1k:
+ case Intrinsic::amdgcn_mfma_f32_32x32x8bf16_1k:
+
+ case Intrinsic::amdgcn_mfma_f64_16x16x4f64:
+ case Intrinsic::amdgcn_mfma_f64_4x4x4f64:
+
+ case Intrinsic::amdgcn_mfma_i32_16x16x32_i8:
+ case Intrinsic::amdgcn_mfma_i32_32x32x16_i8:
+ case Intrinsic::amdgcn_mfma_f32_16x16x8_xf32:
+ case Intrinsic::amdgcn_mfma_f32_32x32x4_xf32:
+
+ case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_bf8:
+ case Intrinsic::amdgcn_mfma_f32_16x16x32_bf8_fp8:
+ case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_bf8:
+ case Intrinsic::amdgcn_mfma_f32_16x16x32_fp8_fp8:
+
+ case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_bf8:
+ case Intrinsic::amdgcn_mfma_f32_32x32x16_bf8_fp8:
+ case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_bf8:
+ case Intrinsic::amdgcn_mfma_f32_32x32x16_fp8_fp8:
+ return true;
+ default:
+ return false;
}
}
@@ -89,42 +90,40 @@ public:
PostDominatorTree *PDT;
UniformityInfo *UA;
- AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT, UniformityInfo *UA)
- : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {}
+ AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT,
+ UniformityInfo *UA)
+ : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {}
void run(Function &F);
};
static bool IsValidInt(const Type *Ty) {
- return Ty->isIntegerTy(1) ||
- Ty->isIntegerTy(8) ||
- Ty->isIntegerTy(16) ||
- Ty->isIntegerTy(32) ||
- Ty->isIntegerTy(64) ||
- Ty->isIntegerTy(128);
+ return Ty->isIntegerTy(1) || Ty->isIntegerTy(8) || Ty->isIntegerTy(16) ||
+ Ty->isIntegerTy(32) || Ty->isIntegerTy(64) || Ty->isIntegerTy(128);
}
static bool isShader(CallingConv::ID CC) {
- switch(CC) {
- case CallingConv::AMDGPU_VS:
- case CallingConv::AMDGPU_LS:
- case CallingConv::AMDGPU_HS:
- case CallingConv::AMDGPU_ES:
- case CallingConv::AMDGPU_GS:
- case CallingConv::AMDGPU_PS:
- case CallingConv::AMDGPU_CS_Chain:
- case CallingConv::AMDGPU_CS_ChainPreserve:
- case CallingConv::AMDGPU_CS:
- return true;
- default:
- return false;
+ switch (CC) {
+ case CallingConv::AMDGPU_VS:
+ case CallingConv::AMDGPU_LS:
+ case CallingConv::AMDGPU_HS:
+ case CallingConv::AMDGPU_ES:
+ case CallingConv::AMDGPU_GS:
+ case CallingConv::AMDGPU_PS:
+ case CallingConv::AMDGPU_CS_Chain:
+ case CallingConv::AMDGPU_CS_ChainPreserve:
+ case CallingConv::AMDGPU_CS:
+ return true;
+ default:
+ return false;
}
}
void AMDGPUTargetVerify::run(Function &F) {
// Ensure shader calling convention returns void
if (isShader(F.getCallingConv()))
- Check(F.getReturnType() == Type::getVoidTy(F.getContext()), "Shaders must return void");
+ Check(F.getReturnType() == Type::getVoidTy(F.getContext()),
+ "Shaders must return void");
for (auto &BB : F) {
@@ -137,32 +136,29 @@ void AMDGPUTargetVerify::run(Function &F) {
Check(IsValidInt(I.getType()), "Int type is invalid.", &I);
for (unsigned i = 0; i < I.getNumOperands(); ++i)
if (I.getOperand(i)->getType()->isIntegerTy())
- Check(IsValidInt(I.getOperand(i)->getType()),
- "Int type is invalid.", I.getOperand(i));
+ Check(IsValidInt(I.getOperand(i)->getType()), "Int type is invalid.",
+ I.getOperand(i));
// Ensure alloca array size is constant
- if (auto *AI = dyn_cast<AllocaInst>(&I))
- {
+ if (auto *AI = dyn_cast<AllocaInst>(&I)) {
auto *AS = AI->getArraySize();
Check(!isa<Constant>(AS), "Dynamically-sized alloca disallowed");
}
// Ensure no store to const memory
- if (auto *SI = dyn_cast<StoreInst>(&I))
- {
+ if (auto *SI = dyn_cast<StoreInst>(&I)) {
unsigned AS = SI->getPointerAddressSpace();
Check(AS != 4, "Write to const memory", SI);
}
// Ensure no kernel to kernel calls.
- if (auto *CI = dyn_cast<CallInst>(&I))
- {
+ if (auto *CI = dyn_cast<CallInst>(&I)) {
CallingConv::ID CalleeCC = CI->getCallingConv();
- if (CalleeCC == CallingConv::AMDGPU_KERNEL)
- {
- CallingConv::ID CallerCC = CI->getParent()->getParent()->getCallingConv();
+ if (CalleeCC == CallingConv::AMDGPU_KERNEL) {
+ CallingConv::ID CallerCC =
+ CI->getParent()->getParent()->getCallingConv();
Check(CallerCC != CallingConv::AMDGPU_KERNEL,
- "A kernel may not call a kernel", CI->getParent()->getParent());
+ "A kernel may not call a kernel", CI->getParent()->getParent());
}
}
@@ -181,7 +177,8 @@ void AMDGPUTargetVerify::run(Function &F) {
break;
}
if (InControlFlow) {
- // If operands to MFMA are not uniform, MFMA cannot be in control flow
+ // If operands to MFMA are not uniform, MFMA cannot be in control
+ // flow
bool hasUniformOperands = true;
for (unsigned i = 0; i < II->getNumOperands(); i++) {
if (!UA->isUniform(II->getOperand(i))) {
@@ -189,17 +186,19 @@ void AMDGPUTargetVerify::run(Function &F) {
hasUniformOperands = false;
}
}
- if (!hasUniformOperands) Check(false, "MFMA in control flow", II);
- //else Check(false, "MFMA in control flow (uniform operands)", II);
+ if (!hasUniformOperands)
+ Check(false, "MFMA in control flow", II);
+ // else Check(false, "MFMA in control flow (uniform operands)", II);
}
- //else Check(false, "MFMA not in control flow", II);
+ // else Check(false, "MFMA not in control flow", II);
}
}
}
}
}
-PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F, FunctionAnalysisManager &AM) {
+PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F,
+ FunctionAnalysisManager &AM) {
auto *Mod = F.getParent();
diff --git a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp
index 68422abd6f..404f76caf5 100644
--- a/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp
+++ b/llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp
@@ -10,7 +10,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/InitializePasses.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/Lint.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
@@ -24,9 +23,10 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/StandardInstrumentations.h"
-#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Debug.h"
@@ -45,19 +45,17 @@ using namespace llvm;
static codegen::RegisterCodeGenFlags CGF;
static cl::opt<std::string>
-InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+ InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
-static cl::opt<bool>
- StacktraceAbort("stacktrace-abort",
- cl::desc("Turn on stacktrace"), cl::init(false));
+static cl::opt<bool> StacktraceAbort("stacktrace-abort",
+ cl::desc("Turn on stacktrace"),
+ cl::init(false));
-static cl::opt<bool>
- NoLint("no-lint",
- cl::desc("Turn off Lint"), cl::init(false));
+static cl::opt<bool> NoLint("no-lint", cl::desc("Turn off Lint"),
+ cl::init(false));
-static cl::opt<bool>
- NoVerify("no-verifier",
- cl::desc("Turn off Verifier"), cl::init(false));
+static cl::opt<bool> NoVerify("no-verifier", cl::desc("Turn off Verifier"),
+ cl::init(false));
static cl::opt<char>
OptLevel("O",
@@ -126,13 +124,12 @@ int main(int argc, char **argv) {
M->setTargetTriple(S);
PassInstrumentationCallbacks PIC;
- StandardInstrumentations SI(Context, false/*debug PM*/,
- false);
+ StandardInstrumentations SI(Context, false /*debug PM*/, false);
registerCodeGenCallback(PIC, *TM);
ModulePassManager MPM;
FunctionPassManager FPM;
- //TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
+ // TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
MachineFunctionAnalysisManager MFAM;
LoopAnalysisManager LAM;
@@ -149,7 +146,7 @@ int main(int argc, char **argv) {
SI.registerCallbacks(PIC, &MAM);
- //FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
+ // FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
Triple TT(M->getTargetTriple());
if (!NoLint)
@@ -158,7 +155,8 @@ int main(int argc, char **argv) {
MPM.addPass(VerifierPass());
if (TT.isAMDGPU())
FPM.addPass(AMDGPUTargetVerifierPass());
- else if (false) {} // ...
+ else if (false) {
+ } // ...
else
FPM.addPass(TargetVerifierPass());
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
This pass verifies the IR for an individual backend. This is different than Lint because it consolidates all checks for a given backend in a single pass. A check for Lint may be undefined behavior across all targets, whereas a check in TargetVerifier would only pertain to the specified target but can check more than just undefined behavior such are IR validity. A use case of this would be to reject programs with invalid IR while fuzzing.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pass verifies the IR for an individual backend. This is different than Lint because it consolidates all checks for a given backend in a single pass. A check for Lint may be undefined behavior across all targets, whereas a check in TargetVerifier would only pertain to the specified target but can check more than just undefined behavior such are IR validity. A use case of this would be to reject programs with invalid IR while fuzzing.