Skip to content

Commit e1a21ec

Browse files
committed
[TargetVerifier][AMDGPU] Add TargetVerifier.
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.
1 parent 1c5b122 commit e1a21ec

File tree

10 files changed

+631
-7
lines changed

10 files changed

+631
-7
lines changed

llvm/include/llvm/IR/Module.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ class LLVM_ABI Module {
211211
/// @name Constructors
212212
/// @{
213213
public:
214+
/// Is this Module valid as determined by one of the verification passes
215+
/// i.e. Lint, Verifier, TargetVerifier.
216+
bool IsValid = true;
217+
214218
/// Is this Module using intrinsics to record the position of debugging
215219
/// information, or non-intrinsic records? See IsNewDbgInfoFormat in
216220
/// \ref BasicBlock.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===-- llvm/Target/TargetVerifier.h - LLVM IR Target Verifier ---*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines target verifier interfaces that can be used for some
10+
// validation of input to the system, and for checking that transformations
11+
// haven't done something bad. In contrast to the Verifier or Lint, the
12+
// TargetVerifier looks for constructions invalid to a particular target
13+
// machine.
14+
//
15+
// To see what specifically is checked, look at TargetVerifier.cpp or an
16+
// individual backend's TargetVerifier.
17+
//
18+
//===----------------------------------------------------------------------===//
19+
20+
#ifndef LLVM_TARGET_VERIFIER_H
21+
#define LLVM_TARGET_VERIFIER_H
22+
23+
#include "llvm/IR/PassManager.h"
24+
#include "llvm/IR/Module.h"
25+
#include "llvm/TargetParser/Triple.h"
26+
27+
namespace llvm {
28+
29+
class Function;
30+
31+
class TargetVerifierPass : public PassInfoMixin<TargetVerifierPass> {
32+
public:
33+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {}
34+
};
35+
36+
class TargetVerify {
37+
protected:
38+
void WriteValues(ArrayRef<const Value *> Vs) {
39+
for (const Value *V : Vs) {
40+
if (!V)
41+
continue;
42+
if (isa<Instruction>(V)) {
43+
MessagesStr << *V << '\n';
44+
} else {
45+
V->printAsOperand(MessagesStr, true, Mod);
46+
MessagesStr << '\n';
47+
}
48+
}
49+
}
50+
51+
/// A check failed, so printout out the condition and the message.
52+
///
53+
/// This provides a nice place to put a breakpoint if you want to see why
54+
/// something is not correct.
55+
void CheckFailed(const Twine &Message) { MessagesStr << Message << '\n'; }
56+
57+
/// A check failed (with values to print).
58+
///
59+
/// This calls the Message-only version so that the above is easier to set
60+
/// a breakpoint on.
61+
template <typename T1, typename... Ts>
62+
void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) {
63+
CheckFailed(Message);
64+
WriteValues({V1, Vs...});
65+
}
66+
public:
67+
Module *Mod;
68+
Triple TT;
69+
70+
std::string Messages;
71+
raw_string_ostream MessagesStr;
72+
73+
TargetVerify(Module *Mod)
74+
: Mod(Mod), TT(Triple::normalize(Mod->getTargetTriple())),
75+
MessagesStr(Messages) {}
76+
77+
void run(Function &F) {};
78+
};
79+
80+
} // namespace llvm
81+
82+
#endif // LLVM_TARGET_VERIFIER_H
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===-- llvm/Target/TargetVerify/AMDGPUTargetVerifier.h - AMDGPU ---*- C++ -*-===//
2+
////
3+
//// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
//// See https://llvm.org/LICENSE.txt for license information.
5+
//// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
////
7+
////===----------------------------------------------------------------------===//
8+
////
9+
//// This file defines target verifier interfaces that can be used for some
10+
//// validation of input to the system, and for checking that transformations
11+
//// haven't done something bad. In contrast to the Verifier or Lint, the
12+
//// TargetVerifier looks for constructions invalid to a particular target
13+
//// machine.
14+
////
15+
//// To see what specifically is checked, look at an individual backend's
16+
//// TargetVerifier.
17+
////
18+
////===----------------------------------------------------------------------===//
19+
20+
#ifndef LLVM_AMDGPU_TARGET_VERIFIER_H
21+
#define LLVM_AMDGPU_TARGET_VERIFIER_H
22+
23+
#include "llvm/Target/TargetVerifier.h"
24+
25+
namespace llvm {
26+
27+
class Function;
28+
29+
class AMDGPUTargetVerifierPass : public TargetVerifierPass {
30+
public:
31+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
32+
};
33+
34+
} // namespace llvm
35+
36+
#endif // LLVM_AMDGPU_TARGET_VERIFIER_H

llvm/lib/Analysis/Lint.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -747,10 +747,13 @@ PreservedAnalyses LintPass::run(Function &F, FunctionAnalysisManager &AM) {
747747
Lint L(Mod, DL, AA, AC, DT, TLI);
748748
L.visit(F);
749749
dbgs() << L.MessagesStr.str();
750-
if (LintAbortOnError && !L.MessagesStr.str().empty())
751-
report_fatal_error(Twine("Linter found errors, aborting. (enabled by --") +
750+
if (!L.MessagesStr.str().empty()) {
751+
F.getParent()->IsValid = false;
752+
if (LintAbortOnError)
753+
report_fatal_error(Twine("Linter found errors, aborting. (enabled by --") +
752754
LintAbortOnErrorArgName + ")",
753-
false);
755+
false);
756+
}
754757
return PreservedAnalyses::all();
755758
}
756759

llvm/lib/IR/Verifier.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ static cl::opt<bool> VerifyNoAliasScopeDomination(
135135
cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical "
136136
"scopes are not dominating"));
137137

138+
static cl::opt<bool>
139+
VerifyAbortOnError("verifier-abort-on-error", cl::init(false),
140+
cl::desc("In the Verifier pass, abort on errors."));
141+
138142
namespace llvm {
139143

140144
struct VerifierSupport {
@@ -7739,16 +7743,22 @@ VerifierAnalysis::Result VerifierAnalysis::run(Function &F,
77397743

77407744
PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) {
77417745
auto Res = AM.getResult<VerifierAnalysis>(M);
7742-
if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken))
7743-
report_fatal_error("Broken module found, compilation aborted!");
7746+
if (Res.IRBroken || Res.DebugInfoBroken) {
7747+
M.IsValid = false;
7748+
if (VerifyAbortOnError && FatalErrors)
7749+
report_fatal_error("Broken module found, compilation aborted!");
7750+
}
77447751

77457752
return PreservedAnalyses::all();
77467753
}
77477754

77487755
PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) {
77497756
auto res = AM.getResult<VerifierAnalysis>(F);
7750-
if (res.IRBroken && FatalErrors)
7751-
report_fatal_error("Broken function found, compilation aborted!");
7757+
if (res.IRBroken) {
7758+
F.getParent()->IsValid = false;
7759+
if (VerifyAbortOnError && FatalErrors)
7760+
report_fatal_error("Broken function found, compilation aborted!");
7761+
}
77527762

77537763
return PreservedAnalyses::all();
77547764
}

0 commit comments

Comments
 (0)