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 "llvm/ADT/StringMap.h"
33 #include "llvm/Support/FormatVariadic.h"
34 #include "llvm/Support/PrettyStackTrace.h"
35 #include "llvm/Support/Regex.h"
36 
37 using namespace mlir;
38 
39 namespace {
40 /// This class encapsulates all the state used to verify an operation region.
41 class OperationVerifier {
42 public:
43   explicit OperationVerifier(MLIRContext *ctx) : ctx(ctx) {}
44 
45   /// Verify the given operation.
46   LogicalResult verify(Operation &op);
47 
48   /// Returns the registered dialect for a dialect-specific attribute.
49   Dialect *getDialectForAttribute(const NamedAttribute &attr) {
50     assert(attr.first.strref().contains('.') && "expected dialect attribute");
51     auto dialectNamePair = attr.first.strref().split('.');
52     return ctx->getRegisteredDialect(dialectNamePair.first);
53   }
54 
55 private:
56   /// Verify the given potentially nested region or block.
57   LogicalResult verifyRegion(Region &region);
58   LogicalResult verifyBlock(Block &block);
59   LogicalResult verifyOperation(Operation &op);
60 
61   /// Verify the dominance within the given IR unit.
62   LogicalResult verifyDominance(Region &region);
63   LogicalResult verifyDominance(Operation &op);
64 
65   /// Emit an error for the given block.
66   InFlightDiagnostic emitError(Block &bb, const Twine &message) {
67     // Take the location information for the first operation in the block.
68     if (!bb.empty())
69       return bb.front().emitError(message);
70 
71     // Worst case, fall back to using the parent's location.
72     return mlir::emitError(bb.getParent()->getLoc(), message);
73   }
74 
75   /// The current context for the verifier.
76   MLIRContext *ctx;
77 
78   /// Dominance information for this operation, when checking dominance.
79   DominanceInfo *domInfo = nullptr;
80 
81   /// Mapping between dialect namespace and if that dialect supports
82   /// unregistered operations.
83   llvm::StringMap<bool> dialectAllowsUnknownOps;
84 };
85 } // end anonymous namespace
86 
87 /// Verify the given operation.
88 LogicalResult OperationVerifier::verify(Operation &op) {
89   // Verify the operation first.
90   if (failed(verifyOperation(op)))
91     return failure();
92 
93   // Since everything looks structurally ok to this point, we do a dominance
94   // check for any nested regions. We do this as a second pass since malformed
95   // CFG's can cause dominator analysis constructure to crash and we want the
96   // verifier to be resilient to malformed code.
97   DominanceInfo theDomInfo(&op);
98   domInfo = &theDomInfo;
99   for (auto &region : op.getRegions())
100     if (failed(verifyDominance(region)))
101       return failure();
102 
103   domInfo = nullptr;
104   return success();
105 }
106 
107 LogicalResult OperationVerifier::verifyRegion(Region &region) {
108   if (region.empty())
109     return success();
110 
111   // Verify the first block has no predecessors.
112   auto *firstBB = &region.front();
113   if (!firstBB->hasNoPredecessors())
114     return mlir::emitError(region.getLoc(),
115                            "entry block of region may not have predecessors");
116 
117   // Verify each of the blocks within the region.
118   for (auto &block : region)
119     if (failed(verifyBlock(block)))
120       return failure();
121   return success();
122 }
123 
124 LogicalResult OperationVerifier::verifyBlock(Block &block) {
125   for (auto arg : block.getArguments())
126     if (arg.getOwner() != &block)
127       return emitError(block, "block argument not owned by block");
128 
129   // Verify that this block has a terminator.
130   if (block.empty())
131     return emitError(block, "block with no terminator");
132 
133   // Verify the non-terminator operations separately so that we can verify
134   // they has no successors.
135   for (auto &op : llvm::make_range(block.begin(), std::prev(block.end()))) {
136     if (op.getNumSuccessors() != 0)
137       return op.emitError(
138           "operation with block successors must terminate its parent block");
139 
140     if (failed(verifyOperation(op)))
141       return failure();
142   }
143 
144   // Verify the terminator.
145   if (failed(verifyOperation(block.back())))
146     return failure();
147   if (block.back().isKnownNonTerminator())
148     return emitError(block, "block with no terminator");
149 
150   // Verify that this block is not branching to a block of a different
151   // region.
152   for (Block *successor : block.getSuccessors())
153     if (successor->getParent() != block.getParent())
154       return block.back().emitOpError(
155           "branching to block of a different region");
156 
157   return success();
158 }
159 
160 LogicalResult OperationVerifier::verifyOperation(Operation &op) {
161   // Check that operands are non-nil and structurally ok.
162   for (auto operand : op.getOperands())
163     if (!operand)
164       return op.emitError("null operand found");
165 
166   /// Verify that all of the attributes are okay.
167   for (auto attr : op.getAttrs()) {
168     // Check for any optional dialect specific attributes.
169     if (!attr.first.strref().contains('.'))
170       continue;
171     if (auto *dialect = getDialectForAttribute(attr))
172       if (failed(dialect->verifyOperationAttribute(&op, attr)))
173         return failure();
174   }
175 
176   // If we can get operation info for this, check the custom hook.
177   auto *opInfo = op.getAbstractOperation();
178   if (opInfo && failed(opInfo->verifyInvariants(&op)))
179     return failure();
180 
181   // Verify that all child regions are ok.
182   for (auto &region : op.getRegions())
183     if (failed(verifyRegion(region)))
184       return failure();
185 
186   // If this is a registered operation, there is nothing left to do.
187   if (opInfo)
188     return success();
189 
190   // Otherwise, verify that the parent dialect allows un-registered operations.
191   auto dialectPrefix = op.getName().getDialect();
192 
193   // Check for an existing answer for the operation dialect.
194   auto it = dialectAllowsUnknownOps.find(dialectPrefix);
195   if (it == dialectAllowsUnknownOps.end()) {
196     // If the operation dialect is registered, query it directly.
197     if (auto *dialect = ctx->getRegisteredDialect(dialectPrefix))
198       it = dialectAllowsUnknownOps
199                .try_emplace(dialectPrefix, dialect->allowsUnknownOperations())
200                .first;
201     // Otherwise, unregistered dialects (when allowed by the context)
202     // conservatively allow unknown operations.
203     else {
204       if (!op.getContext()->allowsUnregisteredDialects() && !op.getDialect())
205         return op.emitOpError()
206                << "created with unregistered dialect. If this is "
207                   "intended, please call allowUnregisteredDialects() on the "
208                   "MLIRContext, or use -allow-unregistered-dialect with "
209                   "mlir-opt";
210 
211       it = dialectAllowsUnknownOps.try_emplace(dialectPrefix, true).first;
212     }
213   }
214 
215   if (!it->second) {
216     return op.emitError("unregistered operation '")
217            << op.getName() << "' found in dialect ('" << dialectPrefix
218            << "') that does not allow unknown operations";
219   }
220 
221   return success();
222 }
223 
224 LogicalResult OperationVerifier::verifyDominance(Region &region) {
225   // Verify the dominance of each of the held operations.
226   for (auto &block : region)
227     // Dominance is only reachable inside reachable blocks.
228     if (domInfo->isReachableFromEntry(&block))
229       for (auto &op : block) {
230         if (failed(verifyDominance(op)))
231           return failure();
232       }
233     else
234       // Verify the dominance of each of the nested blocks within this
235       // operation, even if the operation itself is not reachable.
236       for (auto &op : block)
237         for (auto &region : op.getRegions())
238           if (failed(verifyDominance(region)))
239             return failure();
240   return success();
241 }
242 
243 LogicalResult OperationVerifier::verifyDominance(Operation &op) {
244   // Check that operands properly dominate this use.
245   for (unsigned operandNo = 0, e = op.getNumOperands(); operandNo != e;
246        ++operandNo) {
247     auto operand = op.getOperand(operandNo);
248     if (domInfo->properlyDominates(operand, &op))
249       continue;
250 
251     auto diag = op.emitError("operand #")
252                 << operandNo << " does not dominate this use";
253     if (auto *useOp = operand.getDefiningOp())
254       diag.attachNote(useOp->getLoc()) << "operand defined here";
255     return failure();
256   }
257 
258   // Verify the dominance of each of the nested blocks within this operation.
259   for (auto &region : op.getRegions())
260     if (failed(verifyDominance(region)))
261       return failure();
262 
263   return success();
264 }
265 
266 //===----------------------------------------------------------------------===//
267 // Entrypoint
268 //===----------------------------------------------------------------------===//
269 
270 /// Perform (potentially expensive) checks of invariants, used to detect
271 /// compiler bugs.  On error, this reports the error through the MLIRContext and
272 /// returns failure.
273 LogicalResult mlir::verify(Operation *op) {
274   return OperationVerifier(op->getContext()).verify(*op);
275 }
276