1 //===- Verifier.cpp - MLIR Verifier Implementation ------------------------===//
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 implements the verify() methods on the various IR types, performing
10 // (potentially expensive) checks on the holistic structure of the code. This
11 // can be used for detecting bugs in compiler transformations and hand written
12 // .mlir files.
13 //
14 // The checks in this file are only for things that can occur as part of IR
15 // transformations: e.g. violation of dominance information, malformed operation
16 // attributes, etc. MLIR supports transformations moving IR through locally
17 // invalid states (e.g. unlinking an operation from a block before re-inserting
18 // it in a new place), but each transformation must complete with the IR in a
19 // valid form.
20 //
21 // This should not check for things that are always wrong by construction (e.g.
22 // attributes or other immutable structures that are incorrect), because those
23 // are not mutable and can be checked at time of construction.
24 //
25 //===----------------------------------------------------------------------===//
26
27 #include "mlir/IR/Verifier.h"
28 #include "mlir/IR/Attributes.h"
29 #include "mlir/IR/Dialect.h"
30 #include "mlir/IR/Dominance.h"
31 #include "mlir/IR/Operation.h"
32 #include "mlir/IR/RegionKindInterface.h"
33 #include "llvm/ADT/StringMap.h"
34 #include "llvm/Support/FormatVariadic.h"
35 #include "llvm/Support/PrettyStackTrace.h"
36 #include "llvm/Support/Regex.h"
37
38 using namespace mlir;
39
40 namespace {
41 /// This class encapsulates all the state used to verify an operation region.
42 class OperationVerifier {
43 public:
OperationVerifier(MLIRContext * ctx)44 explicit OperationVerifier(MLIRContext *ctx) : ctx(ctx) {}
45
46 /// Verify the given operation.
47 LogicalResult verify(Operation &op);
48
49 /// Returns the registered dialect for a dialect-specific attribute.
getDialectForAttribute(const NamedAttribute & attr)50 Dialect *getDialectForAttribute(const NamedAttribute &attr) {
51 assert(attr.first.strref().contains('.') && "expected dialect attribute");
52 auto dialectNamePair = attr.first.strref().split('.');
53 return ctx->getLoadedDialect(dialectNamePair.first);
54 }
55
56 private:
57 /// Verify the given potentially nested region or block.
58 LogicalResult verifyRegion(Region ®ion);
59 LogicalResult verifyBlock(Block &block);
60 LogicalResult verifyOperation(Operation &op);
61
62 /// Verify the dominance property of operations within the given Region.
63 LogicalResult verifyDominance(Region ®ion);
64
65 /// Verify the dominance property of regions contained within the given
66 /// Operation.
67 LogicalResult verifyDominanceOfContainedRegions(Operation &op);
68
69 /// Emit an error for the given block.
emitError(Block & bb,const Twine & message)70 InFlightDiagnostic emitError(Block &bb, const Twine &message) {
71 // Take the location information for the first operation in the block.
72 if (!bb.empty())
73 return bb.front().emitError(message);
74
75 // Worst case, fall back to using the parent's location.
76 return mlir::emitError(bb.getParent()->getLoc(), message);
77 }
78
79 /// The current context for the verifier.
80 MLIRContext *ctx;
81
82 /// Dominance information for this operation, when checking dominance.
83 DominanceInfo *domInfo = nullptr;
84
85 /// Mapping between dialect namespace and if that dialect supports
86 /// unregistered operations.
87 llvm::StringMap<bool> dialectAllowsUnknownOps;
88 };
89 } // end anonymous namespace
90
91 /// Verify the given operation.
verify(Operation & op)92 LogicalResult OperationVerifier::verify(Operation &op) {
93 // Verify the operation first.
94 if (failed(verifyOperation(op)))
95 return failure();
96
97 // Since everything looks structurally ok to this point, we do a dominance
98 // check for any nested regions. We do this as a second pass since malformed
99 // CFG's can cause dominator analysis constructure to crash and we want the
100 // verifier to be resilient to malformed code.
101 DominanceInfo theDomInfo(&op);
102 domInfo = &theDomInfo;
103 if (failed(verifyDominanceOfContainedRegions(op)))
104 return failure();
105
106 domInfo = nullptr;
107 return success();
108 }
109
verifyRegion(Region & region)110 LogicalResult OperationVerifier::verifyRegion(Region ®ion) {
111 if (region.empty())
112 return success();
113
114 // Verify the first block has no predecessors.
115 auto *firstBB = ®ion.front();
116 if (!firstBB->hasNoPredecessors())
117 return mlir::emitError(region.getLoc(),
118 "entry block of region may not have predecessors");
119
120 // Verify each of the blocks within the region.
121 for (Block &block : region)
122 if (failed(verifyBlock(block)))
123 return failure();
124 return success();
125 }
126
verifyBlock(Block & block)127 LogicalResult OperationVerifier::verifyBlock(Block &block) {
128 for (auto arg : block.getArguments())
129 if (arg.getOwner() != &block)
130 return emitError(block, "block argument not owned by block");
131
132 // Verify that this block has a terminator.
133 if (block.empty())
134 return emitError(block, "block with no terminator");
135
136 // Verify the non-terminator operations separately so that we can verify
137 // they has no successors.
138 for (auto &op : llvm::make_range(block.begin(), std::prev(block.end()))) {
139 if (op.getNumSuccessors() != 0)
140 return op.emitError(
141 "operation with block successors must terminate its parent block");
142
143 if (failed(verifyOperation(op)))
144 return failure();
145 }
146
147 // Verify the terminator.
148 if (failed(verifyOperation(block.back())))
149 return failure();
150 if (block.back().isKnownNonTerminator())
151 return block.back().emitError("block with no terminator");
152
153 // Verify that this block is not branching to a block of a different
154 // region.
155 for (Block *successor : block.getSuccessors())
156 if (successor->getParent() != block.getParent())
157 return block.back().emitOpError(
158 "branching to block of a different region");
159
160 return success();
161 }
162
verifyOperation(Operation & op)163 LogicalResult OperationVerifier::verifyOperation(Operation &op) {
164 // Check that operands are non-nil and structurally ok.
165 for (auto operand : op.getOperands())
166 if (!operand)
167 return op.emitError("null operand found");
168
169 /// Verify that all of the attributes are okay.
170 for (auto attr : op.getAttrs()) {
171 // Check for any optional dialect specific attributes.
172 if (!attr.first.strref().contains('.'))
173 continue;
174 if (auto *dialect = getDialectForAttribute(attr))
175 if (failed(dialect->verifyOperationAttribute(&op, attr)))
176 return failure();
177 }
178
179 // If we can get operation info for this, check the custom hook.
180 auto *opInfo = op.getAbstractOperation();
181 if (opInfo && failed(opInfo->verifyInvariants(&op)))
182 return failure();
183
184 auto kindInterface = dyn_cast<mlir::RegionKindInterface>(op);
185
186 // Verify that all child regions are ok.
187 unsigned numRegions = op.getNumRegions();
188 for (unsigned i = 0; i < numRegions; i++) {
189 Region ®ion = op.getRegion(i);
190 // Check that Graph Regions only have a single basic block. This is
191 // similar to the code in SingleBlockImplicitTerminator, but doesn't
192 // require the trait to be specified. This arbitrary limitation is
193 // designed to limit the number of cases that have to be handled by
194 // transforms and conversions until the concept stabilizes.
195 if (op.isRegistered() && kindInterface &&
196 kindInterface.getRegionKind(i) == RegionKind::Graph) {
197 // Empty regions are fine.
198 if (region.empty())
199 continue;
200
201 // Non-empty regions must contain a single basic block.
202 if (std::next(region.begin()) != region.end())
203 return op.emitOpError("expects graph region #")
204 << i << " to have 0 or 1 blocks";
205 }
206 if (failed(verifyRegion(region)))
207 return failure();
208 }
209
210 // If this is a registered operation, there is nothing left to do.
211 if (opInfo)
212 return success();
213
214 // Otherwise, verify that the parent dialect allows un-registered operations.
215 auto dialectPrefix = op.getName().getDialect();
216
217 // Check for an existing answer for the operation dialect.
218 auto it = dialectAllowsUnknownOps.find(dialectPrefix);
219 if (it == dialectAllowsUnknownOps.end()) {
220 // If the operation dialect is registered, query it directly.
221 if (auto *dialect = ctx->getLoadedDialect(dialectPrefix))
222 it = dialectAllowsUnknownOps
223 .try_emplace(dialectPrefix, dialect->allowsUnknownOperations())
224 .first;
225 // Otherwise, unregistered dialects (when allowed by the context)
226 // conservatively allow unknown operations.
227 else {
228 if (!op.getContext()->allowsUnregisteredDialects() && !op.getDialect())
229 return op.emitOpError()
230 << "created with unregistered dialect. If this is "
231 "intended, please call allowUnregisteredDialects() on the "
232 "MLIRContext, or use -allow-unregistered-dialect with "
233 "mlir-opt";
234
235 it = dialectAllowsUnknownOps.try_emplace(dialectPrefix, true).first;
236 }
237 }
238
239 if (!it->second) {
240 return op.emitError("unregistered operation '")
241 << op.getName() << "' found in dialect ('" << dialectPrefix
242 << "') that does not allow unknown operations";
243 }
244
245 return success();
246 }
247
verifyDominance(Region & region)248 LogicalResult OperationVerifier::verifyDominance(Region ®ion) {
249 // Verify the dominance of each of the held operations.
250 for (Block &block : region) {
251 // Dominance is only meaningful inside reachable blocks.
252 if (domInfo->isReachableFromEntry(&block))
253 for (Operation &op : block)
254 // Check that operands properly dominate this use.
255 for (unsigned operandNo = 0, e = op.getNumOperands(); operandNo != e;
256 ++operandNo) {
257 auto operand = op.getOperand(operandNo);
258 if (domInfo->properlyDominates(operand, &op))
259 continue;
260
261 auto diag = op.emitError("operand #")
262 << operandNo << " does not dominate this use";
263 if (auto *useOp = operand.getDefiningOp())
264 diag.attachNote(useOp->getLoc()) << "operand defined here";
265 return failure();
266 }
267 // Recursively verify dominance within each operation in the
268 // block, even if the block itself is not reachable, or we are in
269 // a region which doesn't respect dominance.
270 for (Operation &op : block)
271 if (failed(verifyDominanceOfContainedRegions(op)))
272 return failure();
273 }
274 return success();
275 }
276
277 /// Verify the dominance of each of the nested blocks within the given operation
278 LogicalResult
verifyDominanceOfContainedRegions(Operation & op)279 OperationVerifier::verifyDominanceOfContainedRegions(Operation &op) {
280 for (Region ®ion : op.getRegions()) {
281 if (failed(verifyDominance(region)))
282 return failure();
283 }
284 return success();
285 }
286
287 //===----------------------------------------------------------------------===//
288 // Entrypoint
289 //===----------------------------------------------------------------------===//
290
291 /// Perform (potentially expensive) checks of invariants, used to detect
292 /// compiler bugs. On error, this reports the error through the MLIRContext and
293 /// returns failure.
verify(Operation * op)294 LogicalResult mlir::verify(Operation *op) {
295 return OperationVerifier(op->getContext()).verify(*op);
296 }
297