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 "mlir/IR/Threading.h"
34 #include "llvm/ADT/StringMap.h"
35 #include "llvm/Support/FormatVariadic.h"
36 #include "llvm/Support/PrettyStackTrace.h"
37 #include "llvm/Support/Regex.h"
38 #include <atomic>
39 
40 using namespace mlir;
41 
42 namespace {
43 /// This class encapsulates all the state used to verify an operation region.
44 class OperationVerifier {
45 public:
46   /// If `verifyRecursively` is true, then this will also recursively verify
47   /// nested operations.
48   explicit OperationVerifier(bool verifyRecursively)
49       : verifyRecursively(verifyRecursively) {}
50 
51   /// Verify the given operation.
52   LogicalResult verifyOpAndDominance(Operation &op);
53 
54 private:
55   LogicalResult
56   verifyBlock(Block &block,
57               SmallVectorImpl<Operation *> &opsWithIsolatedRegions);
58   /// Verify the properties and dominance relationships of this operation,
59   /// stopping region recursion at any "isolated from above operations".  Any
60   /// such ops are returned in the opsWithIsolatedRegions vector.
61   LogicalResult
62   verifyOperation(Operation &op,
63                   SmallVectorImpl<Operation *> &opsWithIsolatedRegions);
64 
65   /// Verify the dominance property of regions contained within the given
66   /// Operation.
67   LogicalResult verifyDominanceOfContainedRegions(Operation &op,
68                                                   DominanceInfo &domInfo);
69 
70   /// A flag indicating if this verifier should recursively verify nested
71   /// operations.
72   bool verifyRecursively;
73 };
74 } // namespace
75 
76 LogicalResult OperationVerifier::verifyOpAndDominance(Operation &op) {
77   SmallVector<Operation *> opsWithIsolatedRegions;
78 
79   // Verify the operation first, collecting any IsolatedFromAbove operations.
80   if (failed(verifyOperation(op, opsWithIsolatedRegions)))
81     return failure();
82 
83   // Since everything looks structurally ok to this point, we do a dominance
84   // check for any nested regions. We do this as a second pass since malformed
85   // CFG's can cause dominator analysis construction to crash and we want the
86   // verifier to be resilient to malformed code.
87   if (op.getNumRegions() != 0) {
88     DominanceInfo domInfo;
89     if (failed(verifyDominanceOfContainedRegions(op, domInfo)))
90       return failure();
91   }
92 
93   // If we aren't verifying nested operations, then we're done.
94   if (!verifyRecursively)
95     return success();
96 
97   // Otherwise, check the dominance properties and invariants of any operations
98   // in the regions contained by the 'opsWithIsolatedRegions' operations.
99   return failableParallelForEach(
100       op.getContext(), opsWithIsolatedRegions,
101       [&](Operation *op) { return verifyOpAndDominance(*op); });
102 }
103 
104 /// Returns true if this block may be valid without terminator. That is if:
105 /// - it does not have a parent region.
106 /// - Or the parent region have a single block and:
107 ///    - This region does not have a parent op.
108 ///    - Or the parent op is unregistered.
109 ///    - Or the parent op has the NoTerminator trait.
110 static bool mayBeValidWithoutTerminator(Block *block) {
111   if (!block->getParent())
112     return true;
113   if (!llvm::hasSingleElement(*block->getParent()))
114     return false;
115   Operation *op = block->getParentOp();
116   return !op || op->mightHaveTrait<OpTrait::NoTerminator>();
117 }
118 
119 LogicalResult OperationVerifier::verifyBlock(
120     Block &block, SmallVectorImpl<Operation *> &opsWithIsolatedRegions) {
121 
122   for (auto arg : block.getArguments())
123     if (arg.getOwner() != &block)
124       return emitError(arg.getLoc(), "block argument not owned by block");
125 
126   // Verify that this block has a terminator.
127   if (block.empty()) {
128     if (mayBeValidWithoutTerminator(&block))
129       return success();
130     return emitError(block.getParent()->getLoc(),
131                      "empty block: expect at least a terminator");
132   }
133 
134   // Check each operation, and make sure there are no branches out of the
135   // middle of this block.
136   for (Operation &op : block) {
137     // Only the last instructions is allowed to have successors.
138     if (op.getNumSuccessors() != 0 && &op != &block.back())
139       return op.emitError(
140           "operation with block successors must terminate its parent block");
141 
142     // If we aren't verifying recursievly, there is nothing left to check.
143     if (!verifyRecursively)
144       continue;
145 
146     // If this operation has regions and is IsolatedFromAbove, we defer
147     // checking.  This allows us to parallelize verification better.
148     if (op.getNumRegions() != 0 &&
149         op.hasTrait<OpTrait::IsIsolatedFromAbove>()) {
150       opsWithIsolatedRegions.push_back(&op);
151 
152       // Otherwise, check the operation inline.
153     } else if (failed(verifyOperation(op, opsWithIsolatedRegions))) {
154       return failure();
155     }
156   }
157 
158   // Verify that this block is not branching to a block of a different
159   // region.
160   for (Block *successor : block.getSuccessors())
161     if (successor->getParent() != block.getParent())
162       return block.back().emitOpError(
163           "branching to block of a different region");
164 
165   // If this block doesn't have to have a terminator, don't require it.
166   if (mayBeValidWithoutTerminator(&block))
167     return success();
168 
169   Operation &terminator = block.back();
170   if (!terminator.mightHaveTrait<OpTrait::IsTerminator>())
171     return block.back().emitError("block with no terminator, has ")
172            << terminator;
173 
174   return success();
175 }
176 
177 /// Verify the properties and dominance relationships of this operation,
178 /// stopping region recursion at any "isolated from above operations".  Any such
179 /// ops are returned in the opsWithIsolatedRegions vector.
180 LogicalResult OperationVerifier::verifyOperation(
181     Operation &op, SmallVectorImpl<Operation *> &opsWithIsolatedRegions) {
182   // Check that operands are non-nil and structurally ok.
183   for (auto operand : op.getOperands())
184     if (!operand)
185       return op.emitError("null operand found");
186 
187   /// Verify that all of the attributes are okay.
188   for (auto attr : op.getAttrs()) {
189     // Check for any optional dialect specific attributes.
190     if (auto *dialect = attr.getNameDialect())
191       if (failed(dialect->verifyOperationAttribute(&op, attr)))
192         return failure();
193   }
194 
195   // If we can get operation info for this, check the custom hook.
196   OperationName opName = op.getName();
197   Optional<RegisteredOperationName> registeredInfo = opName.getRegisteredInfo();
198   if (registeredInfo && failed(registeredInfo->verifyInvariants(&op)))
199     return failure();
200 
201   if (unsigned numRegions = op.getNumRegions()) {
202     auto kindInterface = dyn_cast<RegionKindInterface>(op);
203 
204     // Verify that all child regions are ok.
205     MutableArrayRef<Region> regions = op.getRegions();
206     for (unsigned i = 0; i < numRegions; ++i) {
207       Region &region = regions[i];
208       RegionKind kind =
209           kindInterface ? kindInterface.getRegionKind(i) : RegionKind::SSACFG;
210       // Check that Graph Regions only have a single basic block. This is
211       // similar to the code in SingleBlockImplicitTerminator, but doesn't
212       // require the trait to be specified. This arbitrary limitation is
213       // designed to limit the number of cases that have to be handled by
214       // transforms and conversions.
215       if (op.isRegistered() && kind == RegionKind::Graph) {
216         // Non-empty regions must contain a single basic block.
217         if (!region.empty() && !region.hasOneBlock())
218           return op.emitOpError("expects graph region #")
219                  << i << " to have 0 or 1 blocks";
220       }
221 
222       if (region.empty())
223         continue;
224 
225       // Verify the first block has no predecessors.
226       Block *firstBB = &region.front();
227       if (!firstBB->hasNoPredecessors())
228         return emitError(op.getLoc(),
229                          "entry block of region may not have predecessors");
230 
231       // Verify each of the blocks within the region if we are verifying
232       // recursively.
233       if (verifyRecursively) {
234         for (Block &block : region)
235           if (failed(verifyBlock(block, opsWithIsolatedRegions)))
236             return failure();
237       }
238     }
239   }
240 
241   // After the region ops are verified, run the verifiers that have additional
242   // region invariants need to veirfy.
243   if (registeredInfo && failed(registeredInfo->verifyRegionInvariants(&op)))
244     return failure();
245 
246   // If this is a registered operation, there is nothing left to do.
247   if (registeredInfo)
248     return success();
249 
250   // Otherwise, verify that the parent dialect allows un-registered operations.
251   Dialect *dialect = opName.getDialect();
252   if (!dialect) {
253     if (!op.getContext()->allowsUnregisteredDialects()) {
254       return op.emitOpError()
255              << "created with unregistered dialect. If this is "
256                 "intended, please call allowUnregisteredDialects() on the "
257                 "MLIRContext, or use -allow-unregistered-dialect with "
258                 "the MLIR opt tool used";
259     }
260     return success();
261   }
262 
263   if (!dialect->allowsUnknownOperations()) {
264     return op.emitError("unregistered operation '")
265            << op.getName() << "' found in dialect ('" << dialect->getNamespace()
266            << "') that does not allow unknown operations";
267   }
268 
269   return success();
270 }
271 
272 //===----------------------------------------------------------------------===//
273 // Dominance Checking
274 //===----------------------------------------------------------------------===//
275 
276 /// Emit an error when the specified operand of the specified operation is an
277 /// invalid use because of dominance properties.
278 static void diagnoseInvalidOperandDominance(Operation &op, unsigned operandNo) {
279   InFlightDiagnostic diag = op.emitError("operand #")
280                             << operandNo << " does not dominate this use";
281 
282   Value operand = op.getOperand(operandNo);
283 
284   /// Attach a note to an in-flight diagnostic that provide more information
285   /// about where an op operand is defined.
286   if (auto *useOp = operand.getDefiningOp()) {
287     Diagnostic &note = diag.attachNote(useOp->getLoc());
288     note << "operand defined here";
289     Block *block1 = op.getBlock();
290     Block *block2 = useOp->getBlock();
291     Region *region1 = block1->getParent();
292     Region *region2 = block2->getParent();
293     if (block1 == block2)
294       note << " (op in the same block)";
295     else if (region1 == region2)
296       note << " (op in the same region)";
297     else if (region2->isProperAncestor(region1))
298       note << " (op in a parent region)";
299     else if (region1->isProperAncestor(region2))
300       note << " (op in a child region)";
301     else
302       note << " (op is neither in a parent nor in a child region)";
303     return;
304   }
305   // Block argument case.
306   Block *block1 = op.getBlock();
307   Block *block2 = operand.cast<BlockArgument>().getOwner();
308   Region *region1 = block1->getParent();
309   Region *region2 = block2->getParent();
310   Location loc = UnknownLoc::get(op.getContext());
311   if (block2->getParentOp())
312     loc = block2->getParentOp()->getLoc();
313   Diagnostic &note = diag.attachNote(loc);
314   if (!region2) {
315     note << " (block without parent)";
316     return;
317   }
318   if (block1 == block2)
319     llvm::report_fatal_error("Internal error in dominance verification");
320   int index = std::distance(region2->begin(), block2->getIterator());
321   note << "operand defined as a block argument (block #" << index;
322   if (region1 == region2)
323     note << " in the same region)";
324   else if (region2->isProperAncestor(region1))
325     note << " in a parent region)";
326   else if (region1->isProperAncestor(region2))
327     note << " in a child region)";
328   else
329     note << " neither in a parent nor in a child region)";
330 }
331 
332 /// Verify the dominance of each of the nested blocks within the given operation
333 LogicalResult
334 OperationVerifier::verifyDominanceOfContainedRegions(Operation &op,
335                                                      DominanceInfo &domInfo) {
336   for (Region &region : op.getRegions()) {
337     // Verify the dominance of each of the held operations.
338     for (Block &block : region) {
339       // Dominance is only meaningful inside reachable blocks.
340       bool isReachable = domInfo.isReachableFromEntry(&block);
341 
342       for (Operation &op : block) {
343         if (isReachable) {
344           // Check that operands properly dominate this use.
345           for (const auto &operand : llvm::enumerate(op.getOperands())) {
346             if (domInfo.properlyDominates(operand.value(), &op))
347               continue;
348 
349             diagnoseInvalidOperandDominance(op, operand.index());
350             return failure();
351           }
352         }
353 
354         // Recursively verify dominance within each operation in the block, even
355         // if the block itself is not reachable, or we are in a region which
356         // doesn't respect dominance.
357         if (verifyRecursively && op.getNumRegions() != 0) {
358           // If this operation is IsolatedFromAbove, then we'll handle it in the
359           // outer verification loop.
360           if (op.hasTrait<OpTrait::IsIsolatedFromAbove>())
361             continue;
362 
363           if (failed(verifyDominanceOfContainedRegions(op, domInfo)))
364             return failure();
365         }
366       }
367     }
368   }
369   return success();
370 }
371 
372 //===----------------------------------------------------------------------===//
373 // Entrypoint
374 //===----------------------------------------------------------------------===//
375 
376 LogicalResult mlir::verify(Operation *op, bool verifyRecursively) {
377   OperationVerifier verifier(verifyRecursively);
378   return verifier.verifyOpAndDominance(*op);
379 }
380