From: River Riddle Date: Tue, 11 Jun 2019 01:37:09 +0000 (-0700) Subject: Add a general Operation::verify that verifies an operation instance and the dominance... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=65c94470ed5bb147b4e0300c164aca0e5466cf02;p=platform%2Fupstream%2Fllvm.git Add a general Operation::verify that verifies an operation instance and the dominance of operations in any nested regions. PiperOrigin-RevId: 252529850 --- diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h index f974947..e354891 100644 --- a/mlir/include/mlir/IR/Operation.h +++ b/mlir/include/mlir/IR/Operation.h @@ -158,6 +158,11 @@ public: /// take O(N) where N is the number of operations within the parent block. bool isBeforeInBlock(Operation *other); + /// Perform (potentially expensive) checks of invariants, used to detect + /// compiler bugs. On error, this reports the error through the MLIRContext + /// and returns failure. + LogicalResult verify(); + void print(raw_ostream &os); void dump(); diff --git a/mlir/lib/Analysis/Dominance.cpp b/mlir/lib/Analysis/Dominance.cpp index 2c9ec00..954a01b 100644 --- a/mlir/lib/Analysis/Dominance.cpp +++ b/mlir/lib/Analysis/Dominance.cpp @@ -106,8 +106,12 @@ bool DominanceInfoBase::properlyDominates(Block *a, Block *b) { } // Otherwise, use the standard dominance functionality. + + // If we don't have a dominance information for this region, assume that b is + // dominated by anything. auto baseInfoIt = dominanceInfos.find(regionA); - assert(baseInfoIt != dominanceInfos.end() && "region info not found"); + if (baseInfoIt == dominanceInfos.end()) + return true; return baseInfoIt->second->properlyDominates(a, b); } diff --git a/mlir/lib/Analysis/Verifier.cpp b/mlir/lib/Analysis/Verifier.cpp index e1f6f28..9e722e4 100644 --- a/mlir/lib/Analysis/Verifier.cpp +++ b/mlir/lib/Analysis/Verifier.cpp @@ -55,6 +55,9 @@ public: /// Verify the body of the given function. LogicalResult verify(Function &fn); + /// Verify the given operation. + LogicalResult verify(Operation &op); + /// Returns the registered dialect for a dialect-specific attribute. Dialect *getDialectForAttribute(const NamedAttribute &attr) { assert(attr.first.strref().contains('.') && "expected dialect attribute"); @@ -67,13 +70,12 @@ public: private: /// Verify the given potentially nested region or block. - LogicalResult verifyRegion(Region ®ion, bool isTopLevel); - LogicalResult verifyBlock(Block &block, bool isTopLevel); + LogicalResult verifyRegion(Region ®ion); + LogicalResult verifyBlock(Block &block); LogicalResult verifyOperation(Operation &op); /// Verify the dominance within the given IR unit. LogicalResult verifyDominance(Region ®ion); - LogicalResult verifyDominance(Block &block); LogicalResult verifyDominance(Operation &op); /// Emit an error for the given block. @@ -104,7 +106,7 @@ private: /// Verify the body of the given function. LogicalResult OperationVerifier::verify(Function &fn) { // Verify the body first. - if (failed(verifyRegion(fn.getBody(), /*isTopLevel=*/true))) + if (failed(verifyRegion(fn.getBody()))) return failure(); // Since everything looks structurally ok to this point, we do a dominance @@ -113,15 +115,34 @@ LogicalResult OperationVerifier::verify(Function &fn) { // resilient to malformed code. DominanceInfo theDomInfo(&fn); domInfo = &theDomInfo; - for (auto &block : fn) - if (failed(verifyDominance(block))) + if (failed(verifyDominance(fn.getBody()))) + return failure(); + + domInfo = nullptr; + return success(); +} + +/// Verify the given operation. +LogicalResult OperationVerifier::verify(Operation &op) { + // Verify the operation first. + if (failed(verifyOperation(op))) + return failure(); + + // Since everything looks structurally ok to this point, we do a dominance + // check for any nested regions. We do this as a second pass since malformed + // CFG's can cause dominator analysis constructure to crash and we want the + // verifier to be resilient to malformed code. + DominanceInfo theDomInfo(&op); + domInfo = &theDomInfo; + for (auto ®ion : op.getRegions()) + if (failed(verifyDominance(region))) return failure(); domInfo = nullptr; return success(); } -LogicalResult OperationVerifier::verifyRegion(Region ®ion, bool isTopLevel) { +LogicalResult OperationVerifier::verifyRegion(Region ®ion) { if (region.empty()) return success(); @@ -133,12 +154,12 @@ LogicalResult OperationVerifier::verifyRegion(Region ®ion, bool isTopLevel) { // Verify each of the blocks within the region. for (auto &block : region) - if (failed(verifyBlock(block, isTopLevel))) + if (failed(verifyBlock(block))) return failure(); return success(); } -LogicalResult OperationVerifier::verifyBlock(Block &block, bool isTopLevel) { +LogicalResult OperationVerifier::verifyBlock(Block &block) { for (auto *arg : block.getArguments()) if (arg->getOwner() != &block) return emitError(block, "block argument not owned by block"); @@ -200,7 +221,7 @@ LogicalResult OperationVerifier::verifyOperation(Operation &op) { // Verify that all child regions are ok. for (auto ®ion : op.getRegions()) - if (failed(verifyRegion(region, /*isTopLevel=*/false))) + if (failed(verifyRegion(region))) return failure(); // If this is a registered operation, there is nothing left to do. @@ -232,11 +253,12 @@ LogicalResult OperationVerifier::verifyOperation(Operation &op) { return success(); } -LogicalResult OperationVerifier::verifyDominance(Block &block) { +LogicalResult OperationVerifier::verifyDominance(Region ®ion) { // Verify the dominance of each of the held operations. - for (auto &op : block) - if (failed(verifyDominance(op))) - return failure(); + for (auto &block : region) + for (auto &op : block) + if (failed(verifyDominance(op))) + return failure(); return success(); } @@ -257,9 +279,8 @@ LogicalResult OperationVerifier::verifyDominance(Operation &op) { // Verify the dominance of each of the nested blocks within this operation. for (auto ®ion : op.getRegions()) - for (auto &block : region) - if (failed(verifyDominance(block))) - return failure(); + if (failed(verifyDominance(region))) + return failure(); return success(); } @@ -338,6 +359,13 @@ LogicalResult Function::verify() { /// Perform (potentially expensive) checks of invariants, used to detect /// compiler bugs. On error, this reports the error through the MLIRContext and /// returns failure. +LogicalResult Operation::verify() { + return OperationVerifier(getContext()).verify(*this); +} + +/// Perform (potentially expensive) checks of invariants, used to detect +/// compiler bugs. On error, this reports the error through the MLIRContext and +/// returns failure. LogicalResult Module::verify() { /// Check that each function is correct. for (auto &fn : *this)