1 //===- Verifier.cpp - MLIR Verifier Implementation ------------------------===//
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
7 //===----------------------------------------------------------------------===//
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
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
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.
25 //===----------------------------------------------------------------------===//
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 "mlir/IR/Threading.h"
34 #include "llvm/ADT/DenseMapInfoVariant.h"
35 #include "llvm/ADT/StringMap.h"
36 #include "llvm/Support/FormatVariadic.h"
37 #include "llvm/Support/PrettyStackTrace.h"
38 #include "llvm/Support/Regex.h"
45 /// This class encapsulates all the state used to verify an operation region.
46 class OperationVerifier
{
48 /// If `verifyRecursively` is true, then this will also recursively verify
49 /// nested operations.
50 explicit OperationVerifier(bool verifyRecursively
)
51 : verifyRecursively(verifyRecursively
) {}
53 /// Verify the given operation.
54 LogicalResult
verifyOpAndDominance(Operation
&op
);
57 using WorkItem
= llvm::PointerUnion
<Operation
*, Block
*>;
59 /// This verifier uses a DFS of the tree of operations/blocks. The method
60 /// verifyOnEntrance is invoked when we visit a node for the first time, i.e.
61 /// before visiting its children. The method verifyOnExit is invoked
62 /// upon exit from the subtree, i.e. when we visit a node for the second time.
63 LogicalResult
verifyOnEntrance(Block
&block
);
64 LogicalResult
verifyOnEntrance(Operation
&op
);
66 LogicalResult
verifyOnExit(Block
&block
);
67 LogicalResult
verifyOnExit(Operation
&op
);
69 /// Verify the properties and dominance relationships of this operation.
70 LogicalResult
verifyOperation(Operation
&op
);
72 /// Verify the dominance property of regions contained within the given
74 LogicalResult
verifyDominanceOfContainedRegions(Operation
&op
,
75 DominanceInfo
&domInfo
);
77 /// A flag indicating if this verifier should recursively verify nested
79 bool verifyRecursively
;
83 LogicalResult
OperationVerifier::verifyOpAndDominance(Operation
&op
) {
84 // Verify the operation first, collecting any IsolatedFromAbove operations.
85 if (failed(verifyOperation(op
)))
88 // Since everything looks structurally ok to this point, we do a dominance
89 // check for any nested regions. We do this as a second pass since malformed
90 // CFG's can cause dominator analysis construction to crash and we want the
91 // verifier to be resilient to malformed code.
92 if (op
.getNumRegions() != 0) {
93 DominanceInfo domInfo
;
94 if (failed(verifyDominanceOfContainedRegions(op
, domInfo
)))
101 /// Returns true if this block may be valid without terminator. That is if:
102 /// - it does not have a parent region.
103 /// - Or the parent region have a single block and:
104 /// - This region does not have a parent op.
105 /// - Or the parent op is unregistered.
106 /// - Or the parent op has the NoTerminator trait.
107 static bool mayBeValidWithoutTerminator(Block
*block
) {
108 if (!block
->getParent())
110 if (!llvm::hasSingleElement(*block
->getParent()))
112 Operation
*op
= block
->getParentOp();
113 return !op
|| op
->mightHaveTrait
<OpTrait::NoTerminator
>();
116 LogicalResult
OperationVerifier::verifyOnEntrance(Block
&block
) {
117 for (auto arg
: block
.getArguments())
118 if (arg
.getOwner() != &block
)
119 return emitError(arg
.getLoc(), "block argument not owned by block");
121 // Verify that this block has a terminator.
123 if (mayBeValidWithoutTerminator(&block
))
125 return emitError(block
.getParent()->getLoc(),
126 "empty block: expect at least a terminator");
129 // Check each operation, and make sure there are no branches out of the
130 // middle of this block.
131 for (Operation
&op
: block
) {
132 // Only the last instructions is allowed to have successors.
133 if (op
.getNumSuccessors() != 0 && &op
!= &block
.back())
135 "operation with block successors must terminate its parent block");
141 LogicalResult
OperationVerifier::verifyOnExit(Block
&block
) {
142 // Verify that this block is not branching to a block of a different
144 for (Block
*successor
: block
.getSuccessors())
145 if (successor
->getParent() != block
.getParent())
146 return block
.back().emitOpError(
147 "branching to block of a different region");
149 // If this block doesn't have to have a terminator, don't require it.
150 if (mayBeValidWithoutTerminator(&block
))
153 Operation
&terminator
= block
.back();
154 if (!terminator
.mightHaveTrait
<OpTrait::IsTerminator
>())
155 return block
.back().emitError("block with no terminator, has ")
161 LogicalResult
OperationVerifier::verifyOnEntrance(Operation
&op
) {
162 // Check that operands are non-nil and structurally ok.
163 for (auto operand
: op
.getOperands())
165 return op
.emitError("null operand found");
167 /// Verify that all of the attributes are okay.
168 for (auto attr
: op
.getDiscardableAttrDictionary()) {
169 // Check for any optional dialect specific attributes.
170 if (auto *dialect
= attr
.getNameDialect())
171 if (failed(dialect
->verifyOperationAttribute(&op
, attr
)))
175 // If we can get operation info for this, check the custom hook.
176 OperationName opName
= op
.getName();
177 std::optional
<RegisteredOperationName
> registeredInfo
=
178 opName
.getRegisteredInfo();
179 if (registeredInfo
&& failed(registeredInfo
->verifyInvariants(&op
)))
182 unsigned numRegions
= op
.getNumRegions();
185 auto kindInterface
= dyn_cast
<RegionKindInterface
>(&op
);
186 SmallVector
<Operation
*> opsWithIsolatedRegions
;
187 // Verify that all child regions are ok.
188 MutableArrayRef
<Region
> regions
= op
.getRegions();
189 for (unsigned i
= 0; i
< numRegions
; ++i
) {
190 Region
®ion
= regions
[i
];
192 kindInterface
? kindInterface
.getRegionKind(i
) : RegionKind::SSACFG
;
193 // Check that Graph Regions only have a single basic block. This is
194 // similar to the code in SingleBlockImplicitTerminator, but doesn't
195 // require the trait to be specified. This arbitrary limitation is
196 // designed to limit the number of cases that have to be handled by
197 // transforms and conversions.
198 if (op
.isRegistered() && kind
== RegionKind::Graph
) {
199 // Non-empty regions must contain a single basic block.
200 if (!region
.empty() && !region
.hasOneBlock())
201 return op
.emitOpError("expects graph region #")
202 << i
<< " to have 0 or 1 blocks";
208 // Verify the first block has no predecessors.
209 Block
*firstBB
= ®ion
.front();
210 if (!firstBB
->hasNoPredecessors())
211 return emitError(op
.getLoc(),
212 "entry block of region may not have predecessors");
217 LogicalResult
OperationVerifier::verifyOnExit(Operation
&op
) {
218 SmallVector
<Operation
*> opsWithIsolatedRegions
;
219 if (verifyRecursively
) {
220 for (Region
®ion
: op
.getRegions())
221 for (Block
&block
: region
)
222 for (Operation
&o
: block
)
223 if (o
.getNumRegions() != 0 &&
224 o
.hasTrait
<OpTrait::IsIsolatedFromAbove
>())
225 opsWithIsolatedRegions
.push_back(&o
);
227 if (failed(failableParallelForEach(
228 op
.getContext(), opsWithIsolatedRegions
,
229 [&](Operation
*o
) { return verifyOpAndDominance(*o
); })))
231 OperationName opName
= op
.getName();
232 std::optional
<RegisteredOperationName
> registeredInfo
=
233 opName
.getRegisteredInfo();
234 // After the region ops are verified, run the verifiers that have additional
235 // region invariants need to veirfy.
236 if (registeredInfo
&& failed(registeredInfo
->verifyRegionInvariants(&op
)))
239 // If this is a registered operation, there is nothing left to do.
243 // Otherwise, verify that the parent dialect allows un-registered operations.
244 Dialect
*dialect
= opName
.getDialect();
246 if (!op
.getContext()->allowsUnregisteredDialects()) {
247 return op
.emitOpError()
248 << "created with unregistered dialect. If this is "
249 "intended, please call allowUnregisteredDialects() on the "
250 "MLIRContext, or use -allow-unregistered-dialect with "
251 "the MLIR opt tool used";
256 if (!dialect
->allowsUnknownOperations()) {
257 return op
.emitError("unregistered operation '")
258 << op
.getName() << "' found in dialect ('" << dialect
->getNamespace()
259 << "') that does not allow unknown operations";
265 /// Verify the properties and dominance relationships of this operation,
266 /// stopping region "recursion" at any "isolated from above operations".
267 /// Such ops are collected separately and verified inside
268 /// verifyBlockPostChildren.
269 LogicalResult
OperationVerifier::verifyOperation(Operation
&op
) {
270 SmallVector
<WorkItem
> worklist
{{&op
}};
271 DenseSet
<WorkItem
> seen
;
272 while (!worklist
.empty()) {
273 WorkItem top
= worklist
.back();
275 auto visit
= [](auto &&visitor
, WorkItem w
) {
276 if (w
.is
<Operation
*>())
277 return visitor(w
.get
<Operation
*>());
278 return visitor(w
.get
<Block
*>());
281 const bool isExit
= !seen
.insert(top
).second
;
282 // 2nd visit of this work item ("exit").
286 [this](auto *workItem
) { return verifyOnExit(*workItem
); }, top
)))
291 // 1st visit of this work item ("entrance").
293 [this](auto *workItem
) { return verifyOnEntrance(*workItem
); },
297 if (top
.is
<Block
*>()) {
298 Block
¤tBlock
= *top
.get
<Block
*>();
299 // Skip "isolated from above operations".
300 for (Operation
&o
: llvm::reverse(currentBlock
)) {
301 if (o
.getNumRegions() == 0 ||
302 !o
.hasTrait
<OpTrait::IsIsolatedFromAbove
>())
303 worklist
.emplace_back(&o
);
308 Operation
¤tOp
= *top
.get
<Operation
*>();
309 if (verifyRecursively
)
310 for (Region
®ion
: llvm::reverse(currentOp
.getRegions()))
311 for (Block
&block
: llvm::reverse(region
))
312 worklist
.emplace_back(&block
);
317 //===----------------------------------------------------------------------===//
318 // Dominance Checking
319 //===----------------------------------------------------------------------===//
321 /// Emit an error when the specified operand of the specified operation is an
322 /// invalid use because of dominance properties.
323 static void diagnoseInvalidOperandDominance(Operation
&op
, unsigned operandNo
) {
324 InFlightDiagnostic diag
= op
.emitError("operand #")
325 << operandNo
<< " does not dominate this use";
327 Value operand
= op
.getOperand(operandNo
);
329 /// Attach a note to an in-flight diagnostic that provide more information
330 /// about where an op operand is defined.
331 if (auto *useOp
= operand
.getDefiningOp()) {
332 Diagnostic
¬e
= diag
.attachNote(useOp
->getLoc());
333 note
<< "operand defined here";
334 Block
*block1
= op
.getBlock();
335 Block
*block2
= useOp
->getBlock();
336 Region
*region1
= block1
->getParent();
337 Region
*region2
= block2
->getParent();
338 if (block1
== block2
)
339 note
<< " (op in the same block)";
340 else if (region1
== region2
)
341 note
<< " (op in the same region)";
342 else if (region2
->isProperAncestor(region1
))
343 note
<< " (op in a parent region)";
344 else if (region1
->isProperAncestor(region2
))
345 note
<< " (op in a child region)";
347 note
<< " (op is neither in a parent nor in a child region)";
350 // Block argument case.
351 Block
*block1
= op
.getBlock();
352 Block
*block2
= llvm::cast
<BlockArgument
>(operand
).getOwner();
353 Region
*region1
= block1
->getParent();
354 Region
*region2
= block2
->getParent();
355 Location loc
= UnknownLoc::get(op
.getContext());
356 if (block2
->getParentOp())
357 loc
= block2
->getParentOp()->getLoc();
358 Diagnostic
¬e
= diag
.attachNote(loc
);
360 note
<< " (block without parent)";
363 if (block1
== block2
)
364 llvm::report_fatal_error("Internal error in dominance verification");
365 int index
= std::distance(region2
->begin(), block2
->getIterator());
366 note
<< "operand defined as a block argument (block #" << index
;
367 if (region1
== region2
)
368 note
<< " in the same region)";
369 else if (region2
->isProperAncestor(region1
))
370 note
<< " in a parent region)";
371 else if (region1
->isProperAncestor(region2
))
372 note
<< " in a child region)";
374 note
<< " neither in a parent nor in a child region)";
377 /// Verify the dominance of each of the nested blocks within the given operation
379 OperationVerifier::verifyDominanceOfContainedRegions(Operation
&op
,
380 DominanceInfo
&domInfo
) {
381 for (Region
®ion
: op
.getRegions()) {
382 // Verify the dominance of each of the held operations.
383 for (Block
&block
: region
) {
384 // Dominance is only meaningful inside reachable blocks.
385 bool isReachable
= domInfo
.isReachableFromEntry(&block
);
387 for (Operation
&op
: block
) {
389 // Check that operands properly dominate this use.
390 for (const auto &operand
: llvm::enumerate(op
.getOperands())) {
391 if (domInfo
.properlyDominates(operand
.value(), &op
))
394 diagnoseInvalidOperandDominance(op
, operand
.index());
399 // Recursively verify dominance within each operation in the block, even
400 // if the block itself is not reachable, or we are in a region which
401 // doesn't respect dominance.
402 if (verifyRecursively
&& op
.getNumRegions() != 0) {
403 // If this operation is IsolatedFromAbove, then we'll handle it in the
404 // outer verification loop.
405 if (op
.hasTrait
<OpTrait::IsIsolatedFromAbove
>())
408 if (failed(verifyDominanceOfContainedRegions(op
, domInfo
)))
417 //===----------------------------------------------------------------------===//
419 //===----------------------------------------------------------------------===//
421 LogicalResult
mlir::verify(Operation
*op
, bool verifyRecursively
) {
422 OperationVerifier
verifier(verifyRecursively
);
423 return verifier
.verifyOpAndDominance(*op
);