-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[TargetVerifier][AMDGPU] Add TargetVerifier. #123609
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
Open
jofrn
wants to merge
31
commits 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.
+282
−0
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
210b6d8
[TargetVerifier][AMDGPU] Add TargetVerifier.
jofrn a808efc
Add hook for target verifier in llc,opt
jofrn 64d0018
Run AMDGPUTargetVerifier within AMDGPU pipeline. Move IsValid from
jofrn fdae302
Remove cmd line options that aren't required. Make error message expl…
jofrn 5ceda58
Return Verifier none status through PreservedAnalyses on fail.
jofrn 99c2906
Rebase update.
jofrn 3ea7eae
Add generic TargetVerifier.
jofrn f52c4db
Remove store to const check since it is in Lint already
jofrn 5c9a4ab
Add chain followed by unreachable check
jofrn 0ff03f7
Remove mfma check
jofrn 6b84c73
Add registerVerifierPasses to PassBuilder and add the verifier passes…
jofrn ec3276b
Remove leftovers. Add titles. Add call to registerVerifierCallbacks i…
jofrn 4f00c83
Add pass to legacy PM.
jofrn 3013fc9
Add fam in other projects.
jofrn 8745cd1
Avoid fatal errors in llc.
jofrn c7bf730
Add tool to build/test.
jofrn c8dd3db
Cleanup of unrequired functions.
jofrn 2c12e6a
Make virtual.
jofrn 3267b65
Remove from legacy PM. Add to target dependent pipeline.
jofrn 6401b75
Add back to legacy PM.
jofrn e2f0225
Remove reference to FAM in registerCallbacks and VerifyEach for Targe…
jofrn b43cec1
Remove references to registry
jofrn b583b3f
Remove int check
jofrn 2ba9f5d
Remove modifications to Lint/Verifier.
jofrn 0c57244
Remove llvm-tgt-verify tool.
jofrn 5fec133
Remove TargetVerifier.cpp
jofrn c176578
clang-format
jofrn 97d43c1
Add VerifyTarget option
jofrn ea2f050
Remove AMDGPUTargetVerifier.h
jofrn de38b78
Remove analyses.
jofrn dd34679
function name style, TargetVerifier comment, option name generality
jofrn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//===-- 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 an individual backend's | ||
// TargetVerifier. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_TARGET_VERIFIER_H | ||
#define LLVM_TARGET_VERIFIER_H | ||
|
||
#include "llvm/IR/Module.h" | ||
#include "llvm/IR/PassManager.h" | ||
#include "llvm/TargetParser/Triple.h" | ||
|
||
namespace llvm { | ||
|
||
class Function; | ||
|
||
class TargetVerifierPass : public PassInfoMixin<TargetVerifierPass> { | ||
public: | ||
virtual PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) = 0; | ||
}; | ||
|
||
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; | ||
|
||
bool IsValid = true; | ||
|
||
TargetVerify(Module *Mod) | ||
: Mod(Mod), TT(Mod->getTargetTriple()), MessagesStr(Messages) {} | ||
|
||
virtual bool run(Function &F) = 0; | ||
}; | ||
|
||
} // namespace llvm | ||
|
||
#endif // LLVM_TARGET_VERIFIER_H |
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
//===-- AMDGPUTargetVerifier.cpp - 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. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "AMDGPU.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; | ||
|
||
// Check - We know that cond should be true, if not print an error message. | ||
#define Check(C, ...) \ | ||
do { \ | ||
if (!(C)) { \ | ||
TargetVerify::checkFailed(__VA_ARGS__); \ | ||
} \ | ||
} while (false) | ||
|
||
namespace llvm { | ||
|
||
class AMDGPUTargetVerify : public TargetVerify { | ||
public: | ||
AMDGPUTargetVerify(Module *Mod) : TargetVerify(Mod) {} | ||
bool run(Function &F) override; | ||
}; | ||
|
||
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; | ||
} | ||
} | ||
|
||
bool AMDGPUTargetVerify::run(Function &F) { | ||
// Ensure shader calling convention returns void | ||
if (isShader(F.getCallingConv())) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on previous discussion with @arsenm , this check should go to the IR verifier. |
||
Check(F.getReturnType() == Type::getVoidTy(F.getContext()), | ||
"Shaders must return void"); | ||
|
||
for (auto &BB : F) { | ||
|
||
for (auto &I : BB) { | ||
|
||
if (auto *CI = dyn_cast<CallInst>(&I)) { | ||
// Ensure no kernel to kernel calls. | ||
CallingConv::ID CalleeCC = CI->getCallingConv(); | ||
if (CalleeCC == CallingConv::AMDGPU_KERNEL) { | ||
CallingConv::ID CallerCC = | ||
CI->getParent()->getParent()->getCallingConv(); | ||
Check(CallerCC != CallingConv::AMDGPU_KERNEL, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I already disallow this in the IR verifier. |
||
"A kernel may not call a kernel", CI->getParent()->getParent()); | ||
} | ||
|
||
// Ensure chain intrinsics are followed by unreachables. | ||
if (CI->getIntrinsicID() == Intrinsic::amdgcn_cs_chain) | ||
Check(isa_and_present<UnreachableInst>(CI->getNextNode()), | ||
"llvm.amdgcn.cs.chain must be followed by unreachable", CI); | ||
} | ||
} | ||
} | ||
|
||
dbgs() << MessagesStr.str(); | ||
if (!MessagesStr.str().empty()) { | ||
IsValid = false; | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
PreservedAnalyses AMDGPUTargetVerifierPass::run(Function &F, | ||
FunctionAnalysisManager &AM) { | ||
auto *Mod = F.getParent(); | ||
|
||
AMDGPUTargetVerify TV(Mod); | ||
TV.run(F); | ||
|
||
dbgs() << TV.MessagesStr.str(); | ||
if (!TV.MessagesStr.str().empty()) { | ||
TV.IsValid = false; | ||
return PreservedAnalyses::none(); | ||
} | ||
return PreservedAnalyses::all(); | ||
} | ||
|
||
struct AMDGPUTargetVerifierLegacyPass : public FunctionPass { | ||
static char ID; | ||
|
||
std::unique_ptr<AMDGPUTargetVerify> TV; | ||
bool FatalErrors = false; | ||
|
||
AMDGPUTargetVerifierLegacyPass(bool FatalErrors) | ||
: FunctionPass(ID), FatalErrors(FatalErrors) { | ||
initializeAMDGPUTargetVerifierLegacyPassPass( | ||
*PassRegistry::getPassRegistry()); | ||
} | ||
|
||
bool doInitialization(Module &M) override { | ||
TV = std::make_unique<AMDGPUTargetVerify>(&M); | ||
return false; | ||
} | ||
|
||
bool runOnFunction(Function &F) override { | ||
if (!TV->run(F)) { | ||
errs() << "in function " << F.getName() << '\n'; | ||
if (FatalErrors) | ||
report_fatal_error("broken function found, compilation aborted!"); | ||
else | ||
errs() << "broken function found, compilation aborted!\n"; | ||
} | ||
return false; | ||
} | ||
|
||
bool doFinalization(Module &M) override { | ||
bool IsValid = true; | ||
for (Function &F : M) | ||
if (F.isDeclaration()) | ||
IsValid &= TV->run(F); | ||
|
||
if (!IsValid) { | ||
if (FatalErrors) | ||
report_fatal_error("broken module found, compilation aborted!"); | ||
else | ||
errs() << "broken module found, compilation aborted!\n"; | ||
} | ||
return false; | ||
} | ||
|
||
void getAnalysisUsage(AnalysisUsage &AU) const override { | ||
AU.setPreservesAll(); | ||
} | ||
}; | ||
char AMDGPUTargetVerifierLegacyPass::ID = 0; | ||
FunctionPass *createAMDGPUTargetVerifierLegacyPass(bool FatalErrors) { | ||
return new AMDGPUTargetVerifierLegacyPass(FatalErrors); | ||
} | ||
} // namespace llvm | ||
INITIALIZE_PASS(AMDGPUTargetVerifierLegacyPass, "amdgpu-tgtverifier", | ||
"AMDGPU Target Verifier", false, false) |
This file contains hidden or 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
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -amdgpu-verify-tgt -o - < %s 2>&1 | FileCheck %s | ||
|
||
define amdgpu_cs i32 @nonvoid_shader() { | ||
; CHECK: Shaders must return void | ||
ret i32 0 | ||
} |
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
; RUN: llc -mtriple=amdgcn -mcpu=gfx900 -amdgpu-verify-tgt %s -o - 2>&1 | FileCheck %s --allow-empty | ||
|
||
define amdgpu_cs void @void_shader() { | ||
; CHECK-NOT: Shaders must return void | ||
ret void | ||
} |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rename this to something more accurate because currently I don't know where it writes to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be written to anywhere, but
MessagesStr
is currently being written todbgs()
.llvm-project/llvm/lib/Target/AMDGPU/AMDGPUTargetVerifier.cpp
Line 109 in de38b78