[llvm] [TargetVerifier][AMDGPU] Add TargetVerifier. (PR #123609)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 2 05:36:39 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: None (jofrn)
<details>
<summary>Changes</summary>
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.
---
Patch is 34.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/123609.diff
22 Files Affected:
- (modified) llvm/include/llvm/IR/Module.h (+4)
- (modified) llvm/include/llvm/Passes/StandardInstrumentations.h (+4-2)
- (added) llvm/include/llvm/Target/TargetVerifier.h (+83)
- (added) llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h (+54)
- (modified) llvm/lib/Analysis/Lint.cpp (+6-3)
- (modified) llvm/lib/IR/Verifier.cpp (+14-4)
- (modified) llvm/lib/LTO/LTOBackend.cpp (+1-1)
- (modified) llvm/lib/LTO/ThinLTOCodeGenerator.cpp (+1-1)
- (modified) llvm/lib/Passes/CMakeLists.txt (+1)
- (modified) llvm/lib/Passes/PassBuilderBindings.cpp (+1-1)
- (modified) llvm/lib/Passes/StandardInstrumentations.cpp (+15-4)
- (added) llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp (+213)
- (modified) llvm/lib/Target/AMDGPU/CMakeLists.txt (+1)
- (modified) llvm/lib/Target/CMakeLists.txt (+2)
- (added) llvm/test/CodeGen/AMDGPU/tgt-verify-llc-fail.ll (+6)
- (added) llvm/test/CodeGen/AMDGPU/tgt-verify-llc-pass.ll (+6)
- (added) llvm/test/CodeGen/AMDGPU/tgt-verify.ll (+62)
- (modified) llvm/tools/llc/NewPMDriver.cpp (+1-1)
- (added) llvm/tools/llvm-tgt-verify/CMakeLists.txt (+34)
- (added) llvm/tools/llvm-tgt-verify/llvm-tgt-verify.cpp (+172)
- (modified) llvm/tools/opt/NewPMDriver.cpp (+1-1)
- (modified) llvm/unittests/IR/PassManagerTest.cpp (+3-3)
``````````diff
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 12b50fc506516..7844cb216ed57 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -211,6 +211,10 @@ class LLVM_ABI Module {
/// @name Constructors
/// @{
public:
+ /// Is this Module valid as determined by one of the verification passes
+ /// i.e. Lint, Verifier, TargetVerifier.
+ bool IsValid = true;
+
/// Is this Module using intrinsics to record the position of debugging
/// information, or non-intrinsic records? See IsNewDbgInfoFormat in
/// \ref BasicBlock.
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 4e62ee9c00daf..f794555b7a96d 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -464,7 +464,8 @@ class VerifyInstrumentation {
public:
VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {}
void registerCallbacks(PassInstrumentationCallbacks &PIC,
- ModuleAnalysisManager *MAM);
+ ModuleAnalysisManager *MAM,
+ FunctionAnalysisManager *FAM);
};
/// This class implements --time-trace functionality for new pass manager.
@@ -609,7 +610,8 @@ class StandardInstrumentations {
// Register all the standard instrumentation callbacks. If \p FAM is nullptr
// then PreservedCFGChecker is not enabled.
void registerCallbacks(PassInstrumentationCallbacks &PIC,
- ModuleAnalysisManager *MAM = nullptr);
+ ModuleAnalysisManager *MAM,
+ FunctionAnalysisManager *FAM);
TimePassesHandler &getTimePasses() { return TimePasses; }
};
diff --git a/llvm/include/llvm/Target/TargetVerifier.h b/llvm/include/llvm/Target/TargetVerifier.h
new file mode 100644
index 0000000000000..ad5aeb895953d
--- /dev/null
+++ b/llvm/include/llvm/Target/TargetVerifier.h
@@ -0,0 +1,83 @@
+//===-- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines target verifier interfaces that can be used for some
+// validation of input to the system, and for checking that transformations
+// haven't done something bad. In contrast to the Verifier or Lint, the
+// TargetVerifier looks for constructions invalid to a particular target
+// machine.
+//
+// To see what specifically is checked, look at TargetVerifier.cpp or an
+// individual backend's TargetVerifier.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_VERIFIER_H
+#define LLVM_TARGET_VERIFIER_H
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/TargetParser/Triple.h"
+
+namespace llvm {
+
+class Function;
+
+class TargetVerifierPass : public PassInfoMixin<TargetVerifierPass> {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {}
+};
+
+class TargetVerify {
+protected:
+ void WriteValues(ArrayRef<const Value *> Vs) {
+ for (const Value *V : Vs) {
+ if (!V)
+ continue;
+ if (isa<Instruction>(V)) {
+ MessagesStr << *V << '\n';
+ } else {
+ V->printAsOperand(MessagesStr, true, Mod);
+ MessagesStr << '\n';
+ }
+ }
+ }
+
+ /// A check failed, so printout out the condition and the message.
+ ///
+ /// This provides a nice place to put a breakpoint if you want to see why
+ /// something is not correct.
+ void CheckFailed(const Twine &Message) { MessagesStr << Message << '\n'; }
+
+ /// A check failed (with values to print).
+ ///
+ /// 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) {
+ CheckFailed(Message);
+ WriteValues({V1, Vs...});
+ }
+public:
+ Module *Mod;
+ Triple TT;
+
+ std::string Messages;
+ raw_string_ostream MessagesStr;
+
+ TargetVerify(Module *Mod)
+ : Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())),
+ MessagesStr(Messages) {}
+
+ void run(Function &F) {};
+ void run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // namespace llvm
+
+#endif // LLVM_TARGET_VERIFIER_H
diff --git a/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h
new file mode 100644
index 0000000000000..d8a3fda4f87dc
--- /dev/null
+++ b/llvm/include/llvm/Target/TargetVerify/AMDGPUTargetVerifier.h
@@ -0,0 +1,54 @@
+//===-- 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
+////
+////===----------------------------------------------------------------------===//
+////
+//// This file defines target verifier interfaces that can be used for some
+//// validation of input to the system, and for checking that transformations
+//// haven't done something bad. In contrast to the Verifier or Lint, the
+//// TargetVerifier looks for constructions invalid to a particular target
+//// machine.
+////
+//// To see what specifically is checked, look at an individual backend's
+//// TargetVerifier.
+////
+////===----------------------------------------------------------------------===//
+
+#ifndef LLVM_AMDGPU_TARGET_VERIFIER_H
+#define LLVM_AMDGPU_TARGET_VERIFIER_H
+
+#include "llvm/Target/TargetVerifier.h"
+
+#include "llvm/Analysis/UniformityAnalysis.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/IR/Dominators.h"
+
+namespace llvm {
+
+class Function;
+
+class AMDGPUTargetVerifierPass : public TargetVerifierPass {
+public:
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+class AMDGPUTargetVerify : public TargetVerify {
+public:
+ Module *Mod;
+
+ DominatorTree *DT;
+ PostDominatorTree *PDT;
+ UniformityInfo *UA;
+
+ AMDGPUTargetVerify(Module *Mod, DominatorTree *DT, PostDominatorTree *PDT, UniformityInfo *UA)
+ : TargetVerify(Mod), Mod(Mod), DT(DT), PDT(PDT), UA(UA) {}
+
+ void run(Function &F);
+};
+
+} // namespace llvm
+
+#endif // LLVM_AMDGPU_TARGET_VERIFIER_H
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index e9d96a0c2972a..1a42131b8ed1f 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -747,10 +747,13 @@ PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) {
Lint L(Mod, DL, AA, AC, DT, TLI);
L.visit(F);
dbgs() << L.MessagesStr.str();
- if (LintAbortOnError && !L.MessagesStr.str().empty())
- report_fatal_error(Twine("Linter found errors, aborting. (enabled by --") +
+ if (!L.MessagesStr.str().empty()) {
+ F.getParent()->IsValid = false;
+ if (LintAbortOnError)
+ report_fatal_error(Twine("Linter found errors, aborting. (enabled by --") +
LintAbortOnErrorArgName + ")",
- false);
+ false);
+ }
return PreservedAnalyses::all();
}
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 7b6f7b5aa6171..26616c4de59d2 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -135,6 +135,10 @@ static cl::opt<bool> VerifyNoAliasScopeDomination(
cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical "
"scopes are not dominating"));
+static cl::opt<bool>
+ VerifyAbortOnError("verifier-abort-on-error", cl::init(false),
+ cl::desc("In the Verifier pass, abort on errors."));
+
namespace llvm {
struct VerifierSupport {
@@ -7739,16 +7743,22 @@ VerifierAnalysis::Result VerifierAnalysis::run(Function &F,
PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) {
auto Res = AM.getResult<VerifierAnalysis>(M);
- if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken))
- report_fatal_error("Broken module found, compilation aborted!");
+ if (Res.IRBroken || Res.DebugInfoBroken) {
+ M.IsValid = false;
+ if (VerifyAbortOnError && FatalErrors)
+ report_fatal_error("Broken module found, compilation aborted!");
+ }
return PreservedAnalyses::all();
}
PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) {
auto res = AM.getResult<VerifierAnalysis>(F);
- if (res.IRBroken && FatalErrors)
- report_fatal_error("Broken function found, compilation aborted!");
+ if (res.IRBroken) {
+ F.getParent()->IsValid = false;
+ if (VerifyAbortOnError && FatalErrors)
+ report_fatal_error("Broken function found, compilation aborted!");
+ }
return PreservedAnalyses::all();
}
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 8a2dddce4892c..2d2f16005bd40 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -270,7 +270,7 @@ static void runNewPMPasses(const Config &Conf, Module &Mod, TargetMachine *TM,
PassInstrumentationCallbacks PIC;
StandardInstrumentations SI(Mod.getContext(), Conf.DebugPassManager,
Conf.VerifyEach);
- SI.registerCallbacks(PIC, &MAM);
+ SI.registerCallbacks(PIC, &MAM, &FAM);
PassBuilder PB(TM, Conf.PTO, PGOOpt, &PIC);
RegisterPassPlugins(Conf.PassPlugins, PB);
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 189f2876b61c0..84df56948a5a7 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -245,7 +245,7 @@ static void optimizeModule(Module &TheModule, TargetMachine &TM,
PassInstrumentationCallbacks PIC;
StandardInstrumentations SI(TheModule.getContext(), DebugPassManager);
- SI.registerCallbacks(PIC, &MAM);
+ SI.registerCallbacks(PIC, &MAM, &FAM);
PipelineTuningOptions PTO;
PTO.LoopVectorization = true;
PTO.SLPVectorization = true;
diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt
index 23799ac4f98f7..4b643837722ad 100644
--- a/llvm/lib/Passes/CMakeLists.txt
+++ b/llvm/lib/Passes/CMakeLists.txt
@@ -30,6 +30,7 @@ add_llvm_component_library(LLVMPasses
Scalar
Support
Target
+ TargetParser
TransformUtils
Vectorize
Instrumentation
diff --git a/llvm/lib/Passes/PassBuilderBindings.cpp b/llvm/lib/Passes/PassBuilderBindings.cpp
index 933fe89e53a94..f0e1abb8cebc4 100644
--- a/llvm/lib/Passes/PassBuilderBindings.cpp
+++ b/llvm/lib/Passes/PassBuilderBindings.cpp
@@ -76,7 +76,7 @@ static LLVMErrorRef runPasses(Module *Mod, Function *Fun, const char *Passes,
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach);
- SI.registerCallbacks(PIC, &MAM);
+ SI.registerCallbacks(PIC, &MAM, &FAM);
// Run the pipeline.
if (Fun) {
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index b766517e68eba..27ea19302d8d8 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -45,6 +45,7 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/xxhash.h"
+#include "llvm/Target/TargetVerifier.h"
#include <unordered_map>
#include <unordered_set>
#include <utility>
@@ -1461,9 +1462,10 @@ void PreservedCFGCheckerInstrumentation::registerCallbacks(
}
void VerifyInstrumentation::registerCallbacks(PassInstrumentationCallbacks &PIC,
- ModuleAnalysisManager *MAM) {
+ ModuleAnalysisManager *MAM,
+ FunctionAnalysisManager *FAM) {
PIC.registerAfterPassCallback(
- [this, MAM](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
+ [this, MAM, FAM](StringRef P, Any IR, const PreservedAnalyses &PassPA) {
if (isIgnored(P) || P == "VerifierPass")
return;
const auto *F = unwrapIR<Function>(IR);
@@ -1480,6 +1482,15 @@ void VerifyInstrumentation::registerCallbacks(PassInstrumentationCallbacks &PIC,
report_fatal_error(formatv("Broken function found after pass "
"\"{0}\", compilation aborted!",
P));
+
+ if (FAM) {
+ TargetVerify TV(const_cast<Module*>(F->getParent()));
+ TV.run(*const_cast<Function*>(F), *FAM);
+ if (!F->getParent()->IsValid)
+ report_fatal_error(formatv("Broken function found after pass "
+ "\"{0}\", compilation aborted!",
+ P));
+ }
} else {
const auto *M = unwrapIR<Module>(IR);
if (!M) {
@@ -2524,7 +2535,7 @@ void PrintCrashIRInstrumentation::registerCallbacks(
}
void StandardInstrumentations::registerCallbacks(
- PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) {
+ PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM, FunctionAnalysisManager *FAM) {
PrintIR.registerCallbacks(PIC);
PrintPass.registerCallbacks(PIC);
TimePasses.registerCallbacks(PIC);
@@ -2533,7 +2544,7 @@ void StandardInstrumentations::registerCallbacks(
PrintChangedIR.registerCallbacks(PIC);
PseudoProbeVerification.registerCallbacks(PIC);
if (VerifyEach)
- Verify.registerCallbacks(PIC, MAM);
+ Verify.registerCallbacks(PIC, MAM, FAM);
PrintChangedDiff.registerCallbacks(PIC);
WebsiteChangeReporter.registerCallbacks(PIC);
ChangeTester.registerCallbacks(PIC);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
new file mode 100644
index 0000000000000..e6cdec7160229
--- /dev/null
+++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
@@ -0,0 +1,213 @@
+#include "llvm/Target/TargetVerify/AMDGPUTargetVerifier.h"
+
+#include "llvm/Analysis/UniformityAnalysis.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Support/Debug.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/raw_ostream.h"
+
+using namespace llvm;
+
+//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, ...) \
+ do { \
+ if (!(C)) { \
+ TargetVerify::CheckFailed(__VA_ARGS__); \
+ return; \
+ } \
+ } while (false)
+
+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;
+ }
+}
+
+namespace llvm {
+/*class AMDGPUTargetVerify : public TargetVerify {
+public:
+ Module *Mod;
+
+ DominatorTree *DT;
+ PostDominatorTree *PDT;
+ UniformityInfo *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);
+}
+
+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;
+ }
+}
+
+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");
+
+ for (auto &BB : F) {
+
+ for (auto &I : BB) {
+ //if (MarkUniform)
+ //outs() << UA->isUniform(&I) << ' ' << I << '\n';
+
+ // Ensure integral types are valid: i8, i16, i32, i64, i128
+ if (I.getType()->isIntegerTy())
+ 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));
+
+ // Ensure no store to const memory
+ 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))
+ {
+ CallingConv::ID CalleeCC = CI->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());
+ }
+ }
+
+ // Ensure MFMA is not in control flow with diverging operands
+ if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
+ if (isMFMA(II->getIntrinsicID())) {
+ bool InControlFlow = false;
+ for (const auto &P : predecessors(&BB))
+ if (!PDT->dominates(&BB, P)) {
+ InControlFlow = true;
+ break;
+ }
+ for (const auto &S : successors(&BB))
+ if (!DT->dominates(&BB, S)) {
+ ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/123609
More information about the llvm-commits
mailing list