31
31
#include " mlir/IR/Operation.h"
32
32
#include " mlir/IR/RegionKindInterface.h"
33
33
#include " llvm/ADT/StringMap.h"
34
- #include " llvm/Support/Parallel .h"
34
+ #include " llvm/Support/FormatVariadic .h"
35
35
#include " llvm/Support/PrettyStackTrace.h"
36
+ #include " llvm/Support/Regex.h"
36
37
37
38
#include < atomic>
38
39
@@ -42,8 +43,7 @@ namespace {
42
43
// / This class encapsulates all the state used to verify an operation region.
43
44
class OperationVerifier {
44
45
public:
45
- explicit OperationVerifier (MLIRContext *context)
46
- : parallelismEnabled(context->isMultithreadingEnabled ()) {}
46
+ explicit OperationVerifier () {}
47
47
48
48
// / Verify the given operation.
49
49
LogicalResult verifyOpAndDominance (Operation &op);
@@ -56,8 +56,7 @@ class OperationVerifier {
56
56
57
57
// / Verify the dominance property of regions contained within the given
58
58
// / Operation.
59
- LogicalResult verifyDominanceOfContainedRegions (Operation &op,
60
- DominanceInfo &domInfo);
59
+ LogicalResult verifyDominanceOfContainedRegions (Operation &op);
61
60
62
61
// / Emit an error for the given block.
63
62
InFlightDiagnostic emitError (Block &bb, const Twine &message) {
@@ -69,8 +68,8 @@ class OperationVerifier {
69
68
return mlir::emitError (bb.getParent ()->getLoc (), message);
70
69
}
71
70
72
- // / This is true if parallelism is enabled on the MLIRContext .
73
- const bool parallelismEnabled ;
71
+ // / Dominance information for this operation, when checking dominance .
72
+ DominanceInfo *domInfo = nullptr ;
74
73
};
75
74
} // end anonymous namespace
76
75
@@ -84,11 +83,12 @@ LogicalResult OperationVerifier::verifyOpAndDominance(Operation &op) {
84
83
// check for any nested regions. We do this as a second pass since malformed
85
84
// CFG's can cause dominator analysis constructure to crash and we want the
86
85
// verifier to be resilient to malformed code.
87
- if (op.getNumRegions () != 0 ) {
88
- DominanceInfo domInfo;
89
- if (failed (verifyDominanceOfContainedRegions (op, /* domInfo*/ domInfo)))
90
- return failure ();
91
- }
86
+ DominanceInfo theDomInfo (&op);
87
+ domInfo = &theDomInfo;
88
+ if (failed (verifyDominanceOfContainedRegions (op)))
89
+ return failure ();
90
+
91
+ domInfo = nullptr ;
92
92
return success ();
93
93
}
94
94
@@ -301,83 +301,34 @@ static void diagnoseInvalidOperandDominance(Operation &op, unsigned operandNo) {
301
301
note << " neither in a parent nor in a child region)" ;
302
302
}
303
303
304
- // / Verify the dominance of each of the nested blocks within the given
305
- // / operation. domInfo may be present or absent (null), depending on whether
306
- // / the caller computed it for a higher level.
304
+ // / Verify the dominance of each of the nested blocks within the given operation
307
305
LogicalResult
308
- OperationVerifier::verifyDominanceOfContainedRegions (Operation &opWithRegions,
309
- DominanceInfo &domInfo) {
310
- // This vector keeps track of ops that have regions which should be checked
311
- // in parallel.
312
- SmallVector<Operation *> opsWithRegionsToCheckInParallel;
313
-
314
- // Get information about the requirements on the regions in this op.
315
- for (Region ®ion : opWithRegions.getRegions ()) {
306
+ OperationVerifier::verifyDominanceOfContainedRegions (Operation &op) {
307
+ for (Region ®ion : op.getRegions ()) {
308
+ // Verify the dominance of each of the held operations.
316
309
for (Block &block : region) {
317
310
// Dominance is only meaningful inside reachable blocks.
318
- bool isReachable = domInfo.isReachableFromEntry (&block);
319
-
320
- // Check each operation in this block, and any operations in regions
321
- // that these operations contain.
322
- opsWithRegionsToCheckInParallel.clear ();
311
+ bool isReachable = domInfo->isReachableFromEntry (&block);
323
312
324
313
for (Operation &op : block) {
325
314
if (isReachable) {
326
315
// Check that operands properly dominate this use.
327
- for (auto &operand : op.getOpOperands ()) {
328
- // If the operand doesn't dominate the user, then emit an error.
329
- if (!domInfo.properlyDominates (operand.get (), &op)) {
330
- diagnoseInvalidOperandDominance (op, operand.getOperandNumber ());
331
- return failure ();
332
- }
333
- }
334
- }
316
+ for (unsigned operandNo = 0 , e = op.getNumOperands (); operandNo != e;
317
+ ++operandNo) {
318
+ if (domInfo->properlyDominates (op.getOperand (operandNo), &op))
319
+ continue ;
335
320
336
- // If this operation has any regions, we need to recursively verify
337
- // dominance of the ops within it.
338
- if (op.getNumRegions () == 0 )
339
- continue ;
340
-
341
- // If this is a non-isolated region (e.g. an affine for loop), pass down
342
- // the current dominator information.
343
- if (!op.hasTrait <OpTrait::IsIsolatedFromAbove>()) {
344
- if (failed (verifyDominanceOfContainedRegions (op, domInfo)))
345
- return failure ();
346
- } else if (parallelismEnabled) {
347
- // If this is an IsolatedFromAbove op and parallelism is enabled, then
348
- // enqueue this for processing later.
349
- opsWithRegionsToCheckInParallel.push_back (&op);
350
- } else {
351
- // If not, just verify inline with a local dom scope.
352
- DominanceInfo localDomInfo;
353
- if (failed (verifyDominanceOfContainedRegions (op, localDomInfo)))
321
+ diagnoseInvalidOperandDominance (op, operandNo);
354
322
return failure ();
323
+ }
355
324
}
356
- }
357
325
358
- // If we have multiple parallelizable subregions, check them in parallel.
359
- if (opsWithRegionsToCheckInParallel.size () == 1 ) {
360
- // Each isolated operation gets its own dom info.
361
- Operation *op = opsWithRegionsToCheckInParallel[0 ];
362
- DominanceInfo localDomInfo;
363
- if (failed (verifyDominanceOfContainedRegions (*op, localDomInfo)))
364
- return failure ();
365
- } else if (!opsWithRegionsToCheckInParallel.empty ()) {
366
- ParallelDiagnosticHandler handler (opWithRegions.getContext ());
367
- std::atomic<bool > passFailed (false );
368
- llvm::parallelForEachN (
369
- 0 , opsWithRegionsToCheckInParallel.size (), [&](size_t opIdx) {
370
- handler.setOrderIDForThread (opIdx);
371
- Operation *op = opsWithRegionsToCheckInParallel[opIdx];
372
-
373
- // Each isolated operation gets its own dom info.
374
- DominanceInfo localDomInfo;
375
- if (failed (verifyDominanceOfContainedRegions (*op, localDomInfo)))
376
- passFailed = true ;
377
- handler.eraseOrderIDForThread ();
378
- });
379
- if (passFailed)
380
- return failure ();
326
+ // Recursively verify dominance within each operation in the
327
+ // block, even if the block itself is not reachable, or we are in
328
+ // a region which doesn't respect dominance.
329
+ if (op.getNumRegions () != 0 )
330
+ if (failed (verifyDominanceOfContainedRegions (op)))
331
+ return failure ();
381
332
}
382
333
}
383
334
}
@@ -389,8 +340,8 @@ OperationVerifier::verifyDominanceOfContainedRegions(Operation &opWithRegions,
389
340
// ===----------------------------------------------------------------------===//
390
341
391
342
// / Perform (potentially expensive) checks of invariants, used to detect
392
- // / compiler bugs. On error, this reports the error through the MLIRContext
393
- // / and returns failure.
343
+ // / compiler bugs. On error, this reports the error through the MLIRContext and
344
+ // / returns failure.
394
345
LogicalResult mlir::verify (Operation *op) {
395
- return OperationVerifier (op-> getContext () ).verifyOpAndDominance (*op);
346
+ return OperationVerifier ().verifyOpAndDominance (*op);
396
347
}
0 commit comments