github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Analysis/Verifier.cpp (about) 1 //===- Verifier.cpp - MLIR Verifier Implementation ------------------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 // 18 // This file implements the verify() methods on the various IR types, performing 19 // (potentially expensive) checks on the holistic structure of the code. This 20 // can be used for detecting bugs in compiler transformations and hand written 21 // .mlir files. 22 // 23 // The checks in this file are only for things that can occur as part of IR 24 // transformations: e.g. violation of dominance information, malformed operation 25 // attributes, etc. MLIR supports transformations moving IR through locally 26 // invalid states (e.g. unlinking an operation from a block before re-inserting 27 // it in a new place), but each transformation must complete with the IR in a 28 // valid form. 29 // 30 // This should not check for things that are always wrong by construction (e.g. 31 // attributes or other immutable structures that are incorrect), because those 32 // are not mutable and can be checked at time of construction. 33 // 34 //===----------------------------------------------------------------------===// 35 36 #include "mlir/Analysis/Verifier.h" 37 #include "mlir/Analysis/Dominance.h" 38 #include "mlir/IR/Attributes.h" 39 #include "mlir/IR/Dialect.h" 40 #include "mlir/IR/Operation.h" 41 #include "llvm/Support/FormatVariadic.h" 42 #include "llvm/Support/PrettyStackTrace.h" 43 #include "llvm/Support/Regex.h" 44 using namespace mlir; 45 46 namespace { 47 /// This class encapsulates all the state used to verify an operation region. 48 class OperationVerifier { 49 public: 50 explicit OperationVerifier(MLIRContext *ctx) 51 : ctx(ctx), identifierRegex("^[a-zA-Z_][a-zA-Z_0-9\\.\\$]*$") {} 52 53 /// Verify the given operation. 54 LogicalResult verify(Operation &op); 55 56 /// Returns the registered dialect for a dialect-specific attribute. 57 Dialect *getDialectForAttribute(const NamedAttribute &attr) { 58 assert(attr.first.strref().contains('.') && "expected dialect attribute"); 59 auto dialectNamePair = attr.first.strref().split('.'); 60 return ctx->getRegisteredDialect(dialectNamePair.first); 61 } 62 63 /// Returns if the given string is valid to use as an identifier name. 64 bool isValidName(StringRef name) { return identifierRegex.match(name); } 65 66 private: 67 /// Verify the given potentially nested region or block. 68 LogicalResult verifyRegion(Region ®ion); 69 LogicalResult verifyBlock(Block &block); 70 LogicalResult verifyOperation(Operation &op); 71 72 /// Verify the dominance within the given IR unit. 73 LogicalResult verifyDominance(Region ®ion); 74 LogicalResult verifyDominance(Operation &op); 75 76 /// Emit an error for the given block. 77 InFlightDiagnostic emitError(Block &bb, const Twine &message) { 78 // Take the location information for the first operation in the block. 79 if (!bb.empty()) 80 return bb.front().emitError(message); 81 82 // Worst case, fall back to using the parent's location. 83 return mlir::emitError(bb.getParent()->getLoc(), message); 84 } 85 86 /// The current context for the verifier. 87 MLIRContext *ctx; 88 89 /// Dominance information for this operation, when checking dominance. 90 DominanceInfo *domInfo = nullptr; 91 92 /// Regex checker for attribute names. 93 llvm::Regex identifierRegex; 94 95 /// Mapping between dialect namespace and if that dialect supports 96 /// unregistered operations. 97 llvm::StringMap<bool> dialectAllowsUnknownOps; 98 }; 99 } // end anonymous namespace 100 101 /// Verify the given operation. 102 LogicalResult OperationVerifier::verify(Operation &op) { 103 // Verify the operation first. 104 if (failed(verifyOperation(op))) 105 return failure(); 106 107 // Since everything looks structurally ok to this point, we do a dominance 108 // check for any nested regions. We do this as a second pass since malformed 109 // CFG's can cause dominator analysis constructure to crash and we want the 110 // verifier to be resilient to malformed code. 111 DominanceInfo theDomInfo(&op); 112 domInfo = &theDomInfo; 113 for (auto ®ion : op.getRegions()) 114 if (failed(verifyDominance(region))) 115 return failure(); 116 117 domInfo = nullptr; 118 return success(); 119 } 120 121 LogicalResult OperationVerifier::verifyRegion(Region ®ion) { 122 if (region.empty()) 123 return success(); 124 125 // Verify the first block has no predecessors. 126 auto *firstBB = ®ion.front(); 127 if (!firstBB->hasNoPredecessors()) 128 return mlir::emitError(region.getLoc(), 129 "entry block of region may not have predecessors"); 130 131 // Verify each of the blocks within the region. 132 for (auto &block : region) 133 if (failed(verifyBlock(block))) 134 return failure(); 135 return success(); 136 } 137 138 LogicalResult OperationVerifier::verifyBlock(Block &block) { 139 for (auto *arg : block.getArguments()) 140 if (arg->getOwner() != &block) 141 return emitError(block, "block argument not owned by block"); 142 143 // Verify that this block has a terminator. 144 if (block.empty()) 145 return emitError(block, "block with no terminator"); 146 147 // Verify the non-terminator operations separately so that we can verify 148 // they has no successors. 149 for (auto &op : llvm::make_range(block.begin(), std::prev(block.end()))) { 150 if (op.getNumSuccessors() != 0) 151 return op.emitError( 152 "operation with block successors must terminate its parent block"); 153 154 if (failed(verifyOperation(op))) 155 return failure(); 156 } 157 158 // Verify the terminator. 159 if (failed(verifyOperation(block.back()))) 160 return failure(); 161 if (block.back().isKnownNonTerminator()) 162 return emitError(block, "block with no terminator"); 163 164 // Verify that this block is not branching to a block of a different 165 // region. 166 for (Block *successor : block.getSuccessors()) 167 if (successor->getParent() != block.getParent()) 168 return block.back().emitOpError( 169 "branching to block of a different region"); 170 171 return success(); 172 } 173 174 LogicalResult OperationVerifier::verifyOperation(Operation &op) { 175 // Check that operands are non-nil and structurally ok. 176 for (auto *operand : op.getOperands()) 177 if (!operand) 178 return op.emitError("null operand found"); 179 180 /// Verify that all of the attributes are okay. 181 for (auto attr : op.getAttrs()) { 182 if (!identifierRegex.match(attr.first)) 183 return op.emitError("invalid attribute name '") << attr.first << "'"; 184 185 // Check for any optional dialect specific attributes. 186 if (!attr.first.strref().contains('.')) 187 continue; 188 if (auto *dialect = getDialectForAttribute(attr)) 189 if (failed(dialect->verifyOperationAttribute(&op, attr))) 190 return failure(); 191 } 192 193 // If we can get operation info for this, check the custom hook. 194 auto *opInfo = op.getAbstractOperation(); 195 if (opInfo && failed(opInfo->verifyInvariants(&op))) 196 return failure(); 197 198 // Verify that all child regions are ok. 199 for (auto ®ion : op.getRegions()) 200 if (failed(verifyRegion(region))) 201 return failure(); 202 203 // If this is a registered operation, there is nothing left to do. 204 if (opInfo) 205 return success(); 206 207 // Otherwise, verify that the parent dialect allows un-registered operations. 208 auto dialectPrefix = op.getName().getDialect(); 209 210 // Check for an existing answer for the operation dialect. 211 auto it = dialectAllowsUnknownOps.find(dialectPrefix); 212 if (it == dialectAllowsUnknownOps.end()) { 213 // If the operation dialect is registered, query it directly. 214 if (auto *dialect = ctx->getRegisteredDialect(dialectPrefix)) 215 it = dialectAllowsUnknownOps 216 .try_emplace(dialectPrefix, dialect->allowsUnknownOperations()) 217 .first; 218 // Otherwise, conservatively allow unknown operations. 219 else 220 it = dialectAllowsUnknownOps.try_emplace(dialectPrefix, true).first; 221 } 222 223 if (!it->second) { 224 return op.emitError("unregistered operation '") 225 << op.getName() << "' found in dialect ('" << dialectPrefix 226 << "') that does not allow unknown operations"; 227 } 228 229 return success(); 230 } 231 232 LogicalResult OperationVerifier::verifyDominance(Region ®ion) { 233 // Verify the dominance of each of the held operations. 234 for (auto &block : region) 235 for (auto &op : block) 236 if (failed(verifyDominance(op))) 237 return failure(); 238 return success(); 239 } 240 241 LogicalResult OperationVerifier::verifyDominance(Operation &op) { 242 // Check that operands properly dominate this use. 243 for (unsigned operandNo = 0, e = op.getNumOperands(); operandNo != e; 244 ++operandNo) { 245 auto *operand = op.getOperand(operandNo); 246 if (domInfo->properlyDominates(operand, &op)) 247 continue; 248 249 auto diag = op.emitError("operand #") 250 << operandNo << " does not dominate this use"; 251 if (auto *useOp = operand->getDefiningOp()) 252 diag.attachNote(useOp->getLoc()) << "operand defined here"; 253 return failure(); 254 } 255 256 // Verify the dominance of each of the nested blocks within this operation. 257 for (auto ®ion : op.getRegions()) 258 if (failed(verifyDominance(region))) 259 return failure(); 260 261 return success(); 262 } 263 264 //===----------------------------------------------------------------------===// 265 // Entrypoint 266 //===----------------------------------------------------------------------===// 267 268 /// Perform (potentially expensive) checks of invariants, used to detect 269 /// compiler bugs. On error, this reports the error through the MLIRContext and 270 /// returns failure. 271 LogicalResult mlir::verify(Operation *op) { 272 return OperationVerifier(op->getContext()).verify(*op); 273 }