Add a general Operation::verify that verifies an operation instance and the dominance...
authorRiver Riddle <riverriddle@google.com>
Tue, 11 Jun 2019 01:37:09 +0000 (18:37 -0700)
committerMehdi Amini <joker.eph@gmail.com>
Tue, 11 Jun 2019 17:13:28 +0000 (10:13 -0700)
PiperOrigin-RevId: 252529850

mlir/include/mlir/IR/Operation.h
mlir/lib/Analysis/Dominance.cpp
mlir/lib/Analysis/Verifier.cpp

index f974947..e354891 100644 (file)
@@ -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();
 
index 2c9ec00..954a01b 100644 (file)
@@ -106,8 +106,12 @@ bool DominanceInfoBase<IsPostDom>::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);
 }
 
index e1f6f28..9e722e4 100644 (file)
@@ -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 &region, bool isTopLevel);
-  LogicalResult verifyBlock(Block &block, bool isTopLevel);
+  LogicalResult verifyRegion(Region &region);
+  LogicalResult verifyBlock(Block &block);
   LogicalResult verifyOperation(Operation &op);
 
   /// Verify the dominance within the given IR unit.
   LogicalResult verifyDominance(Region &region);
-  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 &region : op.getRegions())
+    if (failed(verifyDominance(region)))
       return failure();
 
   domInfo = nullptr;
   return success();
 }
 
-LogicalResult OperationVerifier::verifyRegion(Region &region, bool isTopLevel) {
+LogicalResult OperationVerifier::verifyRegion(Region &region) {
   if (region.empty())
     return success();
 
@@ -133,12 +154,12 @@ LogicalResult OperationVerifier::verifyRegion(Region &region, 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 &region : 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 &region) {
   // 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 &region : 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)