Revert "[Verifier] Speed up and parallelize dominance checking. NFC"

This reverts commit 08664d005c, which according to
https://reviews.llvm.org/D103373 was pushed accidentally, and I believe it
causes timeouts in some internal mlir tests.
This commit is contained in:
Alexander Kornienko 2021-06-10 09:58:05 +02:00
parent 99653702fd
commit ad6a84f82c
2 changed files with 33 additions and 82 deletions

View File

@ -35,7 +35,7 @@ class DominanceInfoBase {
using DomTree = llvm::DominatorTreeBase<Block, IsPostDom>; using DomTree = llvm::DominatorTreeBase<Block, IsPostDom>;
public: public:
DominanceInfoBase(Operation *op = nullptr) {} DominanceInfoBase(Operation *op) {}
DominanceInfoBase(DominanceInfoBase &&) = default; DominanceInfoBase(DominanceInfoBase &&) = default;
DominanceInfoBase &operator=(DominanceInfoBase &&) = default; DominanceInfoBase &operator=(DominanceInfoBase &&) = default;
~DominanceInfoBase(); ~DominanceInfoBase();

View File

@ -31,8 +31,9 @@
#include "mlir/IR/Operation.h" #include "mlir/IR/Operation.h"
#include "mlir/IR/RegionKindInterface.h" #include "mlir/IR/RegionKindInterface.h"
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/Support/Parallel.h" #include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
#include <atomic> #include <atomic>
@ -42,8 +43,7 @@ namespace {
/// This class encapsulates all the state used to verify an operation region. /// This class encapsulates all the state used to verify an operation region.
class OperationVerifier { class OperationVerifier {
public: public:
explicit OperationVerifier(MLIRContext *context) explicit OperationVerifier() {}
: parallelismEnabled(context->isMultithreadingEnabled()) {}
/// Verify the given operation. /// Verify the given operation.
LogicalResult verifyOpAndDominance(Operation &op); LogicalResult verifyOpAndDominance(Operation &op);
@ -56,8 +56,7 @@ private:
/// Verify the dominance property of regions contained within the given /// Verify the dominance property of regions contained within the given
/// Operation. /// Operation.
LogicalResult verifyDominanceOfContainedRegions(Operation &op, LogicalResult verifyDominanceOfContainedRegions(Operation &op);
DominanceInfo &domInfo);
/// Emit an error for the given block. /// Emit an error for the given block.
InFlightDiagnostic emitError(Block &bb, const Twine &message) { InFlightDiagnostic emitError(Block &bb, const Twine &message) {
@ -69,8 +68,8 @@ private:
return mlir::emitError(bb.getParent()->getLoc(), message); return mlir::emitError(bb.getParent()->getLoc(), message);
} }
/// This is true if parallelism is enabled on the MLIRContext. /// Dominance information for this operation, when checking dominance.
const bool parallelismEnabled; DominanceInfo *domInfo = nullptr;
}; };
} // end anonymous namespace } // end anonymous namespace
@ -84,11 +83,12 @@ LogicalResult OperationVerifier::verifyOpAndDominance(Operation &op) {
// check for any nested regions. We do this as a second pass since malformed // 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 // CFG's can cause dominator analysis constructure to crash and we want the
// verifier to be resilient to malformed code. // verifier to be resilient to malformed code.
if (op.getNumRegions() != 0) { DominanceInfo theDomInfo(&op);
DominanceInfo domInfo; domInfo = &theDomInfo;
if (failed(verifyDominanceOfContainedRegions(op, /*domInfo*/ domInfo))) if (failed(verifyDominanceOfContainedRegions(op)))
return failure(); return failure();
}
domInfo = nullptr;
return success(); return success();
} }
@ -301,83 +301,34 @@ static void diagnoseInvalidOperandDominance(Operation &op, unsigned operandNo) {
note << " neither in a parent nor in a child region)"; note << " neither in a parent nor in a child region)";
} }
/// Verify the dominance of each of the nested blocks within the given /// Verify the dominance of each of the nested blocks within the given operation
/// operation. domInfo may be present or absent (null), depending on whether
/// the caller computed it for a higher level.
LogicalResult LogicalResult
OperationVerifier::verifyDominanceOfContainedRegions(Operation &opWithRegions, OperationVerifier::verifyDominanceOfContainedRegions(Operation &op) {
DominanceInfo &domInfo) { for (Region &region : op.getRegions()) {
// This vector keeps track of ops that have regions which should be checked // Verify the dominance of each of the held operations.
// in parallel.
SmallVector<Operation *> opsWithRegionsToCheckInParallel;
// Get information about the requirements on the regions in this op.
for (Region &region : opWithRegions.getRegions()) {
for (Block &block : region) { for (Block &block : region) {
// Dominance is only meaningful inside reachable blocks. // Dominance is only meaningful inside reachable blocks.
bool isReachable = domInfo.isReachableFromEntry(&block); bool isReachable = domInfo->isReachableFromEntry(&block);
// Check each operation in this block, and any operations in regions
// that these operations contain.
opsWithRegionsToCheckInParallel.clear();
for (Operation &op : block) { for (Operation &op : block) {
if (isReachable) { if (isReachable) {
// Check that operands properly dominate this use. // Check that operands properly dominate this use.
for (auto &operand : op.getOpOperands()) { for (unsigned operandNo = 0, e = op.getNumOperands(); operandNo != e;
// If the operand doesn't dominate the user, then emit an error. ++operandNo) {
if (!domInfo.properlyDominates(operand.get(), &op)) { if (domInfo->properlyDominates(op.getOperand(operandNo), &op))
diagnoseInvalidOperandDominance(op, operand.getOperandNumber()); continue;
return failure();
} diagnoseInvalidOperandDominance(op, operandNo);
return failure();
} }
} }
// If this operation has any regions, we need to recursively verify // Recursively verify dominance within each operation in the
// dominance of the ops within it. // block, even if the block itself is not reachable, or we are in
if (op.getNumRegions() == 0) // a region which doesn't respect dominance.
continue; if (op.getNumRegions() != 0)
if (failed(verifyDominanceOfContainedRegions(op)))
// If this is a non-isolated region (e.g. an affine for loop), pass down
// the current dominator information.
if (!op.hasTrait<OpTrait::IsIsolatedFromAbove>()) {
if (failed(verifyDominanceOfContainedRegions(op, domInfo)))
return failure(); return failure();
} else if (parallelismEnabled) {
// If this is an IsolatedFromAbove op and parallelism is enabled, then
// enqueue this for processing later.
opsWithRegionsToCheckInParallel.push_back(&op);
} else {
// If not, just verify inline with a local dom scope.
DominanceInfo localDomInfo;
if (failed(verifyDominanceOfContainedRegions(op, localDomInfo)))
return failure();
}
}
// If we have multiple parallelizable subregions, check them in parallel.
if (opsWithRegionsToCheckInParallel.size() == 1) {
// Each isolated operation gets its own dom info.
Operation *op = opsWithRegionsToCheckInParallel[0];
DominanceInfo localDomInfo;
if (failed(verifyDominanceOfContainedRegions(*op, localDomInfo)))
return failure();
} else if (!opsWithRegionsToCheckInParallel.empty()) {
ParallelDiagnosticHandler handler(opWithRegions.getContext());
std::atomic<bool> passFailed(false);
llvm::parallelForEachN(
0, opsWithRegionsToCheckInParallel.size(), [&](size_t opIdx) {
handler.setOrderIDForThread(opIdx);
Operation *op = opsWithRegionsToCheckInParallel[opIdx];
// Each isolated operation gets its own dom info.
DominanceInfo localDomInfo;
if (failed(verifyDominanceOfContainedRegions(*op, localDomInfo)))
passFailed = true;
handler.eraseOrderIDForThread();
});
if (passFailed)
return failure();
} }
} }
} }
@ -389,8 +340,8 @@ OperationVerifier::verifyDominanceOfContainedRegions(Operation &opWithRegions,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Perform (potentially expensive) checks of invariants, used to detect /// Perform (potentially expensive) checks of invariants, used to detect
/// compiler bugs. On error, this reports the error through the MLIRContext /// compiler bugs. On error, this reports the error through the MLIRContext and
/// and returns failure. /// returns failure.
LogicalResult mlir::verify(Operation *op) { LogicalResult mlir::verify(Operation *op) {
return OperationVerifier(op->getContext()).verifyOpAndDominance(*op); return OperationVerifier().verifyOpAndDominance(*op);
} }